【问题标题】:unpack(C*,data) Eats Memory [php exhausting memory on unpack function]unpack(C*,data) Eats Memory [php 在 unpack 函数上耗尽内存]
【发布时间】:2014-04-06 13:38:58
【问题描述】:

我想按照here i unpack'ed fread's output 的建议在 php 中将二进制文件读取为 byte[] 。所以我有类似的东西:

$file=fopen($filename,'r');
fseek($file, $offset);  //file is 500MB so i take it 10MB at a time
$tmp = fread($file,$len);
//so far so good , $tmp includes 10MB of data
var_dump(strlen($tmp));    //int(10485760) 10MB
var_dump(memory_get_usage(true)); //int(11272192) 11MB
$data = unpack('C*',$tmp);

这会抛出

PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 32 bytes) in [myfile.php] on line [unpack line]

因为错误表明内存限制设置为 512MB,根据memory_get_usage,仅使用了 11/512MB,我正在解压 10MB 字符串。最多它应该需要 30MB(10MB 用于 $tmp ,10MB 用于 $data 和 10MB 用于内部变量)。为什么它会爆炸并且无法用 512MB ram 解压 $tmp ?

所以问题是,我在这里做错了什么还是一个错误?还有没有其他方法可以让一个字节数组(0到255)来读取php中的二进制文件,还是我应该切换到另一种语言来做到这一点?

附加说明:该代码适用于 117KB 文件。

php -v
PHP 5.5.3-1ubuntu2.2 (cli) (built: Feb 28 2014 20:06:05) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
    with Zend OPcache v7.0.3-dev, Copyright (c) 1999-2013, by Zend Technologies

【问题讨论】:

    标签: php memory fread unpack


    【解决方案1】:

    在 PHP 中,变量在内部存储为 zval。数组中的每个元素将占用比您预期更多的内存。这是因为 PHP 是一种弱类型语言,因此需要能够在内部快速交换变量的类型。还有 GC 的开销以及 PHP 中的数组实际上是一个哈希表这一事实。

    您可以在此处找到详细信息:

    http://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html

    然而,创建一个包含 10485760 个元素的数组需要大约32 位为 760MB,64 位为 1440MB。

    您最好的选择是最有可能不解压缩字符串,而是当您需要数组中的某个元素来访问字符串中的某个位置时。

    例如,您可以使用使用此概念的库:

    https://github.com/reiner-dolp/PHP-Memory-Efficient-Arrays

    【讨论】:

    • 我看过“内存高效数组”,似乎只有一个问题。如何将 10MB 字符串转换为 ByteArray ?换句话说,一个与你说的 lib 一起工作的解包函数的替代品。
    猜你喜欢
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 2013-08-23
    • 1970-01-01
    • 2014-09-08
    • 2015-12-19
    相关资源
    最近更新 更多