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?
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.
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.
There are two string operators. The first is the concatenation operator ('. '), which returns the concatenation of its right and left arguments.
PHP strings are immutable. If a string was mutable, it would have continued to show "bing".
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With