Why php generator is slower than foreach?

2019-04-05 01:01发布

问题:

According to comments from documentation: http://php.net/manual/en/language.generators.overview.php
We can see that thanks to generators there is huge memory usage improvement (which is obvious), but there is also 2-3 times slower execution - and that is not so obvious to me.

We gain memory usage improvement at the expense of time - which is not fine.
So, why php generator is slower than foreach?

Thanks for tips.

回答1:

In computer science, when doing optimizations a lot of the times you will have to choose between speed of execution and memory usage i.e precalculating something and storing it or just doing calculations when you need them.

A generator allows you to write code that uses foreach to iterate over a set of data without needing to build an array in memory, which may cause you to exceed a memory limit, or require a considerable amount of processing time to generate

The manual is probably referring to a situation when you will not iterate through all of the results that you generate with your generator. The speed benefit will then come from the fact that you don't need to waste processing time and memory by generating items that you don't need.

Also, the generators weren't designed to replace arrays. They were intended as a way to reduce boilerplate code when implementing Iterator objects.

The generators will always be slower when comparing them to arrays, because generator has to generate the values each time you call next() to save memory.

Edit

I was a little curious, so I did a quick and dirty comparson between xrange (implemented with generators, as on the PHP manual page) and the built in range function.

Results on my machine (tested with PHP 5.6) were:

range(1, 10000000, 1):

time: 5.2702
memory (byte): 1495269376

xrange(1, 10000000, 1):

time: 1.9010
memory (byte): 262144

Note that the "benchmark" code I was using was iterating through all results and doing simple math operations. The function calls, as displayed above, serve only as a reference for values I was testing with. As always, with simple benchmarks like this, YMMV.