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で外部ファイルから配列を取得
やりたかった事。 ①管理画面で必要項目を入力すると、aaa.phpが 生成される ...
-
-
PHPでパスワードを保存する際に暗号(パスワードハッシュ)化させ、ログイン認証時に用いる方法
PHPでログイン認証を組み込む際に今までは特に暗号化は行っていなかった。と言うの ...
-
-
smart_resize_imageで縦横の比率関係なく、固定リサイズ
PHPで縦横どちらかが指定の長さを超えた場合、比率を保ったままリサイズで使ったs ...
-
-
PHPページングテンプレ
使いやすいのがあったのでメモ。 $page ...
-
-
CodeIgniter4で特定のページにアクセスがあった際に301リダイレクトさせる方法
CodeIgniter4で特定のページにアクセスがあった際に301リダイレクトさ ...