在PHP中访问大型数组

时间:2012-05-03 15:50:22

标签: php arrays performance

我一直在对PHP中访问大型(ish)数据的不同方法进行一些分析。用例非常简单:我们的一些工具将数据作为关联数组输出到PHP文件中,这些文件被应用程序视为静态数据。我们制作游戏,因此数据文件的一些示例包括目录中的项目,用户必须完成的任务或地图的定义:

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

由于这些数组很大(400K),并且我们的许多代码都对这些数据感兴趣,因此有必要尽可能高效地访问这些数据。我决定为这样做计时3种不同的模式。在介绍方法后,我将在下面分享我的结果。

我正在寻找的是对这些方法及其时间以及任何其他方法进行验证的基于经验的验证。

方法#1:getter函数

在该方法中,导出器实际上创建了一个类似于:

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

客户端代码可以通过在需要时调用getSomeData()来获取数据。

方法#2:global + include

在此方法中,数据文件看起来与上面的原始代码块相同,但是客户端代码必须跳过几个环以将数据放入本地范围。这假设数组位于名为“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内存,PHP版本5.3.4):

<方法#1:
  

AVG:0.0031637034416199   最大值:0.0043289661407471   MIN:0.0025908946990967

<方法#2:
  

AVG:0.01434082698822   MAX:0.018275022506714   MIN:0.012722969055176

<方法#3:
  

AVG:0.00335768699646   最大值:0.0043489933013916   MIN:0.0029017925262451

从这个数据来看,似乎很清楚,全局+包括方法不如其他两个,这是“可忽略的”差异。

思考? 我完全错过了什么吗? (可能...)

提前致谢!

2 个答案:

答案 0 :(得分: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和inmemory引擎,然后从那里访问数据:

$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// .. Use PDO as normal

答案 1 :(得分:3)

对于我的一个项目,其中一个数据库不是一个选项,我遇到了同样的问题,加载大(我的意思是系列3 MB文件)php文件包含内存中的数组,我正在寻找最大化的选项表演。我找到了一个非常简单的方法,它首先使用json将这些文件缓存在磁盘上。我将加载时间除以3,内存峰值消耗除以30%。使用json_decode()加载本地json文件比包含一个包含数组的大型php文件要快得多。它还具有大多数语言可以直接操作的格式的优点。希望有所帮助。