为什么debug_backtrace()使用这么多内存?

时间:2011-03-03 02:24:14

标签: php memory

在尝试跟踪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的返回值?

3 个答案:

答案 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)

如果您的代码是递归的,并且您深入到递归中,则回溯必须存储每次递归的数据...