在 PHP 中需要一个类似数组的结构,并且内存使用量最小

在我的PHP脚本中,我需要创建一个>600k整数数组。不幸的是,我的Web服务器设置为32M,因此在初始化数组时,脚本会中止并显示消息memory_limit

致命错误:允许内存大小为 33554432 字节已耗尽(尝试分配 71 个字节)在第 8 行的 /home/www/myaccount/html/mem_test.php

我知道这样一个事实,PHP不会将数组值存储为纯整数,而是存储为比普通整数值大得多的zvalues(在我的64位系统上为8个字节)。我写了一个小脚本来估计每个数组条目使用多少内存,结果发现它正好是128字节。128!!!我需要>73M来存储数组。不幸的是,Web服务器不在我的控制之下,所以我无法增加.memory_limit

我的问题是,在PHP中是否有可能创建一个使用更少内存的类似数组的结构。我不需要这个结构是关联性的(普通的索引访问就足够了)。它也不需要动态调整大小 - 我确切地知道数组的大小。此外,所有元素的类型都相同。就像一个很好的老式C阵列。


编辑:因此,deceze的解决方案使用32位整数开箱即用。但即使您使用的是 64 位系统,pack() 似乎也不支持 64 位整数。为了在我的数组中使用64位整数,我应用了一些位操作。也许下面的片段会对某人有所帮助:

function push_back(&$storage, $value)
{
    // split the 64-bit value into two 32-bit chunks, then pass these to pack().
    $storage .= pack('ll', ($value>>32), $value);
}

function get(&$storage, $idx)
{
    // read two 32-bit chunks from $storage and glue them back together.
    return (current(unpack('l', substr($storage, $idx * 8, 4)))<<32 |
            current(unpack('l', substr($storage, $idx * 8+4, 4))));
}

答案 1

您将获得的最高效的内存可能是将所有内容存储在字符串中,打包成二进制文件,然后对其使用手动索引。

$storage = '';

$storage .= pack('l', 42);

// ...

// get 10th entry
$int = current(unpack('l', substr($storage, 9 * 4, 4)));

如果“数组”初始化可以一举完成,并且您只是从结构中读取,那么这可能是可行的。如果您需要向字符串追加大量内容,这将变得非常低效。即使这样,也可以使用资源句柄来完成:

$storage = fopen('php://memory', 'r+');
fwrite($storage, pack('l', 42));
...

这是非常有效的。然后,您可以将此缓冲区读回变量并将其用作字符串,也可以继续使用资源和 。fseek


答案 2

PHP Judy Array将使用比标准PHP数组和SplFixedArray少得多的内存。

我引用“使用常规PHP数组数据结构的100万个条目的数组需要200MB。SplFixedArray使用大约90兆字节。朱迪使用8兆。权衡在于性能,Judy花费的时间大约是常规php数组实现的两倍。