在尝试跟踪PHP中的一些内存问题时,我注意到我在日志代码中调用的debug_backtrace()
似乎使用了大量内存。
在大多数情况下,以下代码会打印0.02 MB
之类的内容。但在一个案例中,它会打印171.85 MB
!
$before = memory_get_usage();
$backtrace = debug_backtrace(false);
$after = memory_get_usage();
echo round(($after - $before)/1024/1024, 2)." MB";
我的问题是,这是否意味着debug_backtrace
实际上正在使用那么多内存?或者可能发生其他事情,比如垃圾收集,会弄乱memory_get_usage
的返回值?
答案 0 :(得分:7)
它最有可能导致膨胀的物体。尝试将false
传递给函数,这样就不会拉动对象,而且跟踪会更小。
编辑:如果传递false
不起作用,那么如果你运行PHP 5.3.6+,你可以使用位掩码来限制函数返回的内容。它听起来像是你把对象作为巨大的args传递。
http://php.net/manual/en/function.debug-backtrace.php Reference
此外,如果你使用PHP 5.4.0+,他们添加了第二个参数,允许你限制堆栈帧数。
EDIT2:总计<< HACK >>在这里,但工作...添加一个try / catch,抛出异常并捕获它然后转换为字符串或调用异常getTraceAsString()来获得完整的堆栈。例如:
try {
throw new Exception('ignore this string');
} catch(Exception $e) {
/* @var $trace array */
$trace = $e->getTrace();
// OR
/* @var $str string */
$str = $e->getTraceAsString();
$e = null;
}
在上面的剪辑中,您可以使用$trace
并构建自己的输出,或者只使用标准异常作为字符串$str
。更容易获得堆栈帧输出。
答案 1 :(得分:4)
好的,我想我明白了。我打印出了回溯,"args"
数组很大。这是因为我传递了一些巨大的字符串。我猜它在返回结果时会复制它们(而不是引用)。
例如:
function test($str) {
test2($str);
}
function test2($str) {
test3($str);
}
function test3($str) {
echo "before: ".round(memory_get_usage()/1024/1024, 2)." MB\n";
debug_backtrace(false);
echo "after: ".round(memory_get_usage()/1024/1024, 2)." MB\n";
}
test(str_repeat('a', 10000000));
使用和不使用debug_backtrace()调用尝试此操作。有了它,内存使用量增加了大约28 MB。它只在test3()返回时清除。
答案 2 :(得分:2)
如果您的代码是递归的,并且您深入到递归中,则回溯必须存储每次递归的数据...