unpack(C *,data)吃内存[解压缩功能的php耗尽内存]

时间:2014-04-06 13:38:58

标签: php memory fread unpack

我想在php中读取二进制文件为byte [],如建议here i unpack'ed fread的输出。所以我有类似的东西:

$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($ tmp为10MB,$ data为10MB,内部变量为10MB)。它为什么爆炸,无法用512MB内存解压缩$ 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

1 个答案:

答案 0 :(得分:2)

在PHP中,变量在内部存储为zvals。数组中的每个元素将占用比预期更多的内存。这是因为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