【问题标题】:Is it good/bad practice to store runtime-constant values in a function-locale static variable to speed-up mutliple calls?将运行时常量值存储在函数局部静态变量中以加速多次调用是好还是坏的做法?
【发布时间】:2019-11-26 17:58:14
【问题描述】:

假设这种情况。您有一个带有方法的类,对于给定的实例,该方法总是返回相同的值(例如,由构造函数确定)。

final class A
{
    private const VALUES = [/*long array*/];

    private $a = 5; // initialized in constructor, immutable afterwards

    public function isSafe(): bool
    {
        return \in_array($this->a, self::VALUES, true);
    }
}

在函数局部静态变量中缓存它有什么缺点吗?比如这样:

final class A
{
    private const VALUES = [/*long array*/];

    private $a = 5; // initialized in constructor, immutable afterwards

    public function isSafe(): bool
    {
        static $result = null;
        return $result ?? $result = \in_array($this->a, self::VALUES, true);
    }
}

这种方法的优缺点是什么?有替代品吗?这被认为是好的、坏的还是任何做法(如果是这样:为什么)?还是应该在构造函数中已经发生“缓存”?

【问题讨论】:

  • 在站点注释中,当您有多个 A 类实例时,ìsSafe() 函数将无法正常工作。 (只有第一次调用ìsSafe() 会返回正确的结果)。之后,A 类的 所有 个实例将从 isSafe() 返回相同的值
  • @Turtlefight 哦,看来我当时犯了大错。我认为函数语言环境静态是静态的。对同一个实例进行多次调用,而不是全局调用。那么答案很明显:这是不好的做法。

标签: php performance caching architecture


【解决方案1】:

你的例子很简单,它不能证明使用这种缓冲是合理的。您要做的是在遇到任何性能问题之前优化代码。 Is premature optimization really the root of all evil?

使用static 本身并没有错,但它增加了代码的复杂性,几乎没有任何切实的结果。但是,如果您有一个 DB 操作、文件读取、Web 服务调用而不是 in_array,或者如果您在循环中一遍又一遍地调用此方法,那么缓存结果可能是个好主意。但是,您需要确保每个方法调用的缓冲值始终相同,或者有一种方法可以使缓冲区无效。

"是否应该在构造函数中已经发生"缓存"?"

没有。您应该始终致力于使您的代码尽可能地懒惰。在实际请求时评估第一次调用 isSafe() 的结果,而不是在构造函数中过早地执行它。

【讨论】:

    【解决方案2】:

    如果您打算使用这种方法,我认为将该值保存在私有属性中而不是函数中的静态变量中更有意义。毕竟,它确实是对象的属性,尽管是派生属性。

    final class A
    {
        private const VALUES = [/*long array*/];
    
        private $a; // initialized in constructor, immutable afterwards
        private $safe;
    
        public function isSafe(): bool
        {
            return $this->safe ?? $this->safe = \in_array($this->a, self::VALUES, true);
        }
    }
    

    这也将避免@Turtlefight在您的问题中提到的问题this comment。 (这里引用它,因为 cmets 是无常的。)

    当您有多个 A 类实例时,ìsSafe() 函数将无法正常工作。 (只有第一次调用ìsSafe() 会返回正确的结果)。之后,A 类的所有实例都将从isSafe() 返回相同的值

    【讨论】:

    • 谢谢,在考虑这个问题时犯了一个大错误。我认为函数语言环境静态是静态的。对同一个实例进行多次调用,而不是全局调用。那么答案很明显:这是不好的做法(或完全错误)。
    猜你喜欢
    • 2011-08-13
    • 2012-09-11
    • 2011-03-23
    • 2011-06-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2011-12-19
    相关资源
    最近更新 更多