Php 为什么空的_uset()方法比有效的方法慢?
我在玩弄PHP神奇的方法(特别是),在进行微基准测试时,遇到了一个我难以解释的怪癖: 一个具有空主体的Php 为什么空的_uset()方法比有效的方法慢?,php,magic-methods,microbenchmark,Php,Magic Methods,Microbenchmark,我在玩弄PHP神奇的方法(特别是),在进行微基准测试时,遇到了一个我难以解释的怪癖: 一个具有空主体的\u set方法似乎比一个有效的方法需要更多的时间来运行。下面的代码片段演示了这一点: 类清空器{ 公共函数集($name,$value){} } 类非空发生器{ 公共函数集($name,$value){ $this->{$name}=$value; } } 功能基准($obj){ $start_time=微时间(真); 对于($i=0;$ifoo=42; } 返回microtime(TRUE)
\u set
方法似乎比一个有效的方法需要更多的时间来运行。下面的代码片段演示了这一点:
类清空器{
公共函数集($name,$value){}
}
类非空发生器{
公共函数集($name,$value){
$this->{$name}=$value;
}
}
功能基准($obj){
$start_time=微时间(真);
对于($i=0;$i<10000000;$i++){
$obj->foo=42;
}
返回microtime(TRUE)-$start\u time;
}
printf(“清空设置:%.2f秒\n”,基准测试(新清空设置));
printf(“NonEmptySetter:%.2f秒\n”,基准测试(新的NonEmptySetter));
//输出(在我的Core 2 Duo笔记本电脑上):
//排空时间:4.39秒
//非空计时器:1.28秒
有人能解释为什么会发生这种情况吗?你不能比较这两种情况,因为最终的结果是不相等的
$o1 = (new NonEmptySetter);
$o1->foo = 42;
$o2 = (new EmptySetter);
$o2->foo = 42;
var_dump($o1, $o2, $o2->foo);
这使得:
object(NonEmptySetter)[1]
public 'foo' => int 42
object(EmptySetter)[2]
null
并为最后一个添加一个通知:通知:未定义属性:EmptySetter::$foo
这意味着属性从未设置过,它不存在,fairy dust,我假设那里的不规则性需要时间
如果您正确地声明了类(请注意$foo
):
时间会被限制:哦,我看这是错误的测试用例 在第一个循环之后,
NonEmptySetter
将具有新的公共属性foo
。Next循环根本不调用\u set
方法,它们使用公共属性
class NonEmptySetter {
public function __set($name, $value) {
echo 'called only once'; // would be echoed only once.
$this->{$name} = $value;
}
}
有效测试
class EmptySetter {
public function __set($name, $value) {}
}
class NonEmptySetter {
public function __set($name, $value) {
$this->{$name} = $value;
}
}
function benchmark($class_name) {
$start_time = microtime(TRUE);
for ($i = 0; $i < 1000000; $i++) {
$obj = new $class_name();
$obj->foo = 42;
}
return microtime(TRUE) - $start_time;
}
printf("NonEmptySetter: %.2f seconds\n", benchmark('NonEmptySetter'));
printf("EmptySetter: %.2f seconds\n", benchmark('EmptySetter'));
类清空器{
公共函数集($name,$value){}
}
类非空发生器{
公共函数集($name,$value){
$this->{$name}=$value;
}
}
函数基准($class\u name){
$start_time=微时间(真);
对于($i=0;$i<1000000;$i++){
$obj=新的$class_name();
$obj->foo=42;
}
返回microtime(TRUE)-$start\u time;
}
printf(“NonEmptySetter:%.2f秒\n”,基准(“NonEmptySetter”);
printf(“清空设置:%.2f秒\n”,基准(“清空设置”);
空的setter更快。这有关系吗?你有没有连续访问过1000万次?还有,你到底为什么要使用一种空洞的魔法方法?基准只有在适用于现实情况时才有意义。这是一个精心设计的示例。@SverriM.Olsen,这不重要,但非常有趣:^)@sectus只有当您对PHP的C实现感兴趣时,它才有趣。性能方面,只有在使用空魔法方法1000万次时才有用。。。(并更正我之前的评论:我的意思是说“连续调用该方法”。我不知道为什么我使用“连续访问”作为示例。)@SverriM.Olsen,因此,交易不是在PHP的C实现中,而是错误的测试实现。到底是什么更快<代码>清空设置::$foo不存在。@TOOTSKI,我们不需要检查这段代码的相等性(它们不存在)。我只是说,无论他们做什么,代码的第一次和平都比第二次和平要快。
class EmptySetter {
public function __set($name, $value) {}
}
class NonEmptySetter {
public function __set($name, $value) {
$this->{$name} = $value;
}
}
function benchmark($class_name) {
$start_time = microtime(TRUE);
for ($i = 0; $i < 1000000; $i++) {
$obj = new $class_name();
$obj->foo = 42;
}
return microtime(TRUE) - $start_time;
}
printf("NonEmptySetter: %.2f seconds\n", benchmark('NonEmptySetter'));
printf("EmptySetter: %.2f seconds\n", benchmark('EmptySetter'));