はじめに
私は現在の携わる案件においてPHPを利用しています。
プログラムが動作する環境のデータ量に依存してパフォーマンスに課題が発生することが多く、
メモリー不足エラー「Fatal error: Allowed memory size of 〜」を目にすることが多いです。
課題改善をすべく、多量のデータ(要素)を扱うにあたり配列操作処理に観点を向け、
改善できることがないか調査を行ったところ、新しい学びがあったので本記事にまとめていきたいと思います。
本記事で扱う配列操作について
私の業務に実際に利用される頻度が高いものと今回の調査で学んだものを検証します。
- foreach
- array_***関数(array_sumなど)
- ジェネレータ→ new
検証
※今回は配列操作にあたり1~10万までの数字を要素とする配列を扱うものとします。
※例として全ての要素を足してみます。
1.foreach
<?php
$start = microtime(true);
$start_memory = memory_get_usage();
function create_array() {
$new_array = array();
for ($i = 0; $i <= 100000; $i++) {
$new_array[] = $i;
};
return $new_array;
};
$sum_num = 0;
foreach (create_array() as $key => $value) {
$sum_num += $value;
};
$exec_time = microtime(true) - $start;
$used_memory = (memory_get_peak_usage() - $start_memory) / (1024 * 1024);
echo "処理時間:{$exec_time}s" . "\n";
echo "メモリ使用量:{$used_memory}MB" . "\n";
?>
- 処理時間:0.015480995178223s
- メモリ使用量:4.0039825439453MB
2.array_***関数(array_sumなど)
<?php
$start = microtime(true);
$start_memory = memory_get_usage();
function create_array() {
$new_array = array();
for ($i = 0; $i <= 100000; $i++) {
$new_array[] = $i;
};
return $new_array;
};
$sum_num = array_sum(create_array());
$exec_time = microtime(true) - $start;
$used_memory = (memory_get_peak_usage() - $start_memory) / (1024 * 1024);
echo "処理時間:{$exec_time}s" . "\n";
echo "メモリ使用量:{$used_memory}MB" . "\n";
?>
- 処理時間:0.012201070785522s
- メモリ使用量:4.0039825439453MB
3.ジェネレータ
<?php
$start = microtime(true);
$start_memory = memory_get_usage();
function create_array() {
for ($i = 0; $i <= 100000; $i++) {
yield $i;
}
};
$sum_num = 0;
foreach (create_array() as $key => $value) {
$sum_num += $value;
};
$exec_time = microtime(true) - $start;
$used_memory = (memory_get_peak_usage() - $start_memory) / (1024 * 1024);
echo "処理時間:{$exec_time}s" . "\n";
echo "メモリ使用量:{$used_memory}MB" . "\n";
?>
- 処理時間:0.010108947753906s
- メモリ使用量:0.035301208496094MB
まとめ
検証結果に多少の前後はあると思いますが、処理結果は以下のようになりました。
処理 | 処理時間 | メモリ使用量 |
---|---|---|
foreach | 0.015480995178223s | 4.0039825439453MB |
array_sum | 0.012201070785522s | 4.0039825439453MB |
ジェネレータ | 0.010108947753906s | 0.035301208496094MB |
- 処理時間
- ジェネレータ > array_sum > forearch
- メモリ使用量
- ジェネレータ > array_sum = forearch
今のところ具体的な使用方法は思いつきませんが、
イメージとしては配列要素の順序吐き出しのようなものと思うので
CSVファイルなど大きい要素数を扱う機能において改善できるか検討してみようと思います。