勉強したことのメモ

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でスマホ(iPhone / Android)に画像をダウンロードさせる方法とダウンロード後の保存場所について

PHPで作ったシステムにスマホ(iPhone / Android)でアクセスし何 ...

imgタグのsrc属性のURLにPHPでタイムスタンプを付与しキャッシュ対策する方法

imgタグで画像を表示する際、画像を書き換えても同じものが表示されるというケース ...

PHPでファイルをダウンロードさせる

集計ページみたいなんがあった。その集計ページを CSV化したいと言われた。 ■ソ ...

UTF-16にエンコードされている文字列をUTF-8へデコード

エンコードされている文字列であまり見かけない感じのものがあった。UTF-8やSh ...

PHPでdo-while(0)構文を利用する際のメリット

あるソースコード上にdo-whileという構文が使われていた。見たことのない構文 ...