18

私は、PHP で大きな (っぽい) データ配列にアクセスするさまざまな方法についてプロファイリングを行ってきました。使用例は非常に単純です。一部のツールはデータを連想配列として PHP ファイルに出力し、これらのファイルはアプリケーションによって静的データと見なされます。私たちはゲームを作成しているため、データ ファイルの例には、カタログ内のアイテム、ユーザーが完了する必要があるタスク、またはマップの定義が含まれます。

<?php
$some_data = array(
    ...lots and lots of stuff in here...
);
?>

これらの配列はかなり大きく (400K)、コードの多くはこのデータに関心があるため、このデータにできるだけ効率的にアクセスする必要があります。これを行うための 3 つの異なるパターンのタイミングに落ち着きました。メソッドを提示した後、以下に結果を共有します。

私が探しているのは、これらの方法とそのタイミング、および試してみる他の方法に関する経験に基づく検証です。

方法 #1: ゲッター関数

このメソッドでは、エクスポーターが実際に次のようなファイルを作成します。

<?php
function getSomeData()
{
    $some_data = array(
        ...lots and lots of stuff here...
    );
    return $some_data;
}
?>

クライアントコードは、必要なときに getSomeData() を呼び出すだけでデータを取得できます。

方法 #2: グローバル + インクルード

この方法では、データ ファイルは上記の元のコード ブロックと同じように見えますが、クライアント コードはデータをローカル スコープに取得するためにいくつかの手順を実行する必要があります。これは、配列が「some_data.php」というファイルにあることを前提としています。

global $some_data; //must be the same name as the variable in the data file...
include 'some_data.php';

これにより、$some_data 配列がスコープに含まれますが、クライアント コードでは少し面倒です (私の意見です)。

方法 #3: 参照によるゲッター

このメソッドはメソッド 1 とほぼ同じですが、getter 関数は値を返さず、データへの参照を設定します。

<?php
function getSomeDataByRef($some_data)
{
    $some_data = array(
        ...lots and lots of stuff here...
    );
    return $some_data;
}
?>

次に、クライアント コードはローカル変数 (任意の名前) を宣言し、getter への参照によって渡すことによってデータを取得します。

$some_data_anyname = array();
getSomeDataByRef(&$some_data_anyname);

結果

そこで、データを取得するこれらの各メソッドを 1000 回実行し、実行時間を平均化する小さなスクリプトを実行しました (最初と最後に microtime(true) で計算)。以下は私の結果です (ミリ秒単位、MacBookPro 2GHz、8GB RAM、PHP バージョン 5.3.4 で実行):

方法 #1:

平均: 0.0031637034416199 最大: 0.0043289661407471 最小: 0.0025908946990967

方法 #2:

平均: 0.01434082698822 最大: 0.018275022506714 最小: 0.012722969055176

方法 #3:

平均: 0.00335768699646 最大: 0.0043489933013916 最小: 0.0029017925262451

いずれにせよ、このデータから、global+include メソッドが他の 2 つよりも劣っていることは明らかです。これらは「無視できる」違いです。

考え?私は何かを完全に見逃していますか?(おそらく...)

前もって感謝します!

4

2 に答える 2

9

これがまさにあなたが探しているものかどうかはわかりませんが、速度とメモリの問題に役立つはずです. 固定 spl 配列を使用できます。

$startMemory = memory_get_usage();
$array = new SplFixedArray(100000);
for ($i = 0; $i < 100000; ++$i) {
    $array[$i] = $i;
}
echo memory_get_usage() - $startMemory, ' bytes';

大きな php 配列の詳細については、http: //nikic.github.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.htmlをご覧ください。

また、データをキャッシュ/メモリに保存することを考えましたか? たとえば、最初の実行で mysqlite をインメモリ エンジンと共に使用し、そこからデータにアクセスできます。

$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// .. Use PDO as normal
于 2012-05-03T15:54:25.520 に答える
3

データベースがオプションではない私のプロジェクトの 1 つで、メモリ内の配列を含む大きな (3 MB のファイルのシリーズを意味する) php ファイルをロードするという同じ問題に直面し、パフォーマンスを最大化するオプションを探していました。最初の使用時にこれらのファイルを json としてディスクにキャッシュする非常に簡単なものを見つけました。読み込み時間を 3 で割り、メモリのピーク消費量を 30% で割りました。json_decode() を使用してローカルの json ファイルをロードすることは、配列を含む大きな php ファイルを含めるよりもはるかに高速です。また、ほとんどの言語が直接操作できる形式であるという利点もあります。それが役立つことを願っています。

于 2014-06-27T15:40:52.383 に答える