需要在PHP中的数组状结构以最小的内存使用情况 [英] Need an array-like structure in PHP with minimal memory usage

查看:136
本文介绍了需要在PHP中的数组状结构以最小的内存使用情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的PHP脚本我需要创建> 600K整型数组。不幸的是我的网络服务器 memory_limit的设置为32M让初始化脚本消息中止阵列时


  

致命错误:允许内存用尽33554432字节大小(试图分配71字节)的 /home/www/myaccount/html/mem_test.php 行< STRONG> 8


我知道的事实,PHP不数组的值存储为普通整数,而是作为zvalues​​它比普通整型值(我的64位系统上的8个字节)更大。我写了一个小脚本来估计每个数组项使用的内存和事实证明,它的pretty正好是128个字节。 128!我需要> 73M只是存储阵列。不幸的是,网络服务器是不是我的控制之下,所以我不能增加 memory_limit的

我的问题是,有没有在PHP中的任何可能性,以创建一个使用较少的内存阵列状结构。我不需要这个结构是联想(纯索引访问就足够了)。它也不需要有动态调整 - 我知道数组将准确多大。此外,所有元件将是相同的类型。就像一个好的旧的C数组。


编辑:
因此, deceze 的解决方案工作外的开箱即用的32位整数。但是,即使你是一个64位系统上,包()似乎不支持64位整数。为了在我的阵列中使用的64位整数我申请了一些位操作。也许下面的代码片段将是有人帮助:

 函数的push_back(安培; $存储,$值)
{
    //拆分的64位值分为两个32位的块,然后将这些打包()。
    。$存储=包(LL,($值&GT;&GT; 32),$值);
}功能GET(安培; $存储,$ IDX)
{
    //读取存储$ 2个32位的块和胶水他们重新走到一起。
    返回(电流(解包(L,SUBSTR($存储,$ IDX * 8,4)))≤;&下; 32 |
            电流(解包(L,SUBSTR($存储,$ IDX * 8 + 4,4))));
}


解决方案

最有效的记忆,你会得到可能是通过存储在一个字符串中的一切,装在二进制,而使用手动索引到它。

  $存储='';$存储=包(L,42);// ...//获得10项
$ INT =电流(解包(L,SUBSTR($存储,9 * 4,4)));

这可能是可行的,如果将​​数组初始化可以一举做,你只是从结构看。如果你需要大量的追加到字符串,这成为极其低效。即使这可以使用一个资源句柄虽然完成:

  $存储=的fopen('PHP://记忆,R +);
FWRITE($存储组(L,42));
...

这是非常有效的。然后,您可以读取这个缓冲区回一个变量,并把它作为字符串,也可以继续与资源工作和 fseek的

In my PHP script I need to create an array of >600k integers. Unfortunately my webservers memory_limit is set to 32M so when initializing the array the script aborts with message

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 71 bytes) in /home/www/myaccount/html/mem_test.php on line 8

I am aware of the fact, that PHP does not store the array values as plain integers, but rather as zvalues which are much bigger than the plain integer value (8 bytes on my 64-bit system). I wrote a small script to estimate how much memory each array entry uses and it turns out, that it's pretty exactly 128 bytes. 128!!! I'd need >73M just to store the array. Unfortunately the webserver is not under my control so I cannot increase the memory_limit.

My question is, is there any possibility in PHP to create an array-like structure that uses less memory. I don't need this structure to be associative (plain index-access is sufficient). It also does not need to have dynamic resizing - I know exactly how big the array will be. Also, all elements would be of the same type. Just like a good old C-array.


Edit: So deceze's solution works out-of-the-box with 32-bit integers. But even if you're on a 64-bit system, pack() does not seem to support 64-bit integers. In order to use 64-bit integers in my array I applied some bit-manipulation. Perhaps the below snippets will be of help for someone:

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))));
}

解决方案

The most memory efficient you'll get is probably by storing everything in a string, packed in binary, and use manual indexing to it.

$storage = '';

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

// ...

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

This can be feasible if the "array" initialisation can be done in one fell swoop and you're just reading from the structure. If you need a lot of appending to the string, this becomes extremely inefficient. Even this can be done using a resource handle though:

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

This is very efficient. You can then read this buffer back into a variable and use it as string, or you can continue to work with the resource and fseek.

这篇关于需要在PHP中的数组状结构以最小的内存使用情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆