php Dize birleştirme, Performans

10 Cevap php

Java ve C # gibi dillerde, dizeleri iletmenin ve bir anda bir dize bir karakter oluşturmak için hesaplama pahalı olabilir. Dilde, örneğin C # System.Text.StringBuilder ve Java gibi bu maliyeti azaltmak için kütüphane sınıfları vardır dedi java.lang.StringBuilder.

Php (4 veya 5; ben de ilgileniyorum) mı bu sınırlama paylaşmak? Bu durumda, benzer bir soruna çözüm mevcuttur?

10 Cevap

Dizeleri kesilebilir beri Hayır, PHP StringBuilder sınıfının hiçbir türü yoktur.

Söyleniyor, ne yaptığınızı bağlı bir dize bina farklı yolları vardır.

eko, örneğin, çıkış için virgülle ayrılmış belirteçleri kabul eder.

// This...
echo 'one', 'two';

// Is the same as this
echo 'one';
echo 'two';

Bunun anlamı çıktı yavaş olacağını aslında bitiştirmesi kullanmadan karmaşık bir dize, can ki

// This...
echo 'one', 'two';

// Is faster than this...
echo 'one' . 'two';

Eğer bir değişken bu çıkış yakalamak gerekiyorsa, output buffering functions ile yapabilirsiniz.

Ayrıca, PHP'nin dizi performansı gerçekten çok iyi. Eğer değerleri virgülle ayrılmış listesi gibi bir şey yapmak istiyorsanız, sadece çöktüğünü kullanın ()

$values = array( 'one', 'two', 'three' );
$valueList = implode( ', ', $values );

Son olarak, PHP's string type ile yakından tanımak ve farklı sınırlayıcılarını ve her etkileri olduğundan emin olun.

PHP dizeleri kesilebilir. Bu gibi özel karakterleri değiştirebilirsiniz:

$string = 'abc';
$string[2] = 'a'; // $string equals 'aba'
$string[3] = 'd'; // $string equals 'abad'
$string[5] = 'e'; // $string equals 'abad e' (fills character(s) in between with spaces)

Ve böyle bir dizeye karakterleri ekleyebilirsiniz:

$string .= 'a';

Ben bu merak, bu yüzden bir test koştum. Ben aşağıdaki kod kullanılır:

<?php
ini_set('memory_limit', '1024M');
define ('CORE_PATH', '/Users/foo');
define ('DS', DIRECTORY_SEPARATOR);

$numtests = 1000000;

function test1($numtests)
{
    $CORE_PATH = '/Users/foo';
    $DS = DIRECTORY_SEPARATOR;
    $a = array();

    $startmem = memory_get_usage();
    $a_start = microtime(true);
    for ($i = 0; $i < $numtests; $i++) {
        $a[] = sprintf('%s%sDesktop%sjunk.php', $CORE_PATH, $DS, $DS);
    }
    $a_end = microtime(true);
    $a_mem = memory_get_usage();

    $timeused = $a_end - $a_start;
    $memused = $a_mem - $startmem;

    echo "TEST 1: sprintf()\n";
    echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}

function test2($numtests)
{
    $CORE_PATH = '/Users/shigh';
    $DS = DIRECTORY_SEPARATOR;
    $a = array();

    $startmem = memory_get_usage();
    $a_start = microtime(true);
    for ($i = 0; $i < $numtests; $i++) {
        $a[] = $CORE_PATH . $DS . 'Desktop' . $DS . 'junk.php';
    }
    $a_end = microtime(true);
    $a_mem = memory_get_usage();

    $timeused = $a_end - $a_start;
    $memused = $a_mem - $startmem;

    echo "TEST 2: Concatenation\n";
    echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}

function test3($numtests)
{
    $CORE_PATH = '/Users/shigh';
    $DS = DIRECTORY_SEPARATOR;
    $a = array();

    $startmem = memory_get_usage();
    $a_start = microtime(true);
    for ($i = 0; $i < $numtests; $i++) {
        ob_start();
        echo $CORE_PATH,$DS,'Desktop',$DS,'junk.php';
        $aa = ob_get_contents();
        ob_end_clean();
        $a[] = $aa;
    }
    $a_end = microtime(true);
    $a_mem = memory_get_usage();

    $timeused = $a_end - $a_start;
    $memused = $a_mem - $startmem;

    echo "TEST 3: Buffering Method\n";
    echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}

function test4($numtests)
{
    $CORE_PATH = '/Users/shigh';
    $DS = DIRECTORY_SEPARATOR;
    $a = array();

    $startmem = memory_get_usage();
    $a_start = microtime(true);
    for ($i = 0; $i < $numtests; $i++) {
        $a[] = "{$CORE_PATH}{$DS}Desktop{$DS}junk.php";
    }
    $a_end = microtime(true);
    $a_mem = memory_get_usage();

    $timeused = $a_end - $a_start;
    $memused = $a_mem - $startmem;

    echo "TEST 4: Braced in-line variables\n";
    echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}

function test5($numtests)
{
    $a = array();

    $startmem = memory_get_usage();
    $a_start = microtime(true);
    for ($i = 0; $i < $numtests; $i++) {
        $CORE_PATH = CORE_PATH;
        $DS = DIRECTORY_SEPARATOR;
        $a[] = "{$CORE_PATH}{$DS}Desktop{$DS}junk.php";
    }
    $a_end = microtime(true);
    $a_mem = memory_get_usage();

    $timeused = $a_end - $a_start;
    $memused = $a_mem - $startmem;

    echo "TEST 5: Braced inline variables with loop-level assignments\n";
    echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}

test1($numtests);
test2($numtests);
test3($numtests);
test4($numtests);
test5($numtests);

... And got the following results. Image attached. Clearly, sprintf is the least efficient way to do it, both in terms of time and memory consumption. EDIT: view image in another tab unless you have eagle vision. enter image description here

Evet. Onlar yapmak. Birlikte dizeleri çift echo istiyorsanız, örneğin, kullanmak için

echo str1,str2,str3 

yerine

echo str1.str2.str3 
to get it a little faster.

Eğer birleştirilecek dizeleri gerekmez Öncelikle, bunu yapmayın: her zaman yapmak daha hızlı olacak

echo $a,$b,$c;

göre

echo $a . $b . $c;

Ancak, en azından PHP5, dize birleştirme verilen bir dize tek bir referans var, özellikle eğer gerçekten oldukça hızlı. Ben tercüman dahili bir StringBuilder-benzeri tekniğini kullanır sanırım.

PHP dizeleri içinde değişken değerleri yerleştirerek ediyorsanız, ben (- Ben ne olduğunu hatırlamıyorum ki bu resmi adı değil) sıralı değişken dahil kullanmak biraz daha hızlı olduğunu anlamak

$aString = 'oranges';
$compareString = "comparing apples to {$aString}!";
echo $compareString
   comparing apples to oranges!

Çalışmak için çift tırnak içinde olmalıdır. Ayrıca (dizi üyeleri için çalışıyor yani

echo "You requested page id {$_POST['id']}";

)

no such limitation in php, php can concatenate strng with the dot(.) operator

$a="hello ";
$b="world";
echo $a.$b;

çıkışlar "merhaba dünya"

Eğer bir zamanlanmış karşılaştırma yaptığınızda, farklılıklar çok alakalı değildir o kadar küçüktür. Okumak ve anlamak için kod kolaylaştırır seçim gitmek için çünkü daha yapacak.

Senin bahsettiğini biliyorum. Ben sadece Java StringBuilder sınıfı taklit etmek için bu basit bir sınıf yarattı.

class StringBuilder {

private $str = array();

public function __construct() { }

public function append($str) {
    $this->str[] = $str;
}

public function toString() {
    return implode($this->str);
}

}

StringBuilder analog PHP gerekli değildir.

Basit birkaç test yaptı:

PHP:

$iterations = 10000;
$stringToAppend = 'TESTSTR';
$timer = new Timer(); // based on microtime()
$s = '';
for($i = 0; $i < $iterations; $i++)
{
    $s .= ($i . $stringToAppend);
}
$timer->VarDumpCurrentTimerValue();

$timer->Restart();

// Used purlogic's implementation.
// I tried other implementations, but they are not faster
$sb = new StringBuilder(); 

for($i = 0; $i < $iterations; $i++)
{
    $sb->append($i);
    $sb->append($stringToAppend);
}
$ss = $sb->toString();
$timer->VarDumpCurrentTimerValue();

C # (NET 4.0.)

const int iterations = 10000;
const string stringToAppend = "TESTSTR";
string s = "";
var timer = new Timer(); // based on StopWatch

for(int i = 0; i < iterations; i++)
{
    s += (i + stringToAppend);
}

timer.ShowCurrentTimerValue();

timer.Restart();

var sb = new StringBuilder();

for(int i = 0; i < iterations; i++)
{
    sb.Append(i);
    sb.Append(stringToAppend);
}

string ss = sb.ToString();

timer.ShowCurrentTimerValue();

Results:

10000 iterations:
1) PHP, ordinary concatenation: ~6ms
2) PHP, using StringBuilder: ~5 ms
3) C#, ordinary concatenation: ~520ms
4) C#, using StringBuilder: ~1ms

100000 iterations:
1) PHP, ordinary concatenation: ~63ms
2) PHP, using StringBuilder: ~555ms
3) C#, ordinary concatenation: ~91000ms // !!!
4) C#, using StringBuilder: ~17ms