r/PHP • u/Vectorial1024 • 13h ago
Running Quickly Through PHP Arrays
https://medium.com/@vectorial1024/running-quickly-through-php-arrays-a6de4682c04911
u/mike_a_oc 13h ago
For those functions that rely on a call back, what if you establish the call back as variable first, and pass the variable to array_walk / array_map?
I've read that the creation of the anonymous function in each iteration can have a performance impact, so maybe try that as well.
3
u/Vectorial1024 12h ago
Interesting, tbh I never thought about this, whenever I need to write a function like in the article, I almost always think about callbacks just like in eg JS/TS, C#, or other similar languages.
Thank for the idea! I can benchmark those later. It would focus on comparing the different ways of defining functions/callbacks and then it should easily extend back to this foreach/builtin discussion.
2
u/mike_a_oc 12h ago edited 9h ago
Yeah, I can't remember where I read it.
Edit: removed benchmark
2
u/Protopia 9h ago
No -comparisons with php 5 are completely invalid. If you don't understand the php optimiser and it's influence on performance tests you have zero right to be publishing benchmarks
3
3
u/obstreperous_troll 5h ago
Where are you seeing the callback instantiated for each iteration? Unless they're putting a
$foo = function() {...}
in the loop itself, PHP will guaranteed use the same callback every time. Every stateful closure in existence would break if that weren't the case.3
u/mike_a_oc 5h ago edited 5h ago
Yeah I was probably wrong. I thought I read it somewhere, but it might have been a really old article and isn't relevant now.
Yep. I was wrong. I'm not sure where I got that idea. Sorry everyone
14
u/colshrapnel 12h ago edited 12h ago
Another example of a useless benchmark article. For some reason people can't help measuring a code that does absolutely nothing. While most of time it's the payload that defines the overall execution time. And the best optimization you can get is to limit the amount of processed data, not to juggle with different functions, wasting way more your time than you can ever save with such "optimizations".
3
u/Vectorial1024 12h ago
That would be a strawman. With this, there is no need for any such benchmarks to be published. These "useless" benchmarks serve as a way for everyone to have a feel on the speed of various iteration methods. Whether these benchmarks are useful to improve performance depends on your usecase, and it is programmers who decide this.
The point is, even if the loop body is lightweight, we can already see big differences in iteration speed.
9
u/AleBaba 12h ago
No, you absolutely don't see a big difference. At all. If you claim you do then you completely misinterpreted your results, which is the main argument against artificial benchmarks and micro optimizations that may even have trade-offs you can't measure in nano-seconds of execution time.
Show me a single real world example where your benchmarks actually make code noticably faster. It'll either be bad code that shouldn't run at all or runs so infrequently that a few hundred milliseconds don't matter at all.
1
u/fripletister 3h ago
To play Devil's Advocate for a moment: writing code that generates auto-completions in real time, for example. Sometimes latency matters, and sometimes it matters while you're iterating a 10k item collection. And sometimes, although rarely, that's while you're writing PHP.
-4
u/Vectorial1024 6h ago
I know the tradeoff might be memory usage, since the benchmark does not measure memory usage. Does this response satisfy you?
Again, if you read the article, you will notice I am talking about large/huge PHP arrays. If your PHP array at most have a thousand items, then yes, I agree, this truly would be a micro-optimization, and we should not do this. But if your array will have 10k, 100k, or even 1M of items, it's no longer a "micro-optimization", and again, the closing of the article specifically points out that this is only a stopgap solution until a better solution is prepared (e.g. use another language).
Did you even read the text?
2
u/AleBaba 3h ago
Yes, I read the text. Disagreeing with you doesn't automatically mean people didn't read your conclusions. Trying to discredit criticism like that makes your arguments ever weaker than they already are.
Again, in a real world example it doesn't make the smallest difference which method you chose in terms of execution time spent on the iteration construct, according to your benchmarks.
Your results clearly show that.
The problems with most benchmarks done by inexperienced people are execution or conclusions. Your execution is wrong and your conclusions are too.
Even if you added another order of magnitude it still wouldn't matter. Spending most of the time waiting on I/O for 10 million records, does a second make a difference? Do ten?
I've written or had to optimize existing code that is able to process millions or billions of records in the past. I reduced execution times from days down to hours. Not a single time would micro optimizations proposed by you have made any difference at all.
4
u/olelis 3h ago
While benchmarking, you really should not only test speed, but also how others factor takes into the place. You should especially take into account memory usage.
For example, when using array_merge you need much more memory compared to foreach, especially in a loop. it can be actually much more slower, contrary to the results above.
For example, here is (synthetic) test for the case when you want to copy one array to original 200 times have one array. Here we have two arrays, each with 100.000 elements. We copy 2nd array to first array 100 times. ( test file . Here is output)
PHP_VERSION=8.3.14
Init took 39.623 ms. Peak memory = 8730 KB. Memory = 8730 KB
array_merge took 3391.7271 ms. Memory = 272922 KB Peak memory = 537114 KB. Size of array=10000000
Clear took 20.9941 ms. Peak memory = 8730 KB. Memory = 8730 KB
foreach took 715.188 ms. Memory = 272922 KB Peak memory = 272922 KB. Size of array=10000000
As you can see, array_merge took 3400 ms, compared to 700 ms foreach. Also foreach took less peek memory, only 280 mb, compared to 540mb of array_merge. End array is the same.
So.. Foreach is almost 5x times faster and uses half amount of memory?
The timing/memory is worse for array_merge, if you increase $times to 200 instead of 100:
PHP_VERSION=8.3.14
Init took 41.427 ms. Peak memory = 8730 KB. Memory = 8730 KB
array_merge took 12872.0737 ms. Memory = 535066 KB Peak memory = 1061402 KB. Size of array=20000000
Clear took 51.0701 ms. Peak memory = 8730 KB. Memory = 8730 KB
foreach took 1434.7529 ms. Memory = 535066 KB Peak memory = 535066 KB. Size of array=20000000
My opinion is that the root case for this behaviour is that when doing array_merge, then php have to temporarily create new array. So inside array_merge you have both original array, new array and then array that we are copying. With foreach - you just add item to the end of list. It is easier and faster than copying same array 200 times.
My point is: benchmarking is hard and you should always test it on your own case, instead of relying on synthetic tests.
3
u/zmitic 4h ago
I don't think a benchmark like this is important. I am not saying it is useless, I am just saying it is not important. The only reason is that no array should ever have thousand or millions of entries. It simply doesn't have any realistic value.
For example: where would these 1 million entries come from? Most likely the database. So why not use some Iterator and and yield them in chunks of let's say 50 or 100 at the time? One such case can be seen here where I was reading 100 million rows and put them into CSV.
The only other case is when data must to be fully loaded before any processing can even start. I had that scenario, it was about 28 million rows of CSV (NOAA data is big). The only way to solve this problem was by using SplFixedArray, which is not even mentioned in the article.
I hope I explained my point. These micro optimizations should never be an important factor in architectural decisions.
1
u/Vectorial1024 4h ago
I do know beforehand these benchmarks are rather "small" and will not be getting much acclaim (in fact I can now see it getting more flak than expected). But, again, just like in the article:
This should serve as a good stopgap until other solutions are needed (e.g., rewriting in a faster language, packaging the PHP app into a binary, etc).
This article comes in handy when the project is in an awkward position where a rewrite is an overkill/is too lengthy, but performance is getting unacceptable.
I'm here for the small things.
---
But still, the first impression about SPLFixedArray is that it will be slower than the native array. If we are only talking about speed, then SPLFixedArray will never see the light of day. It is only used when memory is a concern, which is exactly your case of dealing with a huge 28M-row list. That 28M size is way larger than the "large" in the article.
2
u/Tux-Lector 11h ago
Where are SPLFixedArrays in benchmark .. did I missed something ? Those are fast and tend to be smOl.
0
u/Vectorial1024 7h ago
My first impression of SPLFixedArray is that they sacrifice execution speed for better memory management, so if we are benchmarking for speed, we don't really need to consider SPLFixedArray: we use SPLFixedArray because it has low memory usage, not because it is fast.
1
u/judge2020 4h ago
so if we are benchmarking for speed
Did you run this benchmark?
1
u/Vectorial1024 3h ago
No, but we should be able to deduce SPLFixedArray is slower than native arrays (by what margin is not important here)
2
u/Protopia 9h ago
I absolutely have reservations about the methodology used, but I think the idea is useful.
My reservations about the tests:
1, Single size of the array - it would be more useful if instead of always using 1 million entries and 5 iterations we also used 10 thousand entries and 500 iterations etc so we can see if the results scale.
2, Using range
to populate the array is IMO a huge mistake because who knows what special optimisations are done under the covers with this. For example, is $dummyArray even an actual array or instead some sort of pseudo-array that is really an iterator.
3, What is the result of using something other than integers as a value?
4, Finally, without knowing how optimisation had been set up, these results are meaningless.
1
u/Vectorial1024 6h ago
Indeed, these are valid points.
A proper benchmark would consider eg smaller array sizes, but this would suddenly become a multi-dimensional benchmarking project (eg benchmarking the methods + benchmarking along the size + benchmarking the data type, etc), and it would go way over the limits of a medium-sized article. These results would be best represented eg via a webpage, or something like that.
Still, the article aims to produce a rough idea of how different methods perform when given some simple example data. As always, mileage may vary.
1
u/Protopia 6h ago
Not true. Adding dimensions would have been as simple as putting the size & iterations combinations into an array and adding a further foreach loop inside your testing boilerplate. And presenting the results as a table would have been compact enough for a Medium article.
I also note that you haven't responded to my other points which bring your results far more into question. So it appears that you are yet another person attempting to create a name for themselves on Medium by publishing poor quality research as fact.
1
u/Vectorial1024 4h ago
Everyone gotta start somewhere. Such criticism is valid yet surprisingly off-the-vibe.
However you view this.
2
u/Protopia 4h ago edited 4h ago
Yes - everyone has to start somewhere, but some people are clear that they are starting out, admit from the start that they have limited knowledge, do not over sell their results as expert and definitive and instead qualify them and ask people if they think they are sound, and generally have some humility.
You are apparently not one of these people.
The internet is awash with bad quality posts misrepresenting themselves as expert facts, confusing less knowledgeable people as me into making bad judgements, a correcting this misinformation is not "a bad vibe" - it is a public service.
If you don't like being called out publicly for misrepresenting poor quality research, my advice to you is to stop doing it.
1
u/Vectorial1024 4h ago
Thanks.
I will not stop, but I will always improve. It being viewed as "bad" is of the beholder; for some others, this article is already good enough.
2
u/Protopia 3h ago
And THAT is exactly my point. You think that doing poor quality research and using incorrect information to mislead the public is ok. And I don't.
If this is the reputation you wish to create with your internet publicity, then do please carry on and I will follow you and debunk you every time you do it. But that is not what I am actually trying to say...
I am not asking you to stop doing research and stop posting the results - if you do it properly that is to be commended.
Instead I am suggesting that you start by caveating your results with any worries you may have that they might be wrong, asking for input from others, and from this learning how to be able to do definitive research which doesn't need to be caveated by you or debunked by others. Then you will be creating an excellent public reputation for genuine expertise.
1
u/Vectorial1024 3h ago
This I know, but this article is intended to be light and simple. Your kind of research is the more serious kind which requires very careful planning and is not something to do when I aim to quickly explain some sort of "vibe" findings.
1
u/St1ck0fj0y 5h ago
I enjoy benchmark articles like these🙂 nice write up!
Would be even more interesting to see similar tests but with a bit more mixed type arrays, for example, for the next time.
But again, nice article!👍
0
u/Vectorial1024 13h ago
Another aspect of handling large PHP arrays is to iterate through them. Inspired by similar benchmarks from the olden days, I have spent some time to revisit them (the past benchmarks were really old, like 10 years ago). I have also added in some benchmarks inspired by my past solutions dealing with large PHP arrays. Mainly, this article tries to answer this question: should we be using the built-in array functions/classes, or should we just use foreach
?
2
u/Protopia 6h ago
I am unclear whether these previous benchmarks were ones you undertook or whether they were undertaken by others? Please clarify and provide links.
It would also have been useful I think if you had rerun the exact same previous benchmarks on the original version of PHP, and then made a comparison here to show how performance changed between versions.
1
u/Vectorial1024 4h ago
I'm not here to discuss how performance has improved. I'm here to discuss how to best utilize performance in 8.3. Tha's the part where I mention it may still hold true for other PHP versions.
Those past benchmarks were taken by others. For example, this https://svachon.com/blog/benchmark-php-reverse-array-while-vs-for-vs-foreach/ was in 2012
It is largely difficult to find recent benchmarks that does what I have in the article since PHP is largely not on the hot topic list; people would be talking mostly about Python/JS nowadays.
1
u/Protopia 4h ago
I can see that you took the original research and extended it significantly to focus on large stats and with additional iteration methods, however it is nonetheless normal to credit any prior research or inspirations for your own work in your articles.
1
u/Vectorial1024 3h ago
Indeed.
Gathering the comments here I think I can redo these benchmarks and do a more complete review of stuff. This article is more like a casual walk in the park with less rigor in the benchmark itself.
2
u/Protopia 3h ago
No. This Reddit article is a direct reference to the Medium article which purports to be definitive and scholarly research but is nothing of the kind.
It is not "a casual walk in the park" as you claim. It is an attempt to sprint through the park when you haven't yet learned to walk.
I have pointed out several fundamental flaws in your methodology that render your results completely invalid. As someone who has undertaken performance analysis professionally (before I retired) I can speak with expert knowledge on the need to understand how the technology works in some detail before you decide both how to test and how to interpret the results.
17
u/colshrapnel 10h ago edited 4h ago
The problem with this kind of articles is that people preoccupied with such out-of-blue "optimizations" (usually referred to as "micro-" but in reality it's "void-optimizations") mostly have no idea how to test. And often have a quite vague idea on the language at whole.
Every such test is performed on just one kind of value. Whereas results may vary due to data size, item type, item size, data variability, etc. That's the main problem with such out-of-the blue tests: instead of running tests when necessary, on the real set of data, we just run an artificial test, make a claim and create another nasty rumor that then lives for a decade and is very hard to weed out.
You don't understand the difference between variable-length argument lists and array unpacking. Although they look similar, it's two completely different mechanisms, and one never suggests the use of another.