`get_defined_vars()` 的性能影响是什么?

What is the performance impact off `get_defined_vars()`?

我经常看到关于 SO 的问题 answers/solutions 包括 get_defined_vars() 的使用,或互联网上使用该方法的博客文章。在大多数情况下,它用于调试目的,但在某些情况下,似乎作者有意在生产代码中使用它。

虽然我很少使用该功能,因为它让我感觉不舒服,但我想知道在 PHP 应用程序中使用该功能对实际性能有何影响。

它的一个 example 用法可能是查看变量是否明确设置为 NULL:

//$implicit_null = 1234;
$explicit_null = NULL;

var_dump(is_null($implicit_null)); // TRUE, also throws undefined index error
var_dump((
    array_key_exists('implicit_null',get_defined_vars()) && 
    is_null($implicit_null)
)); // FALSE

互联网上流传着其他用例,但很少概述性能或内存影响可能是什么。

事实证明,内存影响可能会有所不同,但在最坏的情况下,它几乎可以 double your memory usage

function report_memory($string = '') {
    $mem = (memory_get_usage()/1000);
    echo "$string: {$mem}kb\n";
    return $mem;
}

// ~117.164kb
$start = report_memory('Start of stript');

for($i = 10000; $i > 0; $i--) {
    $var = "filler_$i";
    $$var = 'banana';
}

// ~1022.752kb after fill
$fill_size = ($after_fill = report_memory('After banana')) - $start;
// ~905.588kb fill size
echo "Fill Size: {$fill_size}kb\n\n";

$tmp_vars = get_defined_vars();

// ~1649.12kb after function call
$grew = report_memory('After get_defined_vars()') - $after_fill;
// ~626.368kb growth due to call
echo "Growth from get_defined_vars(): {$grew}kb\n\n"; 

同样,这是最坏的情况。我确实看到了 some odd behavior when simply filling an array with array_fill(). As you can see here, the growth from calling get_defined_vars() is VERY small, compared to creating variables themselves. I thought, at first, that this was due to arrays being returned as references, but this is clearly not the case. It should also be noted, however, that objects WILL be returned as references,因为对象总是如此。

综上所述,您的所有全局变量都不太可能成为数组上的数组,并且所有这些字符串、二进制数据和数字都将很快加起来。

最后,这是一个函数,几乎可以使您的内存占用量增加一倍,并导致 significant wall-time:

for($i = 10000; $i > 0; $i--) {
    $var = "filler_$i";
    $$var = 'banana';
}

$start = microtime(true);

for($i = 250; $i > 0; $i--) {
    $all = get_defined_vars();
}

$stop = microtime(TRUE);
echo round(((($stop - $start))/250)*1000000, 2); // ~1967.45 microseconds

总的结论

仅使用 进行调试,我什至不习惯将它留在代码中过夜。谨慎使用。