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に対して配列が入っているようなイメージだったので、その後の処理の違いでこんなに差が出るというのが感覚的には掴みづらいかも。
ただ、処理速度・使用メモリ共に顕著な差が出たので積極的に使っていきたいところ。
参考サイト
関連記事
-
-
PHPでエラーログ等のログファイルから指定した行数を表示させる方法
エラーログを最新分から指定行数表示させる プログラムがあって、どういった作りにな ...
-
-
PHPのHTTPクライアント用ライブラリ「Guzzle」の利用方法
以前に「Requests for PHP」を試したが、似たようなライブラリで「G ...
-
-
PHPでCookie保存時にHttpOnly / Secure属性を設定する方法
あるシステムのセキュリティ対策としてCookie保存時にHttpOnly / S ...
-
-
PHPでCSVファイルを出力する際に「①」や「㈱」等の環境依存文字が文字化けする対応方法
過去記事の方法を用いてPHPでCSVファイルを出力すると所々「?」という形に文字 ...
-
-
MySQLで重複を除く
ユニークな値を取り出したいときに使う。 DISTINCT(ディスティンクト) S ...