勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

PHPにて配列の出力時にジェネレータを利用してメモリを節約する方法

  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に対して配列が入っているようなイメージだったので、その後の処理の違いでこんなに差が出るというのが感覚的には掴みづらいかも。

ただ、処理速度・使用メモリ共に顕著な差が出たので積極的に使っていきたいところ。

 

参考サイト

https://tech.willgate.co.jp/entry/2023/12/02/120000

https://qiita.com/falya128/items/53c4392b3695c12f9014

 - PHP

  関連記事

PHPで定義済みの変数 / 定数とincludeしているファイル一覧を取得する方法

他社が作成されたPHPのファイルを読み解く際に、定義済みの変数 / 定数や、in ...

PHP8系で「Warning: Constant xxxxx already defined in」エラーの対応方法

PHP8系&WordPress6.4.3で「Warning: Const ...

PHPでJSONデータを見やすく整形した上で表示させる方法

PHPで何らかのデータをjson_encodeでJSONに変換し、そのままech ...

Shift_JISでカタカナのソを出力するとエラー

先に結論として5C問題とかいうみたいで仕様らしい。 ■参考サイト http:// ...

PHPからCSVファイルを出力する際にメモリを節約する方法

MySQLよりデータを大量に取り出してCSVファイル化し、ダウンロードさせるとい ...