Nasıl PHP hızlı olun: String Yaratılış Hayır Maliyet mı?

6 Cevap php

In this question bir kod biraz sundu ve soru soran değişkenlerin kullanımını da ortadan kaldırarak daha hızlı yapmak istiyor. O yanlış yerde arıyor, ama çok da bilmek benden olacak gibi geliyor bana. İşte kod

while ($item = current($data))
{
    echo '<ATTR>',$item, '</ATTR>', "\n";
    next($data);
}

Satır işlenir daha her hat ve her zaman bir kez daha - - Onlara (hem hız ve bellek açısından ilişkili bir maliyeti olurdu dizeleri <ATTR> vb rekreasyon gibi geliyor bana .) Ya da belki önce döngü değişkenleri içine dizeleri koyarak değil herhangi bir ceza var o kadar yeterince akıllı PHP işlemci?

Ben her durumda netlik ve merkezileşme değişkenler kullanabilirsiniz, ama: is there a cost associated with using variables, not using variables, or what? (diğer similar diller için cevap vermek isteyen herkes çekinmeyin.)

6 Cevap

Eğer gerçekten mikro-optimize etmek bu şekilde isterseniz (ben alakalı ya da yararlı, btw olduğunu sanmıyorum - ama eğlenceli ^ ^ anlıyorum), adlı bir PHP uzantısı bir göz olabilir {[(0) }]

Bu bir PHP komut dosyası için oluşturulan bytecode almayı sağlar.

Sonra senaryoyu başlatmak için, komut satırında, bu gibi bir komut kullanmanız gerekir:

php -dextension=vld.so -dvld.active=1 tests/temp/temp.php

Örneğin, bu komut ile:

$data = array('a', 'b', 'c', 'd');
while ($item = current($data))
{
    echo '<ATTR>',$item, '</ATTR>', "\n";
    next($data);
}

Bu baytkodu dökümü alacak:

line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   8     0  EXT_STMT
         1  INIT_ARRAY                                       ~0      'a'
         2  ADD_ARRAY_ELEMENT                                ~0      'b'
         3  ADD_ARRAY_ELEMENT                                ~0      'c'
         4  ADD_ARRAY_ELEMENT                                ~0      'd'
         5  ASSIGN                                                   !0, ~0
   9     6  EXT_STMT
         7  EXT_FCALL_BEGIN
         8  SEND_REF                                                 !0
         9  DO_FCALL                                      1          'current'
        10  EXT_FCALL_END
        11  ASSIGN                                           $3      !1, $2
        12  JMPZ                                                     $3, ->24
  11    13  EXT_STMT
        14  ECHO                                                     '%3CATTR%3E'
        15  ECHO                                                     !1
        16  ECHO                                                     '%3C%2FATTR%3E'
        17  ECHO                                                     '%0A'
  12    18  EXT_STMT
        19  EXT_FCALL_BEGIN
        20  SEND_REF                                                 !0
        21  DO_FCALL                                      1          'next'
        22  EXT_FCALL_END
  13    23  JMP                                                      ->7
  37    24  RETURN                                                   1
        25* ZEND_HANDLE_EXCEPTION

Ve bu komut ile:

$data = array('a', 'b', 'c', 'd');
while ($item = current($data))
{
    echo "<ATTR>$item</ATTR>\n";
    next($data);
}

Alırsınız:

line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
  19     0  EXT_STMT
         1  INIT_ARRAY                                       ~0      'a'
         2  ADD_ARRAY_ELEMENT                                ~0      'b'
         3  ADD_ARRAY_ELEMENT                                ~0      'c'
         4  ADD_ARRAY_ELEMENT                                ~0      'd'
         5  ASSIGN                                                   !0, ~0
  20     6  EXT_STMT
         7  EXT_FCALL_BEGIN
         8  SEND_REF                                                 !0
         9  DO_FCALL                                      1          'current'
        10  EXT_FCALL_END
        11  ASSIGN                                           $3      !1, $2
        12  JMPZ                                                     $3, ->25
  22    13  EXT_STMT
        14  INIT_STRING                                      ~4
        15  ADD_STRING                                       ~4      ~4, '%3CATTR%3E'
        16  ADD_VAR                                          ~4      ~4, !1
        17  ADD_STRING                                       ~4      ~4, '%3C%2FATTR%3E%0A'
        18  ECHO                                                     ~4
  23    19  EXT_STMT
        20  EXT_FCALL_BEGIN
        21  SEND_REF                                                 !0
        22  DO_FCALL                                      1          'next'
        23  EXT_FCALL_END
  24    24  JMP                                                      ->7
  39    25  RETURN                                                   1
        26* ZEND_HANDLE_EXCEPTION

(This ouput is with PHP 5.2.6, which is the default on Ubuntu Jaunty)

Sonunda, muhtemelen orada bu kadar farklılıklar değildir ve göreceksiniz genellikle gerçekten sadece micro-optimizasyon ^ ^ var

Ne daha ilginç olabilir PHP sürümleri arasında farklılıklar bakmak: bazı işlemler, örneğin, PHP 5.1 ve 5.2 arasında optimize edilmiş olduğunu gördük olabilir.

Detaylı bilgi için, ayrıca Understanding Opcodes de bir göz atabilirsiniz

Eğlenin!

EDIT: Başka bir test ekleme:

Bu kod ile:

$attr_open = '<ATTR>';
$attr_close = '</ATTR>';
$eol = "\n";

$data = array('a', 'b', 'c', 'd');
while ($item = current($data))
{
    echo $attr_open, $item, $attr_close, $eol;
    next($data);
}

Alacağınız:

line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
  19     0  EXT_STMT
         1  ASSIGN                                                   !0, '%3CATTR%3E'
  20     2  EXT_STMT
         3  ASSIGN                                                   !1, '%3C%2FATTR%3E'
  21     4  EXT_STMT
         5  ASSIGN                                                   !2, '%0A'
  23     6  EXT_STMT
         7  INIT_ARRAY                                       ~3      'a'
         8  ADD_ARRAY_ELEMENT                                ~3      'b'
         9  ADD_ARRAY_ELEMENT                                ~3      'c'
        10  ADD_ARRAY_ELEMENT                                ~3      'd'
        11  ASSIGN                                                   !3, ~3
  24    12  EXT_STMT
        13  EXT_FCALL_BEGIN
        14  SEND_REF                                                 !3
        15  DO_FCALL                                      1          'current'
        16  EXT_FCALL_END
        17  ASSIGN                                           $6      !4, $5
        18  JMPZ                                                     $6, ->30
  26    19  EXT_STMT
        20  ECHO                                                     !0
        21  ECHO                                                     !4
        22  ECHO                                                     !1
        23  ECHO                                                     !2
  27    24  EXT_STMT
        25  EXT_FCALL_BEGIN
        26  SEND_REF                                                 !3
        27  DO_FCALL                                      1          'next'
        28  EXT_FCALL_END
  28    29  JMP                                                      ->13
  43    30  RETURN                                                   1
        31* ZEND_HANDLE_EXCEPTION

Ve, bu bir (concatenations yerine ',') ile:

$attr_open = '<ATTR>';
$attr_close = '</ATTR>';
$eol = "\n";

$data = array('a', 'b', 'c', 'd');
while ($item = current($data))
{
    echo $attr_open . $item . $attr_close . $eol;
    next($data);
}

olsun:

line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
  19     0  EXT_STMT
         1  ASSIGN                                                   !0, '%3CATTR%3E'
  20     2  EXT_STMT
         3  ASSIGN                                                   !1, '%3C%2FATTR%3E'
  21     4  EXT_STMT
         5  ASSIGN                                                   !2, '%0A'
  23     6  EXT_STMT
         7  INIT_ARRAY                                       ~3      'a'
         8  ADD_ARRAY_ELEMENT                                ~3      'b'
         9  ADD_ARRAY_ELEMENT                                ~3      'c'
        10  ADD_ARRAY_ELEMENT                                ~3      'd'
        11  ASSIGN                                                   !3, ~3
  24    12  EXT_STMT
        13  EXT_FCALL_BEGIN
        14  SEND_REF                                                 !3
        15  DO_FCALL                                      1          'current'
        16  EXT_FCALL_END
        17  ASSIGN                                           $6      !4, $5
        18  JMPZ                                                     $6, ->30
  26    19  EXT_STMT
        20  CONCAT                                           ~7      !0, !4
        21  CONCAT                                           ~8      ~7, !1
        22  CONCAT                                           ~9      ~8, !2
        23  ECHO                                                     ~9
  27    24  EXT_STMT
        25  EXT_FCALL_BEGIN
        26  SEND_REF                                                 !3
        27  DO_FCALL                                      1          'next'
        28  EXT_FCALL_END
  28    29  JMP                                                      ->13
  43    30  RETURN                                                   1
        31* ZEND_HANDLE_EXCEPTION

Yani, çok fazla bir fark asla ^ ^

Hey çocuklar burada ilginç biri, benim ilk testler yerine, PHP her tekrarında ile ayrıştırma bir değişken içine satır karakterini saklayarak hızlı olduğunu gösteriyor ... aşağıya bakın

$nl = "\n";
while ($item = current($data))
{
    echo '<ATTR>',$item, '</ATTR>',$nl;
    next($data);
}

Döngünün dışındaki değişkenlere taşırken vs döngü içinde string kullanarak ölçülebilir bir farklılık olduğu görülmektedir. Ben birlikte bu test etmek için aşağıdaki basit komut attı:

$length = 100000;
$data = array();
$totals = array();

for ($i = 0; $i < $length; $i++) {
    $data[] = rand(1,1000);
}

$start = xdebug\_time\_index();
while ($item = current($data))
{
    echo '<ATTR>',$item,'</ATTR>',PHP_EOL;
    next($data);
}
$end = xdebug\_time\_index();
$total = $end - $start;
$totals["Warmup:"] = $total;

reset($data);
$start = xdebug\_time\_index();
while ($item = current($data))
{
    echo '<ATTR>',$item,'</ATTR>',PHP_EOL;
    next($data);
}
$end = xdebug\_time\_index();
$total = $end - $start;
$totals["First:"] = $total;

reset($data);
$startTag = '<ATTR>';
$endTag = '</ATTR>';
$start = xdebug\_time\_index();
while ($item = current($data))
{
    echo $startTag,$item,$endTag,PHP_EOL;
    next($data);
}
$end = xdebug\_time\_index();
$total = $end - $start;
$totals["Second:"] = $total;

foreach ($totals as $label => $data) {
    echo $label,' ', $data,PHP_EOL;
}

Ben bu birkaç kez koştu ve farklı yöntemler arasında belirgin bir fark gördüm. Aslında, bazen warmup üç hızlı oldu.

Bu gibi şeyleri microoptimize çalışırken gerçekten daha sık gerçek kodu daha üzerinde makinenin performansını ölçmek sonunda. Not, size PHP_EOL yerine \n veya böyle içeren bir değişken tanımlayarak kullanmak isteyebilirsiniz.

Aslında bu, muhtemelen hızlı uygulamasıdır. Bir dize için tüm CONCAT deneyebilirsiniz ama concatı operasyonların tüm oldukça pahalıdır.

Her şeyin bir maliyeti vardır. Amaç bu maliyet mümkün olduğunca en aza indirmektir.

Onun performansı hakkında bilgi için birleştirme çek this Kaynak düşünmeye olsaydı. Olduğu gibi-kod bırakmak en iyisi.

Eğer gerçekten bu hızlandırmak istiyorsanız, bunun yerine kullanın:

ob_start();
while ($item = current($data))
{
    echo '<ATTR>',$item, '</ATTR>', "\n";
    next($data);
}

Herhangi bir mikro-optimizasyon can daha fazla kodunuzu hızlandırır müşteri, daha verimli çıktı tamponlama basması içeriği.

PHP kodu geldiğinde bir kenara, benim deneyim mikro-optimizasyon bir işe yaramaz bir çabadır. Ben bir performans sorunu belirli bir birleştirme veya değişken bildirim yöntemi akıllı kullanımı ile çözülür olsun görmedim. Gerçek çözümler tasarım veya mimarlık ya da daha az karmaşık algoritmaların kullanımı değişikliği dahil etmek eğilimindedir.