PHP SimpleXML大文件无额外内存使用

PHP SimpleXML大文件无额外内存使用,php,memory,simplexml,Php,Memory,Simplexml,在每一篇关于SimpleXML性能和内存使用的文章中,都提到所有解析的内容都存储在内存中,处理大型文件将导致大量内存使用。 但最近我发现,使用SimpleXML处理大型文件不会导致大量内存使用,甚至不会导致几乎无内存使用。 这是我的测试脚本: <?php error_reporting(E_ALL); ini_set("display_errors", 1); print "OS: " . php_uname() . "\n"; print "PHP version: " . phpver

在每一篇关于SimpleXML性能和内存使用的文章中,都提到所有解析的内容都存储在内存中,处理大型文件将导致大量内存使用。 但最近我发现,使用SimpleXML处理大型文件不会导致大量内存使用,甚至不会导致几乎无内存使用。 这是我的测试脚本:

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
print "OS: " . php_uname() . "\n";
print "PHP version: " . phpversion() . "\n";

print round(memory_get_usage() / 1024 / 1024, 2) . " Mb\n";
$large_xml = '<?xml version="1.0" encoding="UTF-8"?><catalog><products>';
for ($i = 0; $i < 500000; $i++) {
    $large_xml .= "<product><id>{$i}</id><name>Product Name {$i}</name><description>Some Description {$i}</description><price>{$i}</price></product>\n";
}
$large_xml .= "</products></catalog>";
print round(memory_get_usage() / 1024 / 1024, 2) . " Mb\n";
$products_sxml = simplexml_load_string($large_xml);
print round(memory_get_usage() / 1024 / 1024, 2) . " Mb\n";
?>

我在Linux服务器上测试这个脚本,PHP版本:5.3.8,输出为:

操作系统:Linux 2.6.32-5-amd64#1 SMP周一2月25日00:26:11 UTC 2013 x86_64

PHP版本:5.3.8

0.6MB

65.98 Mb

65.98 Mb


所以我的问题是——有没有其他人注意到了它,有什么可以解释它,因为我在网上找不到任何地方对它的解释——甚至没有对它的确认?

如果我执行脚本,我会得到完全相同的结果。 一种解释是,您没有使用XML对象,因此XML字符串甚至没有被完全解析。 修改脚本以便将数据发送到浏览器
print\r($products\u sxml)调用后内存使用率要高得多。

显然,您应该减少xml中的产品数量。

PHP的内存管理功能非常复杂,准确测量特定高级代码的影响非常困难。Julien Pauli在PHP英国会议上对此进行了非常好的(非常技术性的)讨论

memory\u get\u usage
可能对您撒谎的原因如下:

  • 首先,
    memory\u get\u usage
    采用一个可选参数
    $real\u usage
    ,它区分分配的内存量和使用的内存量-内存管理器一次分配一个内存块,因此它通常会从操作系统索取比实际使用的更多的内存。当需要更多的内存时,已经声明的内存将被用完,这意味着不再需要分配更多的内存。这种情况下的测试表明,这与此无关
  • 一般来说,在运行PHP的底层C代码中有不同的内存分配方式。由于SimpleXML的大部分工作不是在Zend引擎中完成的,而是在名为libxml2的第三方库中完成的,因此内存分配将在那里完成,而不是在特定于PHP的分配例程中完成,例如,在附加到PHP字符串时将使用这些例程
我从Julien Pauli的幻灯片中获取了以下函数,它查看Linux内核对正在运行的PHP进程的视图,并找到表示“驻留集大小”的行,即实际分配的物理内存量,而不是进程要求保留的内存量:

function heap() {
    return shell_exec(sprintf('grep "VmRSS:" /proc/%s/status', getmypid()));
}
在示例代码中添加对此的调用(以及
get\u memory\u usage(true)
),我得到了以下输出,显示了解析XML时“heap”内存的重要分配:

OS:Linux粉红果酱3.8.0-29-generic#42~precise1 Ubuntu SMP周三8月14日16:19:23 UTC 2013 x86_64
PHP版本:5.3.10-1ubuntu3.8
内存获取使用率():0.61 Mb
内存使用率(真):0.75 Mb
堆:VmRSS:6956 kB
内存获取使用率():65.99 Mb
内存使用率(真):66.25 Mb
堆:VmRSS:74348KB
内存获取使用率():65.99 Mb
内存使用率(真):66.25 Mb
堆:VmRSS:761836KB

SimpleXML将XML树存储在一个外部资源中,该资源不包含在get\u memory\u usage函数中。

欢迎使用SO。请考虑让问题尽可能简单。要理解您的问题需要两到三次阅读。问题是-有人能解释一下为什么在使用SimpleXML处理大型XML文件时没有额外的内存使用吗-因为在每一篇关于SimpleXML的文章中,大型内存使用都被提到是最大的缺点。您可以添加像foreach这样的XML处理代码($products_sxml->products->product as$product_sxml){$product_count++}您将看到内存使用率没有增加。问题不是XML文件大小,而是使用SimpleXML处理XML文件时没有额外的内存使用。