问题
I'm modifying some code in which the original author built a web page by using an array thusly:
$output[]=$stuff_from_database;
$output[]='more stuff';
// etc
echo join('',$output);
Can anyone think of a reason why this would be preferable (or vice versa) to:
$output =$stuff_from_database;
$output .='more stuff';
// etc
echo $output;
回答1:
It was probably written by someone who comes from a language where strings are immutable and thus concatenation is expensive. PHP is not one of them as the following tests show. So the second approach is performance wise, better. The only other reason that I can think of to use the first approach is to be able to replace some part of the array with another, but that means to keep track of the indexes, which is not specified.
~$ cat join.php
<?php
for ($i=0;$i<50000;$i++) {
$output[] = "HI $i\n";
}
echo join('',$output);
?>
~$ time for i in `seq 100`; do php join.php >> outjoin ; done
real 0m19.145s
user 0m12.045s
sys 0m3.216s
~$ cat dot.php
<?php
for ($i=0;$i<50000;$i++) {
$output.= "HI $i\n";
}
echo $output;
?>
~$ time for i in `seq 100`; do php dot.php >> outdot ; done
real 0m15.530s
user 0m8.985s
sys 0m2.260s
回答2:
This is a little off topic, but
$output =$stuff_from_database;
$output .='more stuff';
// etc
echo $output;
Is far slower than:
echo = $stuff_from_database;
echo 'more stuff';
In fact, the fastest way to build a string in PHP is:
ob_start();
echo = $stuff_from_database;
echo 'more stuff';
$output = ob_get_contents();
ob_end_clean();
Due to the way that output buffers work and such, it is the fastest way to build a string. Obviously you would only do this if you really need to optimize sting building as it is ugly and doesn't lead to easy reading of the code. And everyone one knows that "Premature optimization is the root of all evil".
回答3:
Again, a little bit off topic (not very far), but if you were aiming to put something between the array items being output, then if there was only a few lines to concatenate, join(', ', $output) would do it easily and quickly enough. This would be easier to write, and avoids having to check for the end of the list (where you would not want a trailing ',').
For programmer time, as it is on the order of 1000's of times more expensive than a cpu cycle, I'd usually just throw it into a join if it wasn't going to be run 10,0000+ times per second.
Post-coding micro-optimisation like this is very rarely worth it in terms of time taken vs cpu time saved.
回答4:
<!-- Redacted Previous Comment -->
It would appear I had an error in my code so i was doing a no-op and forgot to check.
It would appear Contary to previous testing, and reading previous blogs on the topic, the following conclusions are actually ( tested ) untrue at least for all variants of the above code I can permute.
- UNTRUE: String interpolation is slower than string concatenation. (!)
- UNTRUE: SprintF is fastest.
In actual tests, Sprintf was the slowest and interpolation was fastest
PHP 5.2.6-pl7-gentoo (cli) (built: Sep 21 2008 13:43:03) Copyright (c) 1997-2008 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies with Xdebug v2.0.3, Copyright (c) 2002-2007, by Derick Rethans
It may be conditional to my setup, but its still odd. :/
回答5:
I think the fastest way to do it is with echoes. It's not as pretty and probably not enough faster to be worth the cost in readability.
echo $stuff_from_database
, 'more stuff'
, 'yet more'
// etc
, 'last stuff';
回答6:
The bottom will reallocate the $output string repeatedly, whereas I believe the top will just store each piece in an array, and then join them all at the end. The original example may end up being faster as a result. If this isn't performance sensitive, then I would probably append, not join.
回答7:
This part of the code is not performance sensitive; it is used to format and display a user's shopping cart info on a low-traffic website. Also, the array (or string) is built from scratch each time and there is no need to address or search for specific elements. It sounds like the array is somewhat more efficient, but I guess it doesn't matter either way for this use. Thanks for all of the info!
回答8:
If you're generating a list (e.g. a shopping cart), you should have some code that generates the HTML from each entry fetched from the database.
for ($prod in $cart)
{
$prod->printHTML();
}
Or something like that. That way, the code becomes a lot cleaner. Of course, this assumes that you've got nice code with objects, rather than a whole moronic mess like my company does (and is replacing).
回答9:
It has already been said, but I think a distinct answer will help.
The original programmer wrote it that way because he thought it was faster. In fact, under PHP 4, it really was faster, especially for large strings.
回答10:
If joined with implode()
or join()
, PHP is able to better optimize that. It goes through all strings in your list, calculates the length and allocates the required space and fills the space. In comparison with the ".=" it has to constantly free()
and malloc()
the space for the string.
来源:https://stackoverflow.com/questions/111282/php-output-w-join-vs-output