laszlovl/yii2-staticactiverecord

一个对 Yii2 的 ActiveRecord 进行了多种性能优化,但牺牲了少许灵活性的版本

安装: 46

依赖项: 0

建议者: 0

安全: 0

星标: 8

关注者: 3

分支: 0

开放问题: 0

类型:yii2-extension

v1.2 2015-05-07 16:20 UTC

This package is not auto-updated.

Last update: 2024-09-28 16:41:33 UTC


README

一个更快但略少灵活的 Yii2 ActiveRecord 版本。

Build Status

描述

Yii2 是一个优秀的框架,其灵活性是其优点之一。然而,灵活性往往是以性能为代价的,有时性能的损失可能不值得。

此代码专门针对 Yii2 的 ActiveRecord。由于 ActiveRecord 的灵活性,许多计算必须在运行时完成:查找相应的数据库模式、从该模式中推导出属性列表、根据模型的 rules() 确定每个场景的安全属性等。

在 Yii2 的架构中,这些计算不仅针对你的每个 ActiveRecord 进行一次(每个请求),而且针对每个 ActiveRecord 实例 进行。

以下是一个示例代码

foreach (Cat::find()->limit(100)->all() as $cat) {
    echo $cat->owner;
}

->owner 的调用将被转发到 __get(),然后调用 hasAttribute(),再调用 attributes(),然后调用 getTableSchema(),这将使用 DI 容器检索对 db 组件的引用,等等。所有这些只是为了确定你的 Cat 类是否有一个本地属性 $owner,或者应该将其解析为 ActiveRecord 属性,或者可能是关系。这不是只进行一次,而是 100 次:为你的每个 Cat 实例再次进行。

这些都是必要的吗?这当然取决于你的应用程序的设计方式。例如,在运行时向对象附加行为是完全可能的,这可能导致你的猫中有一个 owner 关系,而另一个没有。或者,可以覆盖 attributes() 来根据实例的其他属性值完全隐藏 owner 属性。

但在许多应用程序中并非如此:虽然类不同的实例当然会有不同的 ,但它们的 元数据 将是 静态的:要么你的所有 Cats 都有一个属性 owner,要么一个也没有。如果你的某个猫实例被发现在具有 MiowBehavior,则所有其他猫也会具有它。

如果你的应用程序确实如此,我们可以在类级别缓存此元数据:一旦为类的某个实例计算过,其他实例就可以立即查找。此扩展的 ActiveRecord 就是这样做的,通过使用静态类变量在包含类的所有实例之间缓存函数的结果。

这可以极大地提高你应用程序的性能,尤其是在处理大量相同类实例的请求中,如具有大分页大小的 GridView 或 ListView,或在资源集合上的 API 调用。

基准测试

此扩展包含一个基准测试工具,用于测量几个非常简单场景的性能改进。在所有情况下,都创建了 1000 个同一类的实例。

~/yii2-staticactiverecord/benchmark$ ./yii benchmark

Benchmarking benchmarkGetProperty...
Regular ActiveRecord: 0.0089842319488525
Static ActiveRecord:  0.0069756507873535
Improvement:          23%

Benchmarking benchmarkSetProperty...
Regular ActiveRecord: 0.009577751159668
Static ActiveRecord:  0.0076509952545166
Improvement:          21%

Benchmarking benchmarkValidate...
Regular ActiveRecord: 0.046598815917969
Static ActiveRecord:  0.03521466255188
Improvement:          25%

单个请求中性能改进的总和当然取决于你的具体应用程序,但我已经能够将应用程序的一个重请求的响应时间降低超过 50%。

测试

此扩展重用了 Yii 的现有 ActiveRecordTest 套件,用此扩展中的实现覆盖了默认的 ActiveRecord 实现。这表明 Yii 中包含的任何测试用例都没有因此扩展的行为而损坏。

注意事项

正如所说,这个扩展并不适用于所有人。以下是一些可能不适合特定类的迹象:

  • 该类覆盖了以下任何函数:getTableSchema()primaryKey()attributes()hasAttribute()scenarios()
  • 在类的这些函数中有一个对$this的引用:rules()behaviors()tableName()
  • 您的应用程序在运行时将行为附加到该类
  • 您的应用程序在类的表上调用getTableSchema($refresh=true)

安装

通过composer:composer require laszlovl/yii2-staticactiverecord

之后,只需从lvl\staticactiverecord\db\ActiveRecord扩展您的ActiveRecord类,而不是yii\db\ActiveRecord