逐个添加元素时的php数组性能与同时添加所有数据时的性能相比



为了简单起见,我将举一个简单的例子,我有一个$array和一些键和值,我想添加到这个数组中。。主要从性能角度看什么更好:

  1. 将一条语句中的所有键值添加到数组中。或
  2. 一个接一个地做是无害的

1

$array = [
$key1 => $value1, 
$key2 => $value2
];

$array[$key1] = $value1;
$array[$key2] = $value2;

如果你有几个键/值,那么绝对没有区别。如果你处理的数组有100K以上的成员,这确实会产生影响。让我们先构建一些数据:

$r = [];
for($i = 1; $i <= 100000; $i++) {
$r[] = $i; // for numerically indexed array
// $r["k_{$i}"] = $i; // for associative array
// array_push($r, $i); // with function call
}

这将逐个生成一个包含100000成员的数组。当添加数字(自动(索引时,这个循环在我的笔记本电脑上需要~0.0025秒,内存使用量约为6.8MB。如果我使用array_push,它需要~0.0065 sec和函数开销。当$i添加命名密钥时,需要~0.015秒,内存使用量约为12.8MB。然后,命名密钥的定义速度较慢。

但如果你剃了0.015秒到0.012秒,会有什么不同吗或者用^10体积,0.15秒到0.12秒,甚至0.075秒?不是。只有当你有1M以上的会员时,它才会真正开始变得引人注目您实际对该数据量所做的操作将花费更长的时间,并且应该是您优化工作的主要重点。


更新:我准备了三个文件,其中一个文件包含一组来自上面的100K整数;另一个具有单独定义的100K整数;并序列化为JSON。我加载了它们并记录了时间。结果证明存在差异,其中定义";在一个集合中";速度快50%,内存效率更高。此外,如果数据是从JSON反序列化的,则它比包含";本机阵列";。

  • "在一个集合中":0.075 sec9.9MB
  • "作为"分离":0.150 sec15.8MB
  • "从JSON":0.025 sec9.9MB
  • "从MySQL":0.110 sec13.8MB*

然后:如果您以原生PHP格式定义大型数组,请一次性定义,而不是一点一点定义。如果从文件加载大容量数组数据,json_decode(file_get_contents('data.json'), true)加载JSON的速度明显快于使用本机PHP数组定义的include 'data.php';。您的里程数可能会随着更复杂的数据结构而变化,但我预计基本性能模式不会改变。供参考:BitBucket的源数据。

一个奇怪的观察结果:在我们上面的循环中,从头开始生成数据实际上比从具有现成数组的文件中加载/解析数据快得多

MySQL:键值对是从具有PDO的两列表中提取到与具有fetchAll(PDO::FETCH_UNIQUE|PDO::FETCH_COLUMN)的样本数据匹配的数组中的


最佳实践:在定义数据时,如果它是您需要处理的东西,而不是";原油出口/进口";未读取或手动编辑的数据:以使代码易于维护的方式构建数组。我个人认为";"清洁剂";以保持简单阵列";包含":

$data = [
'length' => 100,
'width' => 200,
'foobar' => 'possibly'
];

有时,您的数组需要";"指代自身";以及";逐位";格式是必要的:

$data['length'] = 100;
$data['width'] = 200;
$data['square'] = $data['length'] * $data['width'];

如果你构建多维数组,我会发现它是"清洁剂";将每个";根";数据集:

$data = [];
$data['shapes'] = ['square', 'triangle', 'octagon'];
$data['sizes'] = [100, 200, 300, 400];
$data['colors'] = ['red', 'green', 'blue'];

最后,到目前为止,PHP数组的性能限制因素内存使用(请参阅:数组哈希表内部(,这与构建数组的方式无关。如果您在阵列中有大量数据集,请确保不会让它们的不必要的修改副本在其相关范围之外浮动。否则,你的内存使用率会飙升。


在Win10/PHP 8.1.1/MariaDB 10.3.11@Thinkpad L380上测试。

如果这是一个可疑的瓶颈(可能有数百万个项目?(,我会直接去做一个小的性能测试。请参阅这个小脚本,比较一次array[key = , , ]的多个密钥更新和操作1.000.000次时连续语句array[key] =中的多个单独密钥更新:

$time_start = microtime(true);
$a1 = array();
for ($i = 0; $i < 1000000; ++$i) {
$a1 = [
'key1' => $i, 
'key2' => $i + 1
];
}
$time_end = microtime(true);
printf('Took %f seconds for inline array[key = ]<br>', $time_end - $time_start);

$time_start = microtime(true);
$a2 = array();
for ($i = 0; $i < 1000000; ++$i) {
$a2['key1'] = $i;
$a2['key2'] = $i + 1;
}
$time_end = microtime(true);
printf('Took %f seconds for array[key] = <br>', $time_end - $time_start);

这给了我(每次跑步的画面或多或少都是一样的(:

Took 0.195255 seconds for inline array[key = ]
Took 0.204276 seconds for array[key] =

所以,这真的没关系——你不必担心明显的差异——但在一条语句中更新多个键似乎要快一点。大多数时候,并不是总能保证。

这也正是我们所期望的!从逻辑上考虑:在一条语句中更新数组键的效率略高于通过多条连续语句更新相同的数组键,这只是因为内存中的数组访问次数较少。

最新更新