勉強したことのメモ

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でログインフォームにひらがな認証を設置する方法

ログインフォームに平仮名認証を設置したい。英数字認証だとSecurimageとい ...

CodeIgniter4で簡易版ログインシステムの実装方法(管理画面向け)

CodeIgniter4で管理画面向けの簡易版ログインシステムを作成したい。通常 ...

ブラウザから動画ファイル名を確認できないようにPHPで動画を出力する方法

Webページ上で動画ファイルを再生したい場合、通常だとブラウザのソースコード上に ...

PHPの日付・時刻関連

使えそうなものをまとめてメモ。 【関数】 ----------- ■date 日 ...

Codeigniter4で外部ファイル(CSS / JS)の読み込みと共通パーツ化する方法

Codeigniter4.4.4でCSS及びJavaScriptファイルを設置し ...