在每篇关于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,输出是:
OS:Linux 2.6.32-5-amd64#1 SMP Mon Feb 25 00:26:11 UTC 2013 x86_64
PHP版本:5.3.8
0.6 Mb
65.98 Mb
65.98 Mb
所以我的问题是 - 是否有其他人已经注意到它以及可能对此有何解释,因为我无法在网络上的任何地方找到它的解释 - 甚至没有确认它?
答案 0 :(得分:4)
PHP的内存管理功能非常复杂,准确测量特定高级代码的影响非常困难。 Julien Pauli在PHP英国会议上发表了非常好(非常技术性)的演讲,a video of which is available here。
memory_get_usage
可能对您说谎的原因有几个:
memory_get_usage
采用$real_usage
的可选参数,该参数区分已分配的内存量和正在使用的 - 内存管理器一次为一个块分配内存,因此它通常会从操作系统中获得比实际使用中更多的内容。由于需要更多,已经声明的内存已用完,这意味着不再需要分配内存。在这种情况下进行测试表明这与此无关。我从Julien Pauli的幻灯片中获取了以下函数,该幻灯片查看Linux内核对正在运行的PHP进程的视图,并找到代表“Resident Set Size”的行 - 实际已分配的物理内存量,而不是超过要求保留的流程金额:
function heap() {
return shell_exec(sprintf('grep "VmRSS:" /proc/%s/status', getmypid()));
}
在示例代码中添加对此(以及get_memory_usage(true)
)的调用,我得到以下输出,显示解析XML时“堆”内存的重要分配:
OS: Linux pink-marmalade 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 16:19:23 UTC 2013 x86_64
PHP version: 5.3.10-1ubuntu3.8
memory_get_usage(): 0.61 Mb
memory_get_usage(true): 0.75 Mb
Heap: VmRSS: 6956 kB
memory_get_usage(): 65.99 Mb
memory_get_usage(true): 66.25 Mb
Heap: VmRSS: 74348 kB
memory_get_usage(): 65.99 Mb
memory_get_usage(true): 66.25 Mb
Heap: VmRSS: 761836 kB
答案 1 :(得分:0)
如果我执行脚本,我会得到完全相同的结果。
一种解释可能是您不使用XML对象,因此甚至不会完全解析xml字符串。
修改脚本以便将数据发送到浏览器print_r($products_sxml);
时,调用后内存使用量会大大增加。
你应该明显减少xml中的产品数量。
答案 2 :(得分:0)
SimpleXML将XML树存储在外部资源中,该资源不包含在get_memory_usage函数中。