勉強したことのメモ

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

  関連記事

CodeIgniter3でCronを実行する方法

CodeIgniter3系で特定の処理をCronで自動実行したかった。以下に設定 ...

SendGridを使ってメールサーバを構築せずにPHPからメールを送信する方法

メールサーバを構築せずに独自ドメインのメールアドレスにてメール送信を行いたい。過 ...

CentOSでPHPを5.5から5.3にバージョンダウンする方法

事情があってVPSに入れているPHPを5.5系から5.3系にバージョンダウンした ...

ファイルの更新日付取得とリネーム

やりたかった事は、画像ファイルの更新日時取得と リネーム。 ■参考サイト htt ...

PhpSpreadsheetでExcelファイルを読み込みPHPの配列として取り扱う方法

formからCSVファイルをアップロードし、PHPの配列に格納後、データベース登 ...