Visualizing memory usage with and without using generators can help understand the efficiency benefits. Below is a comparison of memory usage in two scenarios:
Without using generators (loading all data into memory at once).
Using generators (loading one item at a time).
Scenario 1: Without Generators
Let’s say we have a simple function that returns an array of numbers from 0 to 999,999. This function loads all the data into memory at once.
function getNumbersArray() {
$numbers = [];
for ($i = 0; $i < 1000000; $i++) {
$numbers[] = $i;
}
return $numbers;
}
$numbers = getNumbersArray();
foreach ($numbers as $number) {
// Process each number
}
?>
Memory Usage (Without Generators)
When the function getNumbersArray is called:
Initial memory: Low, only the function and environment setup are in memory.
During execution: As the loop runs, the memory usage increases linearly, holding all 1,000,000 numbers in an array.
Peak memory: Very high, holding all the data in memory simultaneously.
After execution: Memory remains high until the script ends or the array is explicitly unset.
|——————————————————|
| Start | * |
| | ** |
| | *** |
| | **** |
| | ***** |
| | ****** |
| | ******* |
| … | ******************************************|
| End | ******************************************|
|——————————————————|
Scenario 2: Using Generators
Now, we use a generator function to yield numbers one at a time.
function numberGenerator() {
for ($i = 0; $i < 1000000; $i++) {
yield $i;
}
}
foreach (numberGenerator() as $number) {
// Process each number
}
?>
Memory Usage (Using Generators)
When the generator function numberGenerator is called:
Initial memory: Low, only the function and environment setup are in memory.
During execution: Memory usage remains low as only one number is held in memory at a time.
Peak memory: Low, only one item plus overhead for the generator.
After execution: Memory usage drops immediately after the iteration ends.
|——————————————————|
| Start | * |
| | * |
| | * |
| | * |
| | * |
| | * |
| | * |
| … | * |
| End | * |
|——————————————————|
Summary
Without Generators: Memory usage increases with the size of the dataset and remains high throughout the script execution.
With Generators: Memory usage remains constant and low, regardless of the dataset size, because only one item is processed at a time.
Generators provide significant memory efficiency benefits, especially for large datasets, by yielding one item at a time and maintaining low memory usage throughout the script’s execution.