雄辩的模型观察者表现

时间:2017-04-26 12:10:14

标签: laravel laravel-5 eloquent laravel-5.4 laravel-eloquent

如果我有多重模型并且我在事务中工作繁重,那么在我的AppServiceProvider中,我为我的模型创建一个观察者,如:

$(this).parent().next(".show-subcom").fadeToggle().delay(1000);

是否会造成一些性能损失?如果我对每个应用程序访问都正确理解Stand-alone Programs它将循环遍历我的所有模型观察者方法并将它们与雄辩事件相匹配,那么如果我有30个模型观察者,它会导致糟糕的性能吗?

是否有一些聪明的方法只在模型使用时声明observe类?因此,即使不需要,每个模型只有在使用它时才会知道它的观察者,而不是在每个app访问中声明观察者?

3 个答案:

答案 0 :(得分:1)

有同样的问题,并对此做了一些研究。

  

如果打开Laravel随附的config/app.php文件,您将看到一个providers数组。这些都是将为您的应用程序加载的所有服务提供程序类。 请注意,其中许多都是“延迟的”提供程序,这意味着它们不会在每次请求时都加载,而仅在实际需要它们提供的服务时才加载。

Source

  

如果您的提供者仅在服务容器中注册绑定,则可以选择将其注册推迟到实际需要其中一个注册的绑定为止。 延迟加载此类提供程序将提高应用程序的性能,因为并非每次请求都从文件系统中加载它。

Source

答案 1 :(得分:1)

如果您将事件与Laravel一起使用,则事件将在每次请求时注册(但不会触发)。

更确切地说,将注册事件意味着User::observe(UserObserver::class);UserObserver的{​​{3}}并将它们保存在User类的调度程序的数组中。只有执行通过update模型的create / User方法时,才会触发已注册的UserObserver方法,即从调度程序中调用。

因此,如果您在Observer类中有30个模型,每个模型具有5个方法,则对调度程序的每个请求都将具有150个数组绑定。但是,只有在事件触发时,才会在每个请求期间调用观察者的方法。因此,与加载120kb Logo或执行查询调用所花费的时间相比,我认为150个数组分配不会对请求时间产生影响。

最好的事情当然是自己衡量。结合观察者与不结合观察者来衡量请求的时间。您可以使用loop through all methods


旁注:使用debugbar不会有任何区别,因为您必须将旁听者调用放入提供程序的boot方法中。从文档中:

如果您的提供商仅 在服务容器中注册绑定,则可以选择将其注册推迟到实际需要其中一个注册的绑定为止。

答案 2 :(得分:1)

特别是对于模型观察器,性能影响比典型的事件注册更大。额外的开销来自 Laravel 如何处理观察者事件映射。由于正在注册的事件基于现有方法,Laravel 对每个观察者进行 最少 13 次对 method_exists 的调用。

对于几个观察者来说,这没什么大不了的。但是,如果您开始在审计跟踪流程中使用观察者并涉及多个模型,则此成本可能会开始增加。

举个例子,我曾经开发过一个应用程序,它有四个广义观察者,在它们之间观察了大约 300 个模型(其中一些模型由观察者共享)。这变成了超过 600 次 Model::observe 调用,因此有超过 7,800 次调用 method_exists

我实际上创建了一个包 (reedware/laravel-events) 来解决这个问题。相反,您可以通过配置文件注册观察者(和其他事件),并且可以缓存这些事件。缓存机制实际上也适用于观察者(这不适用于 Laravel 开箱即用),因此观察者的成本变得极低。

或者,您可以放弃观察者设计模式,并在可引导特征中使用 Model::creating(...) 钩子,或者只是抛出自定义事件并为它们注册侦听器。