note 126394 deleted from function.array-merge by salathe

From: Date: Mon, 06 Sep 2021 22:42:42 +0000
Subject: note 126394 deleted from function.array-merge by salathe
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-216876@lists.php.net to get a copy of this message
Note Submitter: Martin K ---- NOT FOR PUBLICATION Previously I made the posting below, which was editorially edited to add "[Editor's Note: the 1125075000 elements are not copied (CoW); the performance is bad due to function call overhead.]". I take issue with that comment. Whilst we can argue over what constitutes a "copy", the measurable performance is dominated by the number of elements in the array, so saying "function call overhead" is misleading. The original posters "straw man" code exhibits quadratic time behaviour, as it repeatedly copies a growing array, so of COURSE it performs badly compared with any linear-time algorithm. Just run the code if you want proof: doubling the initial array size quadruples the runtime. I therefore request that the editorial comment attached to my post be amended or removed; at minimum please remove "due to function call overhead". If that cannot be done then please delete the entire posting, as I do not wish to be associated with an inaccurate comment. We both understand that when the array elements point to ("are references to") objects, those objects are NOT copied. I used the word "copy" in the sense used in the C language: if you copy a pointer then you copy a pointer, not the thing it points at. What matters is that the elements of each new array are initialized with values taken from each of the parameter arrays, and that the time this takes is roughly proportional to the number of such elements. (From that perspective it doesn't even matter whether the references are copied or not; the scale effect would be the same.) I therefore further suggest that "the 1125075000 elements are not copied" comment be re-phrased, preferably to something along the lines of "the 1125075000 elements are initialized rather than copied". And then please look and see whether the editorial comment still adds any value to the posting, and consider deleting it entirely. ORIGINAL POSTING FOLLOWS. Another commentator suggest that a "foreach loop is faster than array_merge to append values to an existing array", and goes on to prove this by timing some code. It starts with a preamble that sets up $chars as an array with 15000 elements, each in turn being an array with 10 elements, and then testing the timing of this code: <?php $new = []; foreach ($chars as $splitArray) { $new = array_merge($new, $splitArray); } ?> It then times this functionally equivalent code: <?php $new = []; foreach ($chars as $splitArray) { foreach ($splitArray as $value) { $new[] = $value; } } ?> and concludes that array_merge is 1400 times slower than a foreach loop. Of course, the problem isn't that array_merge is slow, the problem is that it's being called 15000 times, meaning that it copies 1125075000 array elements, instead of just 150000. (That is, it's making 7500 times as many copies.) More appropriate would be this _also_ functionally equivalent code: <?php $new = array_merge(...$chars); ?> which turns out to be roughly 25% faster than that foreach loop. Of course, if you can modify an existing array, then that will usually be faster than copying the entire existing array plus a few new elements. In that case I would write: <?php push_array($new, ...$chars); ?> ... which again beats the naive foreach loop by about 25%. Even without the speed improvement, the elegance of a single line of code instead of six is hard to beat.

« previous php.notes (#216876) next »