PHPにて配列の出力時にジェネレータを利用してメモリを節約する方法
PHPにて大量のデータが格納された配列をforeach等でループ処理するような場合、memory_limitが気になることがある。特にシステムのリリース当初は大丈夫でも、その後データが増えていくような場合だとさらに気になる。そのような場合、ジェネレータを使うとメモリを節約できるらしい。以下に利用方法をメモ。
想定
過去に取得した全国の市区町村データが入っているMySQLから10,000件取得してID(通し番号)をvar_dump()で出力する。
その際の処理にかかった時間とメモリ使用量を測定する。
利用方法
ソースコード
<?php #通常版 $sql = ' SELECT * FROM ad_address LIMIT 10000 '; $row = $mysqli->query($sql); while( $rs = $row->fetch_array(MYSQLI_ASSOC) ){ var_dump($rs['id']); } #ジェネレータ版 function getAddress(){ $sql = ' SELECT * FROM ad_address LIMIT 10000 '; $row = $mysqli->query($sql); while( $rs = $row->fetch_array(MYSQLI_ASSOC) ){ yield $rs['id']; } } foreach( getAddress() as $val ){ var_dump($val); }
測定結果
以下の通り顕著な差が出た。
- 通常版 → 処理時間0.099609693秒 / 使用メモリ2.17MB
- ジェネレータ版 → 処理時間0.013392766秒 / 使用メモリ418.55KB
リファレンス
https://www.php.net/manual/ja/language.generators.overview.php
所感
「$row = $mysqli->query($sql);」の時点で$rowに対して配列が入っているようなイメージだったので、その後の処理の違いでこんなに差が出るというのが感覚的には掴みづらいかも。
ただ、処理速度・使用メモリ共に顕著な差が出たので積極的に使っていきたいところ。
参考サイト
関連記事
-
-
PHPMailerでエンベロープFrom(Return-Path)を指定する方法
同じメールアドレスから送信したメールがmb_send_mail関数だと受信できる ...
-
-
【2024年版】PHPMailerでGmailのSMTPサーバを経由してメールを送信する方法
だいぶ前に同じようなことをメモしたが、そちらの方法だと送信できずエラー内容を見た ...
-
-
PHPでファイルのダウンロード時に速度制限をかける方法(分割ダウンロード)
オンラインストレージサービス等で有料会員じゃない場合、ファイルのダウンロード時に ...
-
-
レンタルサーバでPHPのsystem関数やexec関数が使用できずにエラーが出力される
レンタルサーバ上でPHPのsystem関数を実行しようとすると「Fatal er ...
-
-
PHPで日付の比較
以前に「締切日を設けて、今日の日付と比較して分岐させる」というもので 日付の比較 ...