はじめに
最近PHP上に大量のデータをメモリ上に展開していたのですが、配列(array)の形式(連想配列 or 単純な配列)や配列の要素のデータ構造(数字、配列、文字列など)で大きくメモリ使用量に差が出てくることに気づき、簡単なプログラムを組んで調べてみました。あくまで筆者の環境での結果なので、細かい数値は参考程度に見てください。
測定環境と方法
- OS: Windows 10
- PHP 7.4.5 (php-7.4.5-nts-Win32-vc15-x64)
計測結果
No. | 方式 | 1MB当たり作成できる 要素数 | プログラム | 補足 |
---|---|---|---|---|
1 | キーも値も整数の配列 (整数IDを想定) |
28571 | // 2,000,000 / 70MB $row = []; for($i = 0; $i < 2000000; $i++) { $row[] = $i; } |
No.2~6でテストしたプログラム中の要素数は200,000。これだけ一桁多い! |
2 | キーが文字列、値が整数の連想配列 | 8333 | // 200,000 / 24MB $row = []; for($i = 0; $i < 200000; $i++) { $row[$i.'_key_string'] = $i; } |
キーの文字列が長い方がメモリ使用量多くなる。 |
3 | キーが整数、値が連想配列の配列 DBから取得してきたデータを想定 |
2325 | // 200,000 / 86MB $row = []; for($i = 0; $i < 200000; $i++) { row[] = ['id' => $i]; } |
|
4 | キーが整数、値が連想配列の配列(配列に複数の値を保持) DBから取得してきたデータを想定 |
2127 | // 200,000 / 94MB $row = []; for($i = 0; $i < 200000; $i++) { $row[] = [ 'id' => $i, 'value1' => $i+1, 'value2' => $i.'_value_2' ]; } |
要素内の保持データによってメモリ使用量がだいぶ変わる。例えば、データが整数だけの場合は、それほどメモリ使用量増えなかった。 |
5 | No.4と同じデータを3つの別の配列で保持 | 4762 | // 200,000 / 42MB $row1 = []; $row2 = []; $row3 = []; for($i = 0; $i < 200000; $i++) { $row1[$i] = $i; $row2[$i] = $i+1; $row3[$i] = $i.'_value2'; } |
|
6 | No.5でキーを文字列にした場合(sha1関数でキーを生成) | 3448 | // 200,000 / 58MB $row1 = []; $row2 = []; $row3 = []; for($i = 0; $i < 200000; $i++) { $key = sha1($i); $row1[$key] = $i; $row2[$key] = $i+1; $row3[$key] = $i.'_value2'; } |
|
7 | No.4で要素をクラスにした場合 | 4762 | // 200,000 / 42MB $row = []; for($i = 0; $i < 200000; $i++) { $row[] = new DataObject($i, $i+1, $i.'_value_2') } class DataObject{ public $id; public $value1; public $value2; public function __construct($id, $value1, $value2) { $this->id = $id; $this->value1 = $value1; $this->value2 = $value2; } } |
まとめ
- メモリ使用量を節約したければ、配列内の要素は配列にせず、値にしたほうがよい。DBからデータを取得するときも、IDだけ取得するような場合は連想配列でなく、IDだけを保持した整数配列にすれば、大幅にメモリ使用量削減できる。筆者としてはここまで差が大きくなると思っていなかったので、この結果が一番驚いた。
- 配列はメモリ使用量が整数、文字列よりも大幅に多いので、大量のデータをメモリ上に展開するときは、連想配列の階層が深くならないように注意したほうがよさそう。
- 整数のデータの方が文字列よりもメモリ使用量少ない(当たり前)。
- 配列よりもクラスを使ったほうがメモリ使用量少ない。保持しているデータにも依存するが50%以上削減できる可能性あり。
- キーにする文字列も長さが短い方がメモリ使用量少ない。
コメント