【问题标题】:Is static method faster than non-static?静态方法比非静态方法快吗?
【发布时间】:2011-06-14 09:02:33
【问题描述】:

编辑::哦我忘了

class Test1{
    public static function test(){
        for($i=0; $i<=1000; $i++)
            $j += $i;       
    }   
}

class Test2{
    public function test() {
        for ($i=0; $i<=1000; $i++){
            $j += $i;
        }
    }

}

对于这个算法

$time_start = microtime();
$test1 = new Test2();
for($i=0; $i<=100;$i++)
    $test1->test();
$time_end = microtime();

$time1 = $time_end - $time_start;

$time_start = microtime();
for($i=0; $i<=100;$i++)
    Test1::test();
$time_end = microtime();    

$time2 = $time_end - $time_start;
$time = $time1 - $time2;
echo "Difference: $time";

我有结果

Difference: 0.007561 

这些天来,我正在尝试使我的方法尽可能地静态化。但这是真的吗,.. 至少对于 php

【问题讨论】:

  • 你应该问自己的问题:速度差异是否会给你带来任何问题?如果没有,请不要担心。
  • 不知道.. 但是如果静态方法很容易调用并且我经常使用它。我假设静态方法会比常规方法慢,但我的结果显示静态方法更快。只是想确认一下(比如说知识)
  • 完成同上。首先让它工作。从您的简单测试中可以清楚地看出,这可能不是一个显着的数量级差异,因此如果它变得流行,请关注功能并担心毫秒级优化。然而,当你达到那个水平时,你可能已经对整个事情进行了几次重构......
  • 是的,静态更快。不,您不想使用静态。尝试在 UnitTest 中模拟一个静态类。那你就知道为什么了。
  • @Amil 错了,Foo::test()foo_test() 没有区别。所有的静态变量都是有效的全局变量。是的,Foo::test 只是全局命名空间中的 Foo,但无论是在函数前加上 foo_ 还是将其放入类中,都没有太大区别。

标签: php performance object methods static


【解决方案1】:

这里有类似的问题:Does using static methods and properties in PHP use less memory?

我刚刚改进了 Stanislav 链接的基准以使其生效:

https://3v4l.org/rDpVv

Results for PHP 7.4.1:

Runs by case: 500000 
Memory usage at start: 426,320

Run                                 Duration    %       Memory
Dynamic                             0.0594      30%     496
Dynamic instantiated                0.0917      46%     0           #
Dynamic instantiated stored         0.1994      100%    48,967,472  # slowest
Storage only                        0.0422      21%     16,781,392
Cost of instations only when stored 0.1572      79%     32,186,O8O  # cost of stored instatiations minus storage cost (diff of 2 previous lines)
Static                              0.0870      44%     0           # equivalent to dynamic with instantiation
Singletons with many getInstance    0.1213      61%     376
Singletons with one getInstance     0.0669      34%     320         # equivalent to "Dynamic"
Functions assigning $GLOBALS        0.0605      30%     0           # more than 2 times longer than using "global"
Functions assigning a global        0.0458      23%     32          # fastest. 32bits allocated? probably passed by copy... odd
Functions with $counter by ref      0.0707      35%     0           # slow for functions
Functions with $counter static prop 0.0524      26%     0

备注:

  • “修改全局的函数”最快,占 23%
  • “实例化,存储然后调用动态方法”是最长的,所以 100%
  • 存储实例会消耗大量内存和 21% 的总时间
  • “通过 ref 将 $counter 作为参数传递”几乎是“修改全局函数”的 2 倍
  • 调用修改静态属性的函数超级快,几乎是调用静态方法的一半。搞笑
  • MyClass::call() 花费了 Singleton::getInstance()->call() 时间的 75%,但花费了 $mySingleton->call() 的 133%
  • MyClass::call() 的成本与 (new MyClass)->call() 一样多
  • “静态”在成本上等同于“动态实例化非存储”。真的很有趣!

关于开发实践的结论(2020 年 1 月生效):

  • 永远不要使用 $GLOBALS,'global $myVar' 非常快(并且分配 32 位?)
  • 仅使用全局变量和函数进行编程是最快的 PHP 吗?老派摇滚!
  • 为大量方法调用存储一个实例然后删除它是最佳选择。
  • 避免存储大量实例。
  • “实例化调用”和“静态调用”成本相同

干杯

PS:由于限制,即使结果不是 100% 稳定,我也无法进行更多的跑步(我看到整个板凳的一些刷新有 20% 的变化) PS 2:如果你想禁用 3v4l.org 的缓存,只需在代码中任意位置添加一个空格即可

【讨论】:

    【解决方案2】:

    简短的回答,因为我不想过多地咆哮:

    它是否更快并不重要。如果您需要一些性能非常重要的东西,那么您可以考虑将每个函数调用缩短 0.02 纳秒,而不是在 PHP 中这样做。

    静态方法会导致无法测试、无法维护的“全局性一切”代码,这对您的伤害比其他任何事情都大。

    如果您不想使用正确的 OOP(如果您知道自己在做什么以及为什么这样做,那完全可以),那么请这样做。只是不要因为你想节省 cpu 时间而这样做。

    http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

    http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html

    http://en.wikipedia.org/wiki/Class-based_programming

    如果你只点击一个链接: http://www.scribd.com/doc/20893084/Advanced-OOP-and-Design-Patterns#scribd

    Premature optimization is the root of all evil. 构建易于维护的代码,如果速度变慢,请进行配置文件,它很可能会告诉您数据库的文件系统有问题,您整理完所有内容后会有一些非常具体的要优化的 php 块。如果你有干净、可变的代码,你可以加快速度。

    【讨论】:

    • 我认为 Stefan 一定已经删除了他的幻灯片,但看起来有人在此处放了一份副本,看起来真的很好读...scribd.com/doc/20893084/Advanced-OOP-and-Design-Patterns
    • “静态方法会导致无法测试、无法维护、“全局性的一切”代码,这对你的伤害比其他任何事情都大。”。我完全不同意。测试静态方法比测试非静态方法更容易。 Class:method() 比 $obj=new Class(); 容易$obj->method().
    【解决方案3】:

    一般来说,是的。静态方法和属性的工作速度更快(PHP 5.3 除外)。

    你可以参考这个或多或少详细的comparison of static and non-static methods in PHP

    【讨论】:

      【解决方案4】:

      “过早的优化是万恶之源”40 年前由 Donald Knuth 说过。您知道,当您拥有英特尔发明的新 4004 微处理器 时。那个鼓被打得像任何马一样用力,我看不出它与最初的问题有什么关系。事实上,我可能很幸运,但我还没有看到该领域这种猖獗行为的证据。唉,互联网上的某个人必须是正确的,然后我们才能全都睡好觉。

      关于主题的更多信息,我认为接受的答案是最实用的,对问题的第一条评论是正确的。静态代码与实例化代码是否更快主要取决于语言的实现方式,我认为这些响应中的任何一个都不能充分回答有关 PHP 的问题。有人知道 PHP 并想参与进来吗?

      【讨论】:

        【解决方案5】:

        如果你打算让你的方法静态并添加一个参数来传递你的类对象,那实际上会更慢。我用这个对测试进行了基准测试,这是一个相当大的损失。通过各种静态方法传递对象是一种性能损失。最好让它们在对象中保持动态。

        我相当肯定动态方法的性能更快,因为调用是在同一个对象中进行的。在对象中使用静态方法时,每次调用都会有额外的跳跃,因为调用不是在对象中进行的,而是在类中进行的。

        使用静态方法确实减少了内存使用量。如果您可以将方法存放在类中,那么没有它们,对象的重量会更轻。但在我的测试中最重要的是可访问性。直接访问方法是最快的,而访问静态类方法是额外的一跳。这实际上是处理与内存的问题。十分之九,动态更快。

        【讨论】:

          【解决方案6】:

          当你不需要一个对象时你应该总是使用静态方法,当你需要一个对象时使用动态。在您提供的示例中,您不需要对象,因为该方法不与您的类中的任何属性或字段交互。

          这个应该是静态的,因为它不需要对象:

          class Person {
              public static function GetPersonByID($id) {
                  //run SQL query here
                  $res = new Person();
                  $res->name = $sql["name"];
                  //fill in the object
                  return $res;
              }
          }
          

          这个应该是动态的,因为它使用它所在的对象:

          class Person {
              public $Name;
              public $Age;
              public function HaveBirthday() {
                  $Age++;
              }
          }
          

          速度差异很小,但您必须创建一个对象来运行动态方法,并且该对象保存在内存中,因此动态方法使用更多内存和更多时间。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-17
          相关资源
          最近更新 更多