PHP: Экономия оперативной памяти с помощью генератора yield
В современной разработке на PHP важно не только обеспечивать высокую производительность приложений, но и эффективно управлять ресурсами сервера, в частности оперативной памятью. Одним из способов оптимизации использования памяти при работе с большими объемами данных является использование генераторов, в частности конструкции yield.
Генераторы позволяют функции возвращать последовательность значений, используя ключевое слово yield, вместо возвращения всех значений сразу, что значительно снижает потребление памяти. Рассмотрим пример оптимизации кода с использованием генератора yield в PHP.
В данном примере мы извлекаем данные из базы данных MySQL, используя PDO (PHP Data Objects) для выполнения запроса к таблице combinations. Мы ограничиваем выборку 100000 и 500000 записями для демонстрации:
$pdo = new PDO('mysql:host=localhost;dbname=dbname', 'user', 'pass');
1. Классический подход
$query = 'SELECT `value` FROM `combinations` LIMIT 100000 '; $statement = $pdo->prepare($query); $statement->execute(); while( $row = $statement->fetch( PDO::FETCH_ASSOC ) ) { echo $row['value'] . '<br>'; } # Выборка: 100_000 записей # Время выполнения: 0.12888598442078 сек. # Использовано памяти: 4.47 МБ # Выделено памяти: 6.29 МБ # Выборка: 500_000 записей # Время выполнения: 0.65475416183472 сек. # Использовано памяти: 20.59 МБ # Выделено памяти: 20.97 МБ
2. Реализация с генератором
Использование генератора yield позволяет функции getDataFromDatabase возвращать данные по мере их чтения из базы данных, не загружая в память всю выборку сразу. Это существенно снижает потребление оперативной памяти при обработке больших объемов данных.
function getDataFromDatabase($pdo) { $query = 'SELECT `value` FROM `combinations` LIMIT 100000 '; $statement = $pdo->prepare($query); $statement->execute(); while( $row = $statement->fetch( PDO::FETCH_ASSOC ) ) { yield $row; } } foreach( getDataFromDatabase( $pdo ) as $row ) { echo $row['value'] . '<br>'; } # Выборка:100_000 записей # Время выполнения: 0.17423105239868 сек. # Использовано памяти: 397.32 КБ # Выделено памяти: 6.29 МБ # Выборка: 500_000 записей # Время выполнения: 0.52105402946472 сек. # Использовано памяти: 398.26 КБ # Выделено памяти: 10.49 МБ
Сравнение показателей использования памяти и времени выполнения для разных объемов данных (100000 и 500000 записей) демонстрирует преимущества использования генераторов:
- При использовании генератора yield потребление памяти остается на низком уровне (около 400 КБ), в то время как в традиционном подходе (без yield) потребление памяти растет пропорционально количеству обрабатываемых записей (до 20.59 МБ при обработке 500000 записей).
- Время выполнения кода с использованием генератора немного выше, что объясняется дополнительными затратами на управление генератором. Однако это незначительно по сравнению с экономией памяти.
Использование генераторов yield является эффективной техникой оптимизации для приложений, работающих с большими объемами данных. Это позволяет существенно снизить потребление оперативной памяти, повысить производительность приложения и улучшить общую эффективность использования серверных ресурсов.
Комментарии