勉強したことのメモ

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

  関連記事

CodeIgniter4でのメール送信方法(テキスト・HTMLメール)

CodeIgniter4.4.4でテキストメール及びHTMLメールを送信したい。 ...

他所のサーバからWordPressの記事情報をpostIDを指定して取得する方法

他所のサーバからWPの記事IDを指定した上で、当該IDのタイトル・アイキャッチ画 ...

PHPでファイルを添付してメールを送信する方法(PHPMailer)

PHPでファイルを添付の上、メールを送信したかった。方法を探したところphpma ...

ソシャゲのガチャのように当選確率が異なる抽選システムをPHPで作成する方法

ソシャゲのガチャみたいな当選確率が異なる抽選システムをPHPで作成したかった。具 ...

PHPでXML形式データをオブジェクト・JSON・連想配列に変換する方法

先日バニラJavaScriptでXML形式データの取り扱いとJSON形式への変換 ...