我有一大堆关联数组。每个关联数组由大约15个不同类型的键组成(字符串,整数,浮点数) - 下面的小例子:
$array = [
[
"key1" => "string",
"key2" => 10,
"key3" => 4.05
],
[
"key1" => "string2",
"key2" => 20,
"key3" => 1.05
],
...
];
现在我想迭代这个数组并添加一些像
这样的键$map = array_map(function (array $item) {
$item['key4'] = 1;
$item['key5'] = 1;
$item['key6'] = 1;
return $item;
}, $array);
问题:对于包含大量关联数组的数组,添加新键会使达到内存限制并终止脚本。你有任何解决方案吗?
答案 0 :(得分:2)
您可以对数据进行分页,对数组进行分块以处理较小的数据,甚至可以增加memory_limit,但我们假设您有一个大数组,但不能这样做。
让我们玩一个1 000 000长阵列并尝试不同的解决方案。我会把内存消耗和放大从笔记本电脑计算时间测量值
for ($i=0; $i< 1000000; $i++){
$array[$i] = [
"key" => 'value',
"key2" => $i,
"key3" => $i / 3
];
}
$map = array_map(function (array $item) {
$item['key4'] = 1;
$item['key5'] = 1;
$item['key6'] = 1;
return $item;
}, $array);
使用这段代码,我的笔记本电脑的内存消耗 857MB,计算时间为640ms 。
在您的示例中,您要从$map
创建一个全新的$array
变量。这意味着您正在内存中制作数组的新副本。
$array = [];
for ($i=0; $i< 1000000; $i++){
$array[$i] = [
"key" => 'value',
"key2" => $i,
"key3" => $i / 3
];
}
foreach ($array as &$item) {
$item['key4'] = 1;
$item['key5'] = 1;
$item['key6'] = 1;
}
使用&$item
我们要求PHP通过引用让我们访问变量,这意味着我们直接在内存中修改数据而不创建它的新副本。
这就是为什么这个脚本消耗的内存和内存要少得多。计算时间。
在幕后,PHP使用C数据结构来管理内存中的数据。对于PHP来说,类比数组更容易预测且更容易优化。很好地解释了here
class TestClass {
public $key1, $key2, $key3, $key4, $key5, $key6;
}
$array = [];
for ($i=0; $i< 1000000; $i++){
$array[$i] = new TestClass();
$array[$i]->key1 = 'value';
$array[$i]->key2 = $i;
$array[$i]->key3 = $i / 3;
}
foreach ($array as $item) {
$item->key4 = 1;
$item->key5 = 1;
$item->key6 = 1;
}
你可以看到内存消耗&amp;迭代的时间要低得多。这是因为PHP不需要修改内存中数据的结构:对象的每个字段都准备好接收数据。
但要小心,如果添加一个未在类中声明的字段(例如$item->newKey = 1
:动态声明newKey):将无法再进行内存优化,您将跳转到620mb内存使用量&amp; 280ms计算)
如果你想更进一步,不怕头痛,请看一下Standard PHP Library(SPL):你会发现很多优化的数据结构解决方案(固定阵列,迭代器等等)。 ..)
PS:禁用Xdebug的基准测试
答案 1 :(得分:-1)
如果您使用引用,您应该能够节省一些内存。这将删除在后台发生的写入操作的许多副本。在一个小测试案例中。我能够将内存减少30%-40%(取决于PHP版本)。如果您使用PHP5,您还可以从升级到PHP7中获益。显然我无法预测其中一个或两个是否能够保存足够的内存。
测试用例(只需在地图或步行之前删除$(".hideme_sometimes").hide();
):
/*