“get_defined_vars()”对性能有何影响


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

每隔一段时间,我就会在SO上看到问题,其答案/解决方案包括使用get_defined_vars(),或互联网上使用该方法的博客文章。 在大多数情况下,它用于调试目的,但在某些情况下,作者似乎有意在生产代码中使用它。

虽然我很少使用这个函数,因为它让我感觉内部不舒服,但我想知道在 PHP 应用程序中使用这个函数的实际性能影响是什么。

它的用法的一个例子可能是查看变量是否显式设置为 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

互联网上还有其他用例流传,但很少概述性能或内存可能产生的影响。

事实证明,内存影响可能会有所不同,但在最坏的情况下,它几乎会使您的内存使用量翻倍。

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"; 

同样,这是最糟糕的情况。 当简单地用array_fill()填充数组时,我确实看到了一些奇怪的行为。 正如你在这里看到的,与创建变量本身相比,调用get_defined_vars()的增长非常小。 起初,我以为这是由于array作为参考返回,但显然并非如此。但是,还应该注意的是,对象将作为引用返回,就像对象始终一样。

综上所述,你不太可能所有的全局变量都是一个数组一个数组,所有这些字符串、二进制数据和数字加起来会相当快。

最后,这是一个单一的功能,可以使您的内存占用几乎翻倍,并产生大量的挂机时间:

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

一般结论

仅用于调试,我什至不会养成一夜之间将其留在代码中的习惯。 谨慎使用。