はじめに
最近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%以上削減できる可能性あり。
- キーにする文字列も長さが短い方がメモリ使用量少ない。
コメント