php 静态方法与函数的性能
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1472721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Performance of static methods vs. functions
提问by J.C. Inacio
In PHP, (unlike what I originally thought) there is an overhead of calling static methods vs simple functions.
在 PHP 中,(与我最初的想法不同)调用静态方法与简单函数会产生开销。
On a very simple bench, the overhead is over 30% of the calling time (the method just returns the parameter):
在一个非常简单的bench上,开销超过调用时间的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";
outputs:
输出:
Static Time: 0.640204906464 ms
Object Time: 0.48961687088 ms
Function Time: 0.438289880753 ms
I know the actual time is still negligible unless I am actually calling something 1 million times, but the fact is that its there.
我知道实际时间仍然可以忽略不计,除非我实际上调用了 100 万次,但事实是它就在那里。
Will anyone care to try and explain what is happening behind the scenes?
有人愿意尝试解释幕后发生的事情吗?
update:
- added object method bench
更新:
- 添加了对象方法工作台
回答by Morgan Touverey Quilling
Apparently this point has been fixed in later versions of PHP (5.5.12).
显然,这一点已在更高版本的 PHP (5.5.12) 中得到修复。
I ran the OP's code (with empty methods), and I get these results :
我运行了 OP 的代码(使用空方法),得到了以下结果:
Static Time: 1.0153820514679 ms
Object Time: 1.100515127182 ms
Edit: Eight months and some releases later...
编辑:八个月后发布了一些版本......
It's interesting to see how Zend and the community are working hard on PHP's performance.
看到 Zend 和社区如何努力提高 PHP 的性能很有趣。
PHP 5.6
PHP 5.6
Here is the same benchmark with PHP 5.6.9(ZE 2.6) :
这是与PHP 5.6.9(ZE 2.6)相同的基准:
Static Time: 0.97488021850586 ms
Object Time: 1.0362110137939 ms
Function Time: 0.96977496147156 ms
For one run, "object time" was even faster than static time, so now they are very close. Better, we can see that objects are almost fast as functions!
对于一次运行,“对象时间”甚至比静态时间还要快,所以现在它们非常接近。更好的是,我们可以看到对象几乎和函数一样快!
PHP 7.0
PHP 7.0
I've also compiled PHP 7.0 alpha 1(ZE 3.0) and it is amazing to see how a fast language like PHP (Compared to other dynamic languages as you can see hereor here)can be optimized again and again:
我还编译了PHP 7.0 alpha 1(ZE 3.0),看到像 PHP 这样的快速语言(与您在此处或此处看到的其他动态语言相比)可以一次又一次地优化,真是太神奇了:
Static Time: 0.33447790145874 ms
Object Time: 0.30291485786438 ms
Function Time: 0.2329089641571 ms
With PHP7, basic functions have been greatly optimized, and "static time" is again slower than "instance/object time".
使用PHP7,基本功能得到极大优化,“静态时间”再次慢于“实例/对象时间”。
Edit, October 2015one year later : PHP 7.0 RC5. Now, "static time" is faster. An important thing to note:scalar type hinting (new feature in PHP7) brings a significant overhead, it's about 16% slower (type hinting does notmake your code 16% slower, it's that slower when you code is only composed of function calls ;) In real life applications, this is negligible). Such an overhead could seem illogic, but it's less surprizing when you know that dynamic typing is at the core of PHP. Contrarily to other more-static languages, type hinting in PHP means morechecks for the Zend Engine, and not lessas some of us could expect. In the future, we will probably get more runtime optimizations on this point (exactly like HHVM's runtime code analyses and JiT approach). Do not forget that PHP7 is young, and all the cleanup that has been done for this release permits great enhancements in the future, in features and performance.
一年后编辑,2015年10 月:PHP 7.0 RC5。现在,“静态时间”更快。要注意的重要一点:标量类型提示(在PHP7新功能)带来了显著的开销,它是约16%的速度较慢(类型提示并没有使你的代码16%的速度较慢,就这么慢,当你的代码仅由函数调用; ) 在现实生活应用中,这是可以忽略不计的)。这样的开销可能看起来不合逻辑,但是当您知道动态类型是 PHP 的核心时,这就不足为奇了。与其他更静态的语言相反,PHP 中的类型提示意味着对 Zend 引擎进行更多检查,而不是更少正如我们中的一些人所预料的那样。未来,我们可能会在这一点上获得更多的运行时优化(就像 HHVM 的运行时代码分析和 JiT 方法)。不要忘记 PHP7 还很年轻,为此版本所做的所有清理都允许在未来在功能和性能方面进行很大的改进。
HHVM
HHVM
A test against HHVM 3.7.1still shows that HHVM easily wins on that type of benchmarks, here you can see the benefits of a JiT compilation (JiT is a "planned" feature for future versions of PHP, we'll probably get it in the 7.x or 8.x branches. Zend had created a PoC, as an OpCache extension):
一个测试HHVM 3.7.1仍然表明 HHVM 在那种类型的基准测试中很容易获胜,在这里你可以看到 JiT 编译的好处(JiT 是 PHP 未来版本的“计划”功能,我们可能会在 7.x或 8.x 分支。Zend 创建了一个 PoC,作为 OpCache 扩展):
Static Time: 0.070882797241211 ms
Object Time: 0.23940300941467 ms
Function Time: 0.06760311126709 ms
For HHVM, functions and static methods have a very similar timing, this could let us think that, internally, those are almost the same things (after all, a static method is very similar to a namespaced function). The instance timing is "catastrophic" compared to the others. This shows how HHVM and ZE are very different engines.
对于 HHVM,函数和静态方法的时序非常相似,这让我们认为,在内部,它们几乎是相同的东西(毕竟静态方法与命名空间函数非常相似)。与其他实例相比,实例时间是“灾难性的”。这表明 HHVM 和 ZE 是非常不同的引擎。
Conclusion?
结论?
There's no guarantee that one of these practices (static/instance) will stay the faster, forever.Use what seems the best in terms of software design and keep a coherent code into an existing application.
不能保证这些实践之一(静态/实例)会永远保持更快。使用在软件设计方面看起来最好的东西,并将连贯的代码保留到现有的应用程序中。
If you have the choice, and/or if you're writing a library, etc, then maybe you could use instance methods, it's more friendly with DI environments, and that gives more control to the developer that consumes your API.
如果您有选择,和/或如果您正在编写库等,那么也许您可以使用实例方法,它对 DI 环境更友好,并且可以为使用您的 API 的开发人员提供更多控制权。
If you're just providing utility functions (like those little packages in npm's ecosystem), then you could use namespaced functions (but be aware that PHP still doesn't have function autoloading, meaning that Composer can't lazy-load your librarylike it does with PSR-0/4)
如果你只是提供实用函数(比如 npm 生态系统中的那些小包),那么你可以使用命名空间函数(但要注意PHP 仍然没有函数 autoloading,这意味着Composer 不能像这样延迟加载你的库它适用于 PSR-0/4)
回答by Greg
There used to be a big penalty when calling a static method - but it's fixed in 5.4.0 - see the extensive test results http://www.micro-optimization.com/global-function-vs-static-method.
调用静态方法时曾经有很大的惩罚 - 但它在 5.4.0 中得到修复 - 请参阅广泛的测试结果http://www.micro-optimization.com/global-function-vs-static-method。
回答by Marco Demaio
I repeated the test on my machine multiple times and surprisingly you are right!
我在我的机器上重复了多次测试,令人惊讶的是你是对的!
在 PHP 中调用static类的方法似乎比调用对象方法慢。单击此处进行简单测试。
The code with the running test is in the above link.
运行测试的代码在上面的链接中。
I even tried placing both the objet method and the static method in the same class and the staticmethod still results SLOWER!!!
我什至尝试将 objet 方法和静态方法放在同一个类中,但该static方法仍然导致速度变慢!!!
At this point I'm wondering how slow could be a call to a staticmethod of an inherited class, since inheritance adds up delay.
在这一点上,我想知道调用static继承类的方法有多慢,因为继承会增加延迟。
Sadly, I'm clueless about the reason. Maybe PHP takes more time in finding the definition of the staticmethod.
可悲的是,我对原因一无所知。也许 PHP 需要更多时间来查找static方法的定义。
As a side note I could only say that in a real life application it usually happens to have the object created before calling one of its methods. Therefor your test should take this into account comparing the loop of static calls to a loop that each time (or at least some times) [*] creates the objet:
作为旁注,我只能说在现实生活中的应用程序中,通常会在调用其方法之一之前创建对象。因此,您的测试应该考虑到将静态调用循环与每次(或至少某些时候)[*] 创建对象的循环进行比较:
for($i=0; $i<10*1000*1000; $i++)
{
$someObj = new someObj();
$someObj->doTest($i);
}
thus is obviously slower than the staticcall.
因此显然比static调用慢。
for($i=0; $i<10*1000*1000; $i++)
{
SomeClass::doTest($i);
}
[*] the problem is: how much is some timesin order to simulate what happnes in a real world app? It's hard to say!
[*] 问题是:为了模拟现实世界的应用程序中发生的事情,有时需要多少时间?很难说!
回答by Jquest
There is some thing Wrong in your tests. With a website designed to work with multiple users at the same time you have to create an object for each one. To run that object's method in your tests you should have:
你的测试有一些错误。对于设计为同时与多个用户一起工作的网站,您必须为每个用户创建一个对象。要在测试中运行该对象的方法,您应该:
for($i=0; $i<10*1000*1000; $i++)
{
$someObj = new someObj();
$someObj->doTest($i);
}
If your object had more properties and methods then creating it is slower and PHP uses more memory. A static method won't have this problem, and therefore using static methods is a better choice in lots of situations. For example, a class with some handy tools with static methods for common tasks.
如果你的对象有更多的属性和方法,那么创建它的速度会更慢,而且 PHP 会使用更多的内存。静态方法不会有这个问题,因此在很多情况下使用静态方法是更好的选择。例如,一个带有一些方便工具的类,带有用于常见任务的静态方法。
回答by Brian Lyttle
It has been a while since I have done any PHP but this is probably similar to what you expect in other programming environments.
我已经有一段时间没有做过任何 PHP 了,但这可能与您在其他编程环境中所期望的相似。
It is likely that the static method requires some construction of a SomeClass object behind the scenes each time that it is called, whereas the function can just be executed without any startup cost. Creating an object couldbe costly depending on a number of things: destruction of existing objects by a garbage collector/reference counter, memory pressure causing fragmentation, suboptimal memory allocation policies in the C runtime etc.
每次调用静态方法时,很可能需要在幕后构造 SomeClass 对象,而该函数可以直接执行而无需任何启动成本。创建对象的成本可能取决于多种因素:垃圾收集器/引用计数器对现有对象的破坏、导致碎片的内存压力、C 运行时中的次优内存分配策略等。
It would be interesting to compare the method performance of an existing object. To do this create an instance of SomeClass and then call an instance method repeatedly.
比较现有对象的方法性能会很有趣。为此,请创建 SomeClass 的实例,然后重复调用实例方法。
回答by Nicolas
In the case of the static method, PHP has to check wether the method can or cannot be called from the calling context (public, protected, private). That's most likely what causes the overhead, or at least part of it, since the classic function call doesn't require PHP to perform that kind of check.
在静态方法的情况下,PHP 必须检查该方法是否可以从调用上下文(公共、受保护、私有)中调用。这很可能是导致开销或至少部分开销的原因,因为经典的函数调用不需要 PHP 执行这种检查。
回答by Adtopkek
I am following up what Morgan Touverey Quilling did but with PHP 7. Did 3 iterations incase it takes longer for the first run vs subsequent runs. Includes all classes as it might be done realistically. All included files just return the input.
我正在跟进 Morgan Touverey Quilling 所做的事情,但使用 PHP 7。做了 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";
Just note that this is being done on one of my webhosts as its easier to switch php versions so might be some noise.
请注意,这是在我的一个网络主机上完成的,因为它更容易切换 php 版本,因此可能会有一些噪音。
PHP 7.0.33
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
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:
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
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 seemed to run a lot slower than the other versions on average. I found their lowest number but it got into the low .2####'s too. Don't' have 7.4 as of right now.
PHP 7.2 的平均运行速度似乎比其他版本慢很多。我找到了他们的最低数字,但它也进入了低 .2#### 的数字。目前还没有 7.4。

