Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php String Concatenation, Performance

In languages like Java and C#, strings are immutable and it can be computationally expensive to build a string one character at a time. In said languages, there are library classes to reduce this cost such as C# System.Text.StringBuilder and Java java.lang.StringBuilder.

Does php (4 or 5; I'm interested in both) share this limitation? If so, are there similar solutions to the problem available?

like image 714
Chris Avatar asked Sep 23 '08 21:09

Chris


People also ask

Is string interpolation faster than concatenation?

String concatenation is a little faster for a very small number of arguments, but requires more memory. After 20+ arguments concat is better by time and memory.

Is StringBuilder better than concatenation?

Note that regular string concatenations are faster than using the StringBuilder but only when you're using a few of them at a time. If you are using two or three string concatenations, use a string.

Can you concatenate strings in PHP?

There are two string operators. The first is the concatenation operator ('. '), which returns the concatenation of its right and left arguments.

Is string in PHP immutable?

PHP strings are immutable. If a string was mutable, it would have continued to show "bing".


2 Answers

No, there is no type of stringbuilder class in PHP, since strings are mutable.

That being said, there are different ways of building a string, depending on what you're doing.

echo, for example, will accept comma-separated tokens for output.

// This... echo 'one', 'two';  // Is the same as this echo 'one'; echo 'two'; 

What this means is that you can output a complex string without actually using concatenation, which would be slower

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

If you need to capture this output in a variable, you can do that with the output buffering functions.

Also, PHP's array performance is really good. If you want to do something like a comma-separated list of values, just use implode()

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

Lastly, make sure you familiarize yourself with PHP's string type and it's different delimiters, and the implications of each.

like image 156
Peter Bailey Avatar answered Sep 26 '22 00:09

Peter Bailey


I was curious about this, so I ran a test. I used the following code:

<?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

like image 23
Evilnode Avatar answered Sep 24 '22 00:09

Evilnode