依赖注入带来的性能问题 [英] Performance problems from dependency injection

查看:318
本文介绍了依赖注入带来的性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的探查器报告中,我越来越看到带有依赖注入的基于模拟的测试的结果。许多依赖项是静态的,但是由于我们要单独测试方法,因此将它们更改为实例成员,例如以下示例:

In my profiler reports I'm increasingly seeing the results of mock-based testing with dependency injection. Many of the dependencies were static, but because we want to test methods in isolation they are changed to instance members, like the following example:

class ShortLivedThing {
   IDependency1 dep1;
   IDependency1 dep2;
   IDependency1 dep3;
   ...

   int TheRealData;

   // Constructor used in production 
   public ShortLivedThing() {
     dep1 = new Dep1(); dep2 = new Dep2(); dep3 = new Dep3();
   }

   // DI for testing 
   public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) { 
     dep1 = d1(); dep2 = d2(); dep3 = d3();
   }
}

在大多数情况下,依赖关系又具有其他依赖关系等等。这导致每次 都实例化(主要是静态)对象树的树,方法调用是在测试之外进行的。每个对象都非常小(只有几个指针),但是树效应将其变成了性能不断提高的问题。

In turn the dependencies most of the time have other dependencies and so on. This results in the instantiation of a tree of (mostly "static") objects every time a method call is done outside of tests. Each of the objects are very small (just a few pointers), but the tree effect turns this into an ever increasing performance hit.

我们该怎么办? / p>

What can we do about it?

推荐答案

在我看来,您需要利用适当的依赖项注入框架可以为您提供的功能。不要对测试/生产使用不同的构造逻辑。

It seems to me like you need to leverage the features a proper dependency injection framework can give you. Do not use different construction logic for testing/production.

在春季,单例注入仅在容器启动时执行。每次都进行原型注射。每次进行单元测试(如果已进行布线)时,也会进行完整布线。因此,概要分析单元测试通常不是一个好主意。

With spring, singleton injections are only performed at container startup. Prototype injections are done every time. The full wiring is also done each time you run a unit test, if it's being wired. So profiling unit tests is generally not a good idea.

也许您使用的单例作用域太少,原型作用域又太多了? (原型=每次都有新实例)

Maybe you're using too little of the singleton scopes and too much prototype scope ? (Prototype = new instance every time)

弹簧注入的好处是您可以使用作用域代理,这意味着您的对象图看起来像这样:

The nice thing about spring injection is that you can use scope proxies, meaning your object graph can look like this:

 A Singleton
 |
 B Singleton
 |
 C Prototype (per-invocation)
 |
 D Singleton
 |
 E Session scope (web app)
 |
 F Singleton

每个请求只会创建1个C实例和1个E实例每个会话。 A,B,D和F是单身人士。如果不是网络应用程序,则默认情况下没有会话范围,但您也可以设置自定义范围( Window范围对于带窗口的桌面应用程序来说很酷)。这里的线索是,您可以引入任何级别的作用域,有效地,您可以拥有十层单例对象,并且突然出现了会话作用域。 (这确实可以彻底改变您在分层体系结构中实现某些横切功能的方式,但这是另一回事)

And each request would only create 1 instance of C and one instance of E per session. A, B, D and F are singletons. If it's not a webapp you dont have session scope by default, but you can also make custom scopes (a "Window" scope sounds cool for a windowed desktop app). The clue here is that you can "introduce" scopes at any level, effectively you can have ten layers of singleton objects and all of a sudden something session scoped shows up. (This can really revolutionize how you implement some cross-cutting features in a layered architecture but that's a different story)

这确实使DI模型中的对象创建最少,我想。

This really gives the minimum object creation possible within a DI model, I think.

尽管这是Java的Spring,但我相信许多其他DI框架也应该支持类似的功能。也许不是最简约的。

Although this is Spring for Java I believe a number of other DI frameworks should support similar features. Maybe not the most minimalistic ones.

这篇关于依赖注入带来的性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆