【问题标题】:Performance of Singleton Class Instance Method vs. Static Class Method in PHP?PHP中单例类实例方法与静态类方法的性能?
【发布时间】:2011-03-26 00:26:16
【问题描述】:

我对客观分析哪个更高效感兴趣;调用单例类的实例方法或静态类的方法。我已经看过this,所以我不是在寻找关于两者之间差异的讨论,也不是关于哪个“更好”的讨论。我只对两者之间的相对表现感兴趣。提前致谢。

-迈克

【问题讨论】:

  • 仅供参考,我认为可以在这里找到一个更好的通用答案,说明为什么更喜欢单例而不是静态类。 stackoverflow.com/questions/6829609/…
  • This post on Stackoverflow 为不同 PHP 版本提供了一些很好的基准测试,并很好地回答了这个问题。

标签: php singleton performance class-design static-methods


【解决方案1】:

检查此图表:)

取自this article

【讨论】:

  • 任何人都可以制作精美的图表。如果没有关于使用的测试设置的信息,它是没有意义的。你至少可以提供一个链接到你从哪里得到这个。
  • 我刚刚添加了文章的链接
  • 另一方面,测试的作者应该大声而明确地声明他每次都在循环中调用TestSingleton::getInstance() 而在现实世界的应用程序中,Singleton 实例会作为参数传递给类方法(这是单例设计与静态类 [stackoverflow.com/questions/6829609/…) 相比的优势之一,因此这些类不会每次都调用 getInstance(),因为它们已经存储了对单例对象的引用...
  • ...无论如何,在现实世界的应用程序中,仍然有很多对 Singletons getInstance() 的调用,而我们没有任何参考,如果是这样的话,所做的测试可能是一个很好的模拟。很难说!还有一些测试证明 static 调用比 PHP stackoverflow.com/questions/1472721 中的方法调用慢 但在这种情况下很难说它还取决于应用程序的功能stackoverflow.com/questions/1472721/…
  • 这个测试是错误的,php profiling 没那么简单。在这种情况下,您必须测量服务器端的 CPU 和内存消耗。在一般情况下,您还必须跟踪脚本持续时间和第一个输出字节的开始时间以及最后一个输出字节的时间。还有一个您知道的 GC,并且根据 GC 发生的位置,它可能会改变时间。在考虑 GC 的情况下,测量整个脚本执行可能会提供更准确的估计。有时静态速度更快,有时单例速度更快,有时创建新实例速度更快!。
【解决方案2】:

除非您在紧密循环中调用它们(意味着没有其他重要代码,调用的开销很大)数千或数十万次,否则不要担心。差异可能会在微秒以下,因此不值得担心。只需做出最佳架构选择...

Premature optimization is the root of all evil...

编辑:对于所有反对者,这是我写的a blog post,它描述了为什么这样的性能比较几乎毫无用处。

【讨论】:

  • +1,完全同意,此外,当谈到包装可能已实例化或未实例化的资源(套接字流、数据库连接等)时,instance() 方法的额外开销一个 Singleton 被否定,因为静态函数仍然需要检查资源是否存在并在需要时创建它。
  • -1:没有回答问题,而是自以为是。该问题与在 WordPress 中的使用有关;插件是否应该使用静态类来封装类的钩子或实例,所以它可以是数千次或更多。在这种情况下不需要实例,所以我选择了静态但有些保持静态方法太慢了。我不知道事实是什么,所以我来这里寻找答案。还是不知道答案...
  • 我确实回答了这个问题。我说不用担心。差异可能非常小。做出更好的架构选择。无论哪种方式,它都是一个微优化,所以不用担心......
  • 这不可能是一个学术问题?
  • @Mike 使用 Wordpress 并为性能而烦恼是一个悖论。 ircmaxell 给了你最明智的建议。如果您真的关心代码的性能,请分析应用程序以找出瓶颈所在,而不是仅仅假设它们在您认为的位置。学术 x 比 y 快不会让你的代码运行得更快。
【解决方案3】:

在调用单例模式对象的实例方法之前,需要先获取实例,这需要静态方法调用:

SomeClass::getInstance()->myMethod();
// versus
SomeClass::myMethod();

因此,当您第一次需要在函数中访问该对象时,您需要先进行静态方法调用。因为函数调用从来都不是免费的,所以最好将方法设为静态。

【讨论】:

    【解决方案4】:

    在我之前所做的测试中,我发现调用静态方法比调用实例方法更快,并且内存效率略高....但是单例不应该仅仅因为这些原因而被解雇。

    【讨论】:

      【解决方案5】:

      我的这次谈话有点晚了,但我刚刚找到了这个问题,我想我会把我的想法抛诸脑后,为我在 SO 上的第一篇帖子。

      作为一个快速实验(在阅读了 zolex 链接的文章之后),我在文章的基准测试中添加了第三个测试用例:

      $inst = TestSingleton::getInstance();  
      for($i=0;$i<$runs;$i++) $inst->test();
      

      当然,结果并非 100% 一致,但我发现大多数情况下,当通过所有三种方法运行 500,000 次调用时,上述方法的运行速度比其他两种方法中的任何一种都快 2-3 秒。

      虽然我总是在看到给出的“过早优化”引用时感到畏缩,但在这种情况下,我认为它一针见血。性能差异充其量是最小的,通常有利于更理智的单例使用。

      【讨论】:

      • 是的,但请阅读我的 zolex 答案中的 cmets。您的测试模拟了一个真实世界的应用程序,其中单例对象可能作为参数传递给其他类方法(对象注入),在这种情况下,类存储对单例对象的引用,并且不需要每次都调用getIntance。但是 zolex 的测试仍然模拟真实世界的应用程序,其中在代码中的任何地方都调用了单例 getIntance 而没有存储第一个引用(在使用不同的单例类时甚至不是一个选项)。所以两个测试都是对的!但很难说哪一个模拟了更好的现实世界应用程序。
      • 最准确的说法可能是现实世界的应用程序将混合使用单例的两种方法。不管怎样,我真正想说的是,单身人士并不像他们想象的那么糟糕。
      猜你喜欢
      • 2012-08-30
      • 1970-01-01
      • 2011-03-02
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 2012-03-28
      相关资源
      最近更新 更多