静态方法与功能的表现

时间:2009-09-24 16:15:31

标签: php performance oop

在PHP中,(与我原先的想法不同),调用静态方法与简单函数的开销很大。

在一个非常简单的工作台上,开销超过了通话时间的30% (该方法只返回参数):

// bench static method
$starttime = microtime(true);
for ($i = 0; $i< 10*1000*1000; $i++)
    SomeClass::doTest($i);

echo "Static Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench object method
$starttime = microtime(true);

for ($i = 0; $i< 10*1000*1000; $i++)
    $someObj->doTest($i);

echo "Object Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench function
$starttime = microtime(true);

for ($i = 0; $i< 10*1000*1000; $i++)
    something_doTest($i);

echo "Function Time: " , (microtime(true)-$starttime) , " ms\n";

输出:

Static Time:   0.640204906464 ms
Object Time:   0.48961687088 ms
Function Time: 0.438289880753 ms

我知道实际时间仍然可以忽略不计,除非我实际上是在呼唤100万次,但事实是它在那里。

有人会关心尝试解释幕后发生的事情吗?

更新:
- 添加对象方法工作台

8 个答案:

答案 0 :(得分:53)

显然,这一点已在PHP(5.5.12)的更高版本中得到修复。

我运行了OP的代码(使用空方法),我得到了这些结果:

Static Time:   1.0153820514679 ms
Object Time:   1.100515127182 ms

编辑:八个月后发布一些......

看看Zend和社区如何在PHP的表现上努力工作,这很有趣。

PHP 5.6

以下是与 PHP 5.6.9 (ZE 2.6)相同的基准:

Static Time:   0.97488021850586 ms
Object Time:   1.0362110137939 ms
Function Time: 0.96977496147156 ms

一次运行,&#34;对象时间&#34;甚至比静态时间更快,所以现在它们非常接近。更好的是,我们可以看到对象几乎像函数一样快!

PHP 7.0

我还编译了 PHP 7.0 alpha 1 (ZE 3.0),很高兴看到像PHP 这样的快速语言(与其他动态语言相比)可以反复优化herehere

Static Time:   0.33447790145874 ms
Object Time:   0.30291485786438 ms
Function Time: 0.2329089641571 ms

使用PHP7,基本功能得到了极大的优化,并且&#34;静态时间&#34;再次慢于&#34;实例/对象时间&#34;。

编辑,2015年10月一年后: PHP 7.0 RC5 。现在,&#34;静态时间&#34;是比较快的。 需要注意的一个重要事项:标量类型提示(PHP7中的新功能)带来了显着的开销,它慢了16%(类型提示使你的代码慢16%,当代码只由函数调用组成时,它会慢一些;)在实际应用中,这可以忽略不计)。这样的开销可能看起来不合逻辑,但当你知道动态类型是PHP的核心时,它就不那么令人惊讶了。与其他更静态的语言相反,在PHP中键入提示意味着更多检查Zend引擎,而不是像我们中的一些人所期望的那样 less 。将来,我们可能会在这一点上获得更多的运行时优化(就像HHVM的运行时代码分析和JiT方法一样)。不要忘记PHP7是年轻的,并且为此版本所做的所有清理工作都可以在将来,功能和性能方面做出很大的改进。

HHVM

针对 HHVM 3.7.1 的测试仍然表明HHVM很容易在这种类型的基准测试中获胜,在这里您可以看到JiT编译的好处(JiT是&#34;计划和# 34; PHP的未来版本的功能,我们可能会在7.x或8.x分支中获得它。Zend had created a PoC, as an OpCache extension):

Static Time:   0.070882797241211 ms
Object Time:   0.23940300941467 ms
Function Time: 0.06760311126709 ms

对于HHVM,函数和静态方法的时序非常相似,这可以让我们认为,在内部,这几乎是相同的事情(毕竟,静态方法与命名空间函数非常相似)。实例时间是灾难性的&#34;与其他人相比。这显示了HHVM和ZE是如何非常不同的引擎。

结论

无法保证其中一种做法(静态/实例)永远保持更快。使用看似最好的软件设计并保持一致的代码现有的申请。

如果您有选择,和/或如果您正在编写库等,那么也许您可以使用实例方法,它对DI环境更友好,并且可以更好地控制使用您的API的开发人员。

如果您只是提供实用程序功能(如npm生态系统中的那些小包),那么您可以使用命名空间函数(但要注意PHP still doesn't have function autoloading,这意味着{{3}就像它与PSR-0/4一样)

答案 1 :(得分:23)

在调用静态方法时曾经有过一个很大的惩罚 - 但它已在5.4.0中修复 - 请参阅广泛的测试结果http://www.micro-optimization.com/global-function-vs-static-method

答案 2 :(得分:7)

我多次在我的机器上重复测试,并且出乎意料地你是对的!

<强> In PHP calling methods of static class seems to be slower than calling object methods. Click here for simple test.

运行测试的代码在上面的链接中。

我甚至尝试将objet方法和静态方法放在同一个类中,static方法仍会导致SLOWER !!!

此时我想知道对继承类的static方法的调用有多慢,因为继承会增加延迟。

可悲的是,我对这个原因一无所知。 也许PHP需要更多时间来查找static方法的定义

作为旁注,我只能说在现实生活中,通常会在调用其中一个方法之前创建对象。因此,您的测试应考虑到这一点,将静态调用循环与每次(或至少某些时间)[*]创建objet的循环进行比较:

for($i=0; $i<10*1000*1000; $i++)
{ 
   $someObj = new someObj();
   $someObj->doTest($i); 
}
因此,

显然比static调用慢。

for($i=0; $i<10*1000*1000; $i++)
{ 
   SomeClass::doTest($i);
}

[*]问题是:为了模拟现实应用程序中的快乐,有多少次?很难说!

答案 3 :(得分:6)

你的测试中有一些错误的东西。通过设计与多个用户同时工作的网站,您必须为每个用户创建一个对象。要在测试中运行该对象的方法,您应该:

for($i=0; $i<10*1000*1000; $i++)
{ 
   $someObj = new someObj();
   $someObj->doTest($i); 
}

如果你的对象有更多的属性和方法,那么创建它会更慢,PHP会占用更多的内存。静态方法不会出现这个问题,因此在很多情况下使用静态方法是更好的选择。例如,一个带有一些方便工具的类,其中包含用于常见任务的静态方法。

答案 4 :(得分:2)

我已经做了一段时间,但是这可能与你在其他编程环境中的预期类似。

静态方法可能需要在每次调用时在幕后构建一些SomeClass对象,而该函数可以在没有任何启动成本的情况下执行。根据许多事情创建对象可能成本高昂:垃圾收集器/引用计数器破坏现有对象,导致碎片的内存压力,C运行时中的次优内存分配策略等。

比较现有对象的方法性能会很有趣。为此,请创建SomeClass的实例,然后重复调用实例方法。

答案 5 :(得分:2)

对于静态方法,PHP必须检查方法是否可以从调用上下文(public,protected,private)调用。这很可能是导致开销或至少部分开销的原因,因为经典函数调用不需要PHP来执行这种检查。

答案 6 :(得分:1)

我在 PHP 8.0.3 上进行了大量迭代并进行了相同的测试。

Opcache 在这个测试中没有太大区别。

没有opcache:

Function Time:  0.15400409698486 ms
Static Time:    0.15216994285583 ms
Object Time:    0.19552803039551 ms
Function Time:  0.1428279876709 ms
Static Time:    0.15206789970398 ms
Object Time:    0.22962498664856 ms
Function Time:  0.14341592788696 ms
Static Time:    0.15271997451782 ms
Object Time:    0.22965002059937 ms
Function Time:  0.1877110004425 ms
Static Time:    0.1523380279541 ms
Object Time:    0.2297830581665 ms
Function Time:  0.14280891418457 ms
Static Time:    0.15206098556519 ms
Object Time:    0.22957897186279 ms
Function Time:  0.14343619346619 ms
Static Time:    0.15272903442383 ms
Object Time:    0.22955703735352 ms
Function Time:  0.14328694343567 ms
Static Time:    0.15257477760315 ms
Object Time:    0.22901511192322 ms
Function Time:  0.14302086830139 ms
Static Time:    0.15233588218689 ms
Object Time:    0.22931504249573 ms
Function Time:  0.14283490180969 ms
Static Time:    0.15209102630615 ms
Object Time:    0.22963285446167 ms
Function Time:  0.14345097541809 ms
Static Time:    0.1527111530304 ms
Object Time:    0.22959303855896 ms

使用 opcache:

Function Time:  0.15897798538208 ms
Static Time:    0.15508103370667 ms
Object Time:    0.20733213424683 ms
Function Time:  0.14364719390869 ms
Static Time:    0.15376496315002 ms
Object Time:    0.18648386001587 ms
Function Time:  0.142982006073 ms
Static Time:    0.15293192863464 ms
Object Time:    0.20651602745056 ms
Function Time:  0.14292907714844 ms
Static Time:    0.15280795097351 ms
Object Time:    0.18663787841797 ms
Function Time:  0.14208316802979 ms
Static Time:    0.15290093421936 ms
Object Time:    0.20616102218628 ms
Function Time:  0.14288401603699 ms
Static Time:    0.15276694297791 ms
Object Time:    0.1861629486084 ms
Function Time:  0.14292597770691 ms
Static Time:    0.15292882919312 ms
Object Time:    0.20615196228027 ms
Function Time:  0.14286112785339 ms
Static Time:    0.1527988910675 ms
Object Time:    0.18700098991394 ms
Function Time:  0.14315795898438 ms
Static Time:    0.15318417549133 ms
Object Time:    0.20666813850403 ms
Function Time:  0.14300584793091 ms
Static Time:    0.15291309356689 ms
Object Time:    0.18714189529419 ms

答案 7 :(得分:0)

我正在跟踪Morgan Touverey Quilling所做的工作,但使用PHP7。是否进行了3次迭代以防第一次运行与后续运行相比花费更长的时间。包括所有类,因为这可能是实际完成的。所有包含的文件仅返回输入。

include 'lib/global.php';
include 'SomeClass.php';
include 'StaticTest.php';

$someObj = new SomeClass();

$starttime = microtime(true);
for ($i = 0; $i< 10*100000; $i++)
    StaticTest::doStaticTest($i);

echo "<br>Static Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench object method
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    $someObj->doObjTest($i);

echo "<br>Object Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench function
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    something_doTest($i);

echo "<br>Function Time: " , (microtime(true)-$starttime) , " ms\n";

echo "<br>Static Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench object method
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    $someObj->doObjTest($i);

echo "<br>Object Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench function
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    something_doTest($i);

echo "<br>Function Time: " , (microtime(true)-$starttime) , " ms\n";

echo "<br>Static Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench object method
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    $someObj->doObjTest($i);

echo "<br>Object Time:   " , (microtime(true)-$starttime) , " ms\n";

// bench function
$starttime = microtime(true);

for ($i = 0; $i< 10*100000; $i++)
    something_doTest($i);

echo "<br>Function Time: " , (microtime(true)-$starttime) , " ms\n";

请注意,这是在我的一台虚拟主机上完成的,因为它更容易切换php版本,因此可能会有些杂音。

PHP 7.0.33

Static Time:   0.14076709747314 ms
Object Time:   0.16203689575195 ms
Function Time: 0.13194108009338 ms
Static Time:   0.13194918632507 ms
Object Time:   0.1779100894928 ms
Function Time: 0.13044309616089 ms
Static Time:   0.13045001029968 ms
Object Time:   0.16074585914612 ms
Function Time: 0.13029479980469 ms 

PHP 7.1.29

Static Time:   0.13407206535339 ms
Object Time:   0.13267111778259 ms
Function Time: 0.1302649974823 ms
Static Time:   0.13027906417847 ms
Object Time:   0.1390438079834 ms
Function Time: 0.16873598098755 ms
Static Time:   0.16874289512634 ms
Object Time:   0.13901305198669 ms
Function Time: 0.12576103210449 ms 

PHP 7.2.18:

Static Time:   0.1657600402832 ms
Object Time:   0.15700101852417 ms
Function Time: 0.1484169960022 ms
Static Time:   0.14842295646667 ms
Object Time:   0.16168689727783 ms
Function Time: 0.17508292198181 ms
Static Time:   0.17508983612061 ms
Object Time:   0.19771790504456 ms
Function Time: 0.1468551158905 ms 

PHP 7.3.5

Static Time:   0.10701704025269 ms
Object Time:   0.097011089324951 ms
Function Time: 0.075740098953247 ms
Static Time:   0.07575798034668 ms
Object Time:   0.083790063858032 ms
Function Time: 0.072473049163818 ms
Static Time:   0.072479009628296 ms
Object Time:   0.081503868103027 ms
Function Time: 0.071882963180542 ms 

PHP 7.2似乎平均比其他版本运行慢得多。我找到了他们的最低数字,但它也进入了最低的.2 ####。截至目前还没有7.4。