在PHP中访问大数组

在PHP中访问大数组,php,arrays,performance,Php,Arrays,Performance,我一直在对PHP中访问大型(ish)数据数组的不同方法进行分析。用例非常简单:我们的一些工具将数据作为关联数组输出到PHP文件中,这些文件被应用程序视为静态数据。我们制作游戏,因此一些数据文件示例包括目录中的项目、用户必须完成的任务或地图定义: <?php $some_data = array( ...lots and lots of stuff in here... ); ?> 这将使$some_数据数组进入范围,尽管它对于客户端代码来说有点麻烦(我的意见) 方法#3:引

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

<?php
$some_data = array(
    ...lots and lots of stuff in here...
);
?>
这将使$some_数据数组进入范围,尽管它对于客户端代码来说有点麻烦(我的意见)

方法#3:引用getter 此方法与方法#1几乎相同,但是getter函数不返回值,而是设置对数据的引用

<?php
function getSomeDataByRef($some_data)
{
    $some_data = array(
        ...lots and lots of stuff here...
    );
    return $some_data;
}
?>
结果 所以我运行了一个小脚本,它将这些检索数据的方法运行1000次,并平均运行时间(在开始和结束时由microtime(true)计算)。以下是我的结果(以毫秒为单位,在MacBookPro 2GHz、8GB RAM、PHP版本5.3.4上运行):

方法#1: 平均值:0.00316374416199 最大值:0.0043289661407471 最小值:0.0025908946967

方法2: 平均值:0.01434082698822 最大值:0.018275022506714 最小值:0.012722969055176

方法#3: 平均值:0.00335768699646 最大值:0.0043489933019316 最小值:0.0029017925262451

不管怎么说,从这些数据来看,似乎相当清楚的是,global+include方法不如其他两种方法,这两种方法的差别“可以忽略不计”

想法? 我完全错过了什么吗?(可能……)


提前谢谢

不确定这是否正是您想要的,但它应该有助于解决速度和内存问题。您可以使用固定spl阵列:

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

在我的一个项目中,数据库不是一个选项,我面临着同样的问题,即在内存中加载包含数组的大型(我指的是一系列3MB文件)php文件,我正在寻找能够最大限度地提高性能的选项。我发现了一个非常简单的方法,即在第一次使用时将这些文件作为json缓存在磁盘上。我将加载时间除以3,内存峰值消耗也除以30%。使用json_decode()加载本地json文件比包含包含数组的大型php文件快得多。它还有一个优点,就是大多数语言都可以直接操作这种格式。希望能有所帮助。

首先,这是一个非常好的问题。我很高兴看到有人阅读这些常见问题。其次,我认为最好使用数据结构和对象。也就是说,一个
Task
类来描述任务,
Level
来描述级别(可能还有
Task
对象?),
Player
来描述玩家等等,都比一个关联数组强。你能解释一下为什么要使用PHP文件作为数据存储吗?为什么不将数据存储在RDBMS(或等效物)中并从那里访问它呢?也许我误解了,但似乎您正在生成PHP文件来存储数据?您的引用方式是错误的。
&
应该在函数声明中,不推荐使用按引用传递调用时间-即它应该是
函数getSomeDataByRef(&$some_data)
getSomeDataByRef($some_data_anyname)。还请注意,将传递的变量预先声明为数组是不必要的<代码>包含总是效率较低,因为它必须再次启动解析器。我怀疑其他版本的差异可以忽略不计的原因是,第一个版本仍将作为写时拷贝实现,并且不需要返回值的内存拷贝。返回数组,而不是将其分配给
$some_data
,只需使用
$some_data=include('some_data'))
出于性能原因,我们决定使用关联数组而不是对象。我理解这些原因可能会也可能不会被PHP5揭穿,但这一决定不太可能改变。RDBMS没有用于类似的性能原因:在实践中,建立连接和运行查询只会降低我们的速度。我们确实会在一定程度上缓存数据,我想我对此并不清楚……也就是说,对于给定的类/web服务,我们只会在其构造函数中“获取”一次数据。我感兴趣的是以最快的方式将数据纳入范围。谢谢。虽然我通常倾向于使用数组来处理较小的事情,比如配置、批量导入等等,但您应该将对数据的访问包装到一些懒散的数组或StreamArray对象中,这些对象一次在内存中的大小永远不会超过固定的卡盘大小。如果您实现了一个迭代器,您仍然可以进行全局搜索或对整个内容进行键控访问,只需要先迭代几次,或者像一个好的解决方案一样实现。在我的测试中,解析json文件并将其作为数组获取比作为对象获取快10%左右。
<?php
function getSomeDataByRef($some_data)
{
    $some_data = array(
        ...lots and lots of stuff here...
    );
    return $some_data;
}
?>
$some_data_anyname = array();
getSomeDataByRef(&$some_data_anyname);
$startMemory = memory_get_usage();
$array = new SplFixedArray(100000);
for ($i = 0; $i < 100000; ++$i) {
    $array[$i] = $i;
}
echo memory_get_usage() - $startMemory, ' bytes';
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// .. Use PDO as normal