假设我有一个对象$foo
,我在字符串变量$bar
中有一个参数的名称。
我知道我可以使用$foo->$bar
访问参数的值,但我听说这在性能方面有点糟糕。
因此我的问题是:有更好的方法吗?
答案 0 :(得分:2)
首先,我应该说我同意这篇文章其他地方的观点,认为它可能不是一种值得花时间的优化。但是,我喜欢它,因为它促进了好奇心。为了满足这种好奇心,我编写了一个小型基准测试程序,将$foo->$bar
与第一个想到的替代方案进行比较:$foo->someKnownArrayProperty[$bar]
。事实证明,第一个一直是快10%左右。我在1M次迭代中测试了几次运行,然后在10M时测试了几次。这是我非常基本的代码:
<?php
$iterations = 10000000;
$bar = 'someproperty';
class Foo {
}
$foo = new Foo();
$start = microtime(TRUE);
for($i = 0; $i<$iterations; $i++) {
$rand = rand(1,1000);
$foo->$bar = $rand;
if($foo->$bar != $rand) {
throw new Exception("A problem occurred reading or writing $bar");
}
}
$end = microtime(TRUE);
$varproptime = $end - $start;
unset($foo);
$foo = new Foo();
$start = microtime(TRUE);
$foo->myarray = array();
for($i = 0; $i<$iterations; $i++) {
$rand = rand(1,1000);
$foo->myarray[$bar] = $rand;
if($foo->myarray[$bar] != $rand) {
throw new Exception("A problem occurred reading or writing $bar");
}
}
$end = microtime(TRUE);
$arrayproptime = $end - $start;
printf("Variable Property: %f.4\nArray Property: %f.4\n", $varproptime, $arrayproptime);
一般来说,1M迭代时间为1.0秒和1.1秒,10M时间为10秒和11秒。
我进一步提出了另一个想法:我们可以编译&#39;一个有“本地人”的班级。财产,以及一个二传手和一个吸气。这只是我头脑中的另一个想法。事实证明,这对于性能来说是可怕的,因为我们需要在堆栈中添加一个帧(使用setter和getter而不是直接访问)。我需要添加它们的原因是,如果这个想法是允许所有代码是静态的,那么目标就是&#39;一旦迭代开始。基本上我通过eval()
运行了一个类定义,它应该使程序处于一个等价的状态,如果它是用属性名称硬编码的。例如,如果您在编程时不知道属性名称,那么这个想法将是有价值的,但是在请求时它只是一个值并且可以读取/写入很多次。我想也许更长一段时间的启动&#39;如果时间导致更快的访问模式,则可以抵消时间。但它没有。这大约慢了100%。
$classDefinition = <<<EOD
class FOO {
public \$$bar;
function setThatThing(\$value) {
\$this->$bar = \$value;
}
function getThatThing() {
return \$this->$bar;
}
EOD;
eval($classDefinition);
在执行时,看起来像这样(注意一些$
被转义,有些没有)
class FOO {
public $someproperty;
public function setThatThing($value) {
$this->someproperty = $value;
}
public function getThatThing() {
return $this->someproperty;
}
}
答案 1 :(得分:0)
不要过分思考它。如果属性名称是动态生成的,并且您事先并不知道其值,则访问它的唯一方法是$obj->$prop
。我无法想出为什么这会影响表现。