PHP: 为什么使用 `global` 比在函数内声明变量慢?
PHP: Why is the use of `global` slower than declaring a variable inside a function?
我一直在阅读 PHP 手册页,但显然我读错了。我 运行 进行了一些简单的测试,看看哪种获取变量的方法更快:使用 global
、在函数内声明变量,或使用声明的常量。
总结:
- 声明变量(例如,
$keyspace = 012...;
)最快。
- 使用
global
(例如,global $keyspace;
)。
- 定义常量(例如,
define('keyspace', '01234...');
最慢。
问题: 为什么使用 global
或 define
比在 PHP 中声明变量慢?
(1)函数外定义变量,函数使用global
$keyspace = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
function buildSKU(){
global $keyspace;
$sku = '';
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= $keyspace[random_int(0, $max)];
}
return $sku;
}
(2) 函数内部定义的变量
function buildSKU(){
$keyspace = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$sku = '';
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= $keyspace[random_int(0, $max)];
}
return $sku;
}
(3) 定义为常量的变量
define('keyspace', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ');
function buildSKU(){
$sku = '';
$max = mb_strlen(keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= keyspace[random_int(0, $max)];
}
return $sku;
}
我的测试台:
<?php
$start = microtime(true);
//Put (1) or (2) here...
for($i=0; $i<10000; $i++){ buildSKU(); }
$end = microtime(true) - $start;
echo "\n\nTime: ".$end."\nMemory:".memory_get_peak_usage(true)."\n\n";
我认为 global 的主要问题是依赖性问题,您的整个代码库将依赖于该全局变量及其存在,随着您的代码增长,很难跟踪和解决问题。即使更改名称也需要更改代码中的所有位置。
在你的代码中,如果键没有改变,也许你应该考虑使用常量。
你的标题有点误导。一个函数变量不是 'declared' 一遍又一遍,它是在您编写函数代码时声明一次的。您还关注了苹果与橙子的比较。
以函数变量为例,变量的作用域完全不同。一旦函数完成,在函数内部声明的局部变量将不复存在(至少从作用域的角度来看)。它也正在被初始化,这与全局示例不同,在全局示例中,函数开始时变量的状态是完全未知的。
您花了很多时间研究微优化和无意义的基准测试,而答案却要简单得多。使用 global
关键字将变量注入函数作用域再好不过了。
你有一些参数可以通过引用或值传递,但你没有评估这些选项,尽管我必须重申,在我看来你不会真正找到任何有趣的东西。
在大多数创建编译程序的语言中,函数变量是在堆栈上分配的。函数完成后,该内存区域将从堆栈中弹出并丢弃。然而,PHP 有一个变量命名和内存分配方案,该方案在所有变量和 objects 之间共享。您可以搜索有关 'php zval' 和 php 内部结构的信息,并了解有关变量分配方式、引用计数以及通过符号表与名称关联的更多信息。
这里要强调的一点是,无论变量的类型如何,变量分配都以相同的方式发生,因此任何对性能的纯粹变量分配语法的期望都不太可能提供任何有意义的差异。
PHP 就何时需要创建新的 zval 或简单地将多个符号指向同一个符号做出各种决定,这对您来说是透明的。
除非绝对需要并且别无选择,否则始终使用局部变量。
我一直在阅读 PHP 手册页,但显然我读错了。我 运行 进行了一些简单的测试,看看哪种获取变量的方法更快:使用 global
、在函数内声明变量,或使用声明的常量。
总结:
- 声明变量(例如,
$keyspace = 012...;
)最快。 - 使用
global
(例如,global $keyspace;
)。 - 定义常量(例如,
define('keyspace', '01234...');
最慢。
问题: 为什么使用 global
或 define
比在 PHP 中声明变量慢?
(1)函数外定义变量,函数使用global
$keyspace = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
function buildSKU(){
global $keyspace;
$sku = '';
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= $keyspace[random_int(0, $max)];
}
return $sku;
}
(2) 函数内部定义的变量
function buildSKU(){
$keyspace = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$sku = '';
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= $keyspace[random_int(0, $max)];
}
return $sku;
}
(3) 定义为常量的变量
define('keyspace', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ');
function buildSKU(){
$sku = '';
$max = mb_strlen(keyspace, '8bit') - 1;
for ($i = 0; $i < 8; ++$i) {
$sku .= keyspace[random_int(0, $max)];
}
return $sku;
}
我的测试台:
<?php
$start = microtime(true);
//Put (1) or (2) here...
for($i=0; $i<10000; $i++){ buildSKU(); }
$end = microtime(true) - $start;
echo "\n\nTime: ".$end."\nMemory:".memory_get_peak_usage(true)."\n\n";
我认为 global 的主要问题是依赖性问题,您的整个代码库将依赖于该全局变量及其存在,随着您的代码增长,很难跟踪和解决问题。即使更改名称也需要更改代码中的所有位置。
在你的代码中,如果键没有改变,也许你应该考虑使用常量。
你的标题有点误导。一个函数变量不是 'declared' 一遍又一遍,它是在您编写函数代码时声明一次的。您还关注了苹果与橙子的比较。
以函数变量为例,变量的作用域完全不同。一旦函数完成,在函数内部声明的局部变量将不复存在(至少从作用域的角度来看)。它也正在被初始化,这与全局示例不同,在全局示例中,函数开始时变量的状态是完全未知的。
您花了很多时间研究微优化和无意义的基准测试,而答案却要简单得多。使用 global
关键字将变量注入函数作用域再好不过了。
你有一些参数可以通过引用或值传递,但你没有评估这些选项,尽管我必须重申,在我看来你不会真正找到任何有趣的东西。
在大多数创建编译程序的语言中,函数变量是在堆栈上分配的。函数完成后,该内存区域将从堆栈中弹出并丢弃。然而,PHP 有一个变量命名和内存分配方案,该方案在所有变量和 objects 之间共享。您可以搜索有关 'php zval' 和 php 内部结构的信息,并了解有关变量分配方式、引用计数以及通过符号表与名称关联的更多信息。
这里要强调的一点是,无论变量的类型如何,变量分配都以相同的方式发生,因此任何对性能的纯粹变量分配语法的期望都不太可能提供任何有意义的差异。
PHP 就何时需要创建新的 zval 或简单地将多个符号指向同一个符号做出各种决定,这对您来说是透明的。
除非绝对需要并且别无选择,否则始终使用局部变量。