Mah*_*ahn 11 php apc large-data
想象一下,你有以下整数数组:
array(1, 2, 1, 0, 0, 1, 2, 4, 3, 2, [...] );
Run Code Online (Sandbox Code Playgroud)
整数最多可达一百万条; 它们不是硬编码而是预先生成并存储在JSON格式的文件中(大小约为2MB).这些整数的顺序很重要,我不能每次都随机生成它,因为它应该是一致的,并且在相同的索引处始终具有相同的值.
如果这个文件之后在PHP中被回读(例如使用file_get_contents
+ json_decode
),则需要700到900毫秒来恢复数组 - "好的"我想,"它可能是合理的,因为json_decode
必须解析大约200万个字符,让我们缓存它" .APC将其缓存在大约68MB的条目中,可能正常,zval很大.然而从APC取回这个阵列也需要一些好的600毫秒,这在我眼中仍然太多了.
编辑:APC确实序列化/反序列化以存储和检索具有一百万个项目数组的内容是一个漫长而繁重的过程.
所以问题:
如果我打算在PHP中加载一百万条数组,无论是数据存储还是方法,我都应该期待这种延迟吗?据我所知,APC存储zval本身,所以理论上从APC中检索它应该尽可能快(没有解析,没有转换,没有磁盘访问)
为什么APC对于看似简单的事情这么慢?
有没有有效的方法使用PHP在内存中完全加载一百万个条目数组?假设RAM使用不是问题.
如果我只根据索引访问这个数组的片段(例如将块从索引15加载到索引76)并且实际上从未将整个数组放在内存中(是的,我知道这是理智的做法,但是我想知道所有方面),整个阵列最有效的数据存储系统是什么?显然不是RDBM; 我在想redis,但我很乐意听到其他想法.
假设整数都是 0-15。然后每个字节可以存储 2 个:
<?php
$data = '';
for ($i = 0; $i < 500000; ++$i)
$data .= chr(mt_rand(0, 255));
echo serialize($data);
Run Code Online (Sandbox Code Playgroud)
跑步:php ints.php > ints.ser
现在您有一个包含 500000 字节字符串的文件,其中包含 1,000,000 个从 0 到 15 的随机整数。
加载:
<?php
$data = unserialize(file_get_contents('ints.ser'));
function get_data_at($data, $i)
{
$data = ord($data[$i >> 1]);
return ($i & 1) ? $data & 0xf : $data >> 4;
}
for ($i = 0; $i < 1000; ++$i)
echo get_data_at($data, $i), "\n";
Run Code Online (Sandbox Code Playgroud)
我的机器上的加载时间约为 0.002 秒。
当然,这可能并不直接适用于您的情况,但它会比包含一百万个条目的臃肿 PHP 数组快得多。坦率地说,在 PHP 中拥有这么大的数组从来都不是正确的解决方案。
我并不是说这就是正确的解决方案,但如果它适合您的参数,它绝对是可行的。
请注意,如果您的数组包含 0-255 范围内的整数,您可以摆脱包装并仅以ord($data[$i])
. 在这种情况下,您的字符串长度将为 1M 字节。
最后,根据 的文档file_get_contents()
,php将对该文件进行内存映射。如果是这样,您的最佳性能是将原始字节转储到文件中,并按如下方式使用它:
$ints = file_get_contents('ints.raw');
echo ord($ints[25]);
Run Code Online (Sandbox Code Playgroud)
这假设ints.raw
长度正好是一百万字节。