あっぽログ
← 記事一覧に戻る

PHPのSplFixedArrayを使いこなす:固定長配列でメモリ効率を高める

SplFixedArrayとは

PHPの標準ライブラリ(SPL)には、さまざまなデータ構造が用意されています。その中の一つが SplFixedArray です。

SplFixedArray は、サイズが固定された配列です。通常のPHP配列は要素を自由に追加・削除できますが、SplFixedArray は作成時にサイズを決めると、後からサイズを変えられません(厳密には変更メソッドがありますが、コストがかかります)。

「制限があるなら使いにくそう…」と思うかもしれませんが、その分 メモリ使用量が少なく、アクセスが高速 というメリットがあります。要素数があらかじめ決まっているケースでは非常に有効な選択肢です。


SplFixedArrayの基本操作

作成とアクセス

<?php

// サイズ5の固定長配列を作成
$fixedArray = new SplFixedArray(5);

// 値をセット(インデックスは0始まり)
$fixedArray[0] = 'apple';
$fixedArray[1] = 'banana';
$fixedArray[2] = 'cherry';
$fixedArray[3] = 'date';
$fixedArray[4] = 'elderberry';

// 値にアクセス
echo $fixedArray[0]; // apple
echo $fixedArray[2]; // cherry

// 要素数を確認
echo $fixedArray->getSize(); // 5
echo count($fixedArray);     // 5

範囲外アクセスはエラーになる

通常の配列であれば範囲外にアクセスしても単に null や警告で済むことが多いですが、SplFixedArray では 例外がスローされます

<?php

$fixedArray = new SplFixedArray(3);
$fixedArray[0] = 'foo';

try {
    echo $fixedArray[5]; // 範囲外
} catch (RuntimeException $e) {
    echo 'エラー: ' . $e->getMessage();
    // エラー: RuntimeException: Index invalid or out of range
}

これにより、バグを早期に発見できるという利点もあります。


通常配列との相互変換

既存の配列から SplFixedArray を作ったり、逆に通常配列に戻したりすることも簡単にできます。

<?php

// 通常配列 → SplFixedArray
$array = [10, 20, 30, 40, 50];
$fixedArray = SplFixedArray::fromArray($array);

echo $fixedArray[1]; // 20
echo $fixedArray->getSize(); // 5

// SplFixedArray → 通常配列
$backToArray = $fixedArray->toArray();
var_dump($backToArray);
// array(5) { [0]=> int(10) [1]=> int(20) ... }

fromArrayのsave_indexesオプション

fromArray() の第2引数に false を渡すと、元配列のキーを無視して詰め直してくれます。

<?php

// キーが飛んでいる配列
$sparse = [0 => 'a', 3 => 'b', 7 => 'c'];

// save_indexes: true(デフォルト)→ サイズ8になる
$fixed1 = SplFixedArray::fromArray($sparse, true);
echo $fixed1->getSize(); // 8

// save_indexes: false → サイズ3に詰める
$fixed2 = SplFixedArray::fromArray($sparse, false);
echo $fixed2->getSize(); // 3
echo $fixed2[1];         // b

イテレーションとforeachの使い方

SplFixedArrayIterator インターフェースを実装しているため、foreach でそのまま使えます。

<?php

$fixedArray = SplFixedArray::fromArray(['red', 'green', 'blue']);

foreach ($fixedArray as $index => $value) {
    echo "{$index}: {$value}\n";
}
// 0: red
// 1: green
// 2: blue

サイズの変更

固定長といっても、setSize() メソッドでサイズを変えることは可能です。ただし、既存のデータが失われる可能性があるため注意が必要です。

<?php

$fixedArray = new SplFixedArray(3);
$fixedArray[0] = 'x';
$fixedArray[1] = 'y';
$fixedArray[2] = 'z';

// サイズを5に拡張(既存データは保持される)
$fixedArray->setSize(5);
echo $fixedArray->getSize(); // 5
echo $fixedArray[0];         // x(保持)

// サイズを2に縮小(末尾のデータは失われる)
$fixedArray->setSize(2);
echo $fixedArray->getSize(); // 2
// $fixedArray[2] へのアクセスはエラー

頻繁にサイズ変更が必要な場合は、通常の配列や SplDoublyLinkedList の方が適しています。


通常配列との比較

実際にメモリ使用量を比較してみましょう。

<?php

$size = 100000;

// 通常配列
$before1 = memory_get_usage();
$normalArray = range(0, $size - 1);
$after1 = memory_get_usage();
echo '通常配列: ' . number_format($after1 - $before1) . " bytes\n";

// SplFixedArray
$before2 = memory_get_usage();
$fixedArray = new SplFixedArray($size);
for ($i = 0; $i < $size; $i++) {
    $fixedArray[$i] = $i;
}
$after2 = memory_get_usage();
echo 'SplFixedArray: ' . number_format($after2 - $before2) . " bytes\n";

実行環境によって差はありますが、おおよそ以下のような傾向になります。

種別メモリ使用量の目安
通常配列(100,000要素)約8〜10 MB
SplFixedArray(100,000要素)約4〜5 MB

SplFixedArray は通常配列の 約半分程度のメモリで済む ことが多く、大量データを扱うバッチ処理や数値計算で特に効果を発揮します。


どんなときに使うべきか

SplFixedArray が適しているのは、次のようなケースです。

  • 要素数が事前にわかっているデータを扱う場合
  • 大量の数値データ(行列・ベクトル計算など)を処理する場合
  • メモリ使用量を抑えたいバッチ処理や長時間稼働するプロセス

逆に、要素数が動的に変わる場合や、文字列キーを使いたい場合は通常の配列の方が適しています。


まとめ

SplFixedArray の特徴を整理すると次のとおりです。

  • サイズ固定の配列で、メモリ効率が高い
  • 範囲外アクセス時に例外をスローするため、バグを早期発見しやすい
  • foreach で使えるなど、通常配列に近い使い勝手
  • fromArray() / toArray()相互変換も簡単

PHP標準ライブラリのデータ構造はあまり使われないことも多いですが、適切な場面で活用するとパフォーマンスの改善につながります。ぜひ一度試してみてください。

← 記事一覧に戻る