22
Yielding Bells π - generators in PHP
Today we want us some bells in our Christmas, so let's create them. PHP has a neat feature called generators. Generators are functions that can be used to create iterators, and they don't need a large overhead to create them. For performance sake, let's compare two code snippets.
Snippet 1:
<?php
function produceBells(int $num)
{
$bells = [];
for ($i = 0; $i < $num; $i++) {
$bells[] = 'π';
}
return $bells;
}
$hundredBells = produceBells(100); // 8.3KB
foreach ($hundredBells as $bell) {
echo $bell . ' ';
}
Snippet 2:
function generateBells(int $num)
{
for ($i = 0; $i < $num; $i++) {
yield 'π';
}
}
$hundredBells = generateBells(100); //544 bytes
foreach ($hundredBells as $bell) {
echo $bell . ' ';
}
Both these snippets will produce this output:
π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π π
Is that a hundred bells? I sure hope so, I get lost when counting them!
The question is now, which is less memory intensive, and why is Snippet 2?! I ran both snippets with profile-mode on Xdebug and found the following result:
Snippet | Type | Memory usage |
---|---|---|
1 | Array | 8280 bytes |
2 | Generator | 544 bytes |
As we can see, the generator is a lot more memory efficient than the array. The reason for this is that generators are lazy, and only generate the values when they are needed. This means that the memory usage is only as high as the amount of values that are actually needed. And as we loop through one item at a time to echo it out, that is as much memory as will be used. You could output a million of these things if you like, and the memory usage would not be that much higher. (In fact, it remained at 544 bytes when I ran it.)
So what's the cost? Generators, while memory efficient, are not as time efficient. My machine is not stable enough (poor potato), to do a fair benchmarking. But at a thousand bells we got 9.2 ms for the array and 11.6 ms for the generator. So is it worth it for you to use generators? That question has not only to do with time versus memory cost. If you don't know how often you will need to access an array (or iterator) value, you may need to use a generator anyway.
Have you ever tried a generator before? What use cases do you have or think you would have for generators? Comment below and let us know what you think β
- Generators Overview: https://www.php.net/manual/en/language.generators.overview.php
22