PHP依赖注入容器性能基准

Most frameworks and larger PHP applications utilize a Dependency Injection Container with the goal of a more maintainable codebase. However, this can have an impact on performance. As loading times matter, keeping sites fast is important as ever. Today I’m going to benchmark several PHP Dependency Injection containers to see what their relative performance is like.

大多数框架和较大PHP应用程序都使用依赖注入容器,以实现更易于维护的代码库。 但是,这可能会影响性能。 由于加载时间很重要 ,因此保持网站的快速运行非常重要。 今天,我将对几个PHP Dependency Injection容器进行基准测试,以了解它们的相对性能如何。

For those unfamiliar with the concept, a Dependency Injection Container is a piece of software which automatically builds an object tree. For example, consider a User object which requires a Database instance.

对于那些不熟悉该概念的人,“依赖项注入容器”是一种自动构建对象树的软件。 例如,考虑一个需要数据库实例的User对象。

$user = new User(new Database());

A Dependency Injection Container can be used to automatically construct the object tree without needing to provide the parameters manually:

依赖注入容器可用于自动构造对象树,而无需手动提供参数:

$user = $container->get('User');

Each time this is called, a user object will be created with the database object “injected”.

每次调用该对象时,都会创建一个带有“注入”数据库对象的用户对象。

There are several well known (and not so well known) containers available for PHP:

有几个众所周知的(但不是那么知名的)PHP容器:

  • PHP-DI, a popular DI Container

    PHP-DI ,一个流行的DI容器

  • Symfony\DependencyInjection, the the Dependency Injection Container provided by the Symfony framework

    Symfony \ DependencyInjection ,Symfony框架提供的依赖注入容器

  • Zend\Di the Dependency Injection Container provided by Zend Framework

    Zend \ Di Zend Framework提供的依赖注入容器

  • Orno\Di, a lesser known container with limited features but developed with performance in mind

    Orno \ Di ,一个鲜为人知的容器,功能有限,但在开发时考虑了性能

  • Dice, another lesser known container with a focus on being lightweight. Full disclosure, I’m the author of this container, but I’ll be nothing short of entirely objective in this analysis.

    Dice ,另一个鲜为人知的容器,重点是轻巧。 完全公开,我是这个容器的作者,但在此分析中,我将毫无保留地做到客观。

  • Aura.Di, a fairly popular container with minimal features

    Aura.Di ,一个功能非常有限的颇受欢迎的容器

A word on Pimple: Although Pimple is advertised as a Dependency Injection Container, retrieving an object from the container always returns the same instance, which makes Pimple a Service Locator rather than a Dependency Injection Container and as such, cannot be tested.

关于Pimple的信息:尽管Pimple被宣传为依赖注入容器,但是从容器中检索对象始终返回相同的实例,这使Pimple成为服务定位器而不是依赖注入容器,因此无法进行测试。

Although all the containers support different features, this benchmark will cover the basic functionality required by a Dependency Injection Container. That is, creating objects and injecting dependencies where they’re needed.

尽管所有容器都支持不同的功能,但此基准测试将涵盖依赖注入容器所需的基本功能。 也就是说,创建对象并将依赖项注入到需要的地方。

将测量依赖项注入的哪些方面? (Which aspects of dependency injection will be measured?)

  1. Execution time

    执行时间处理时间
  2. Memory Usage

    内存使用情况
  3. Number of files included. Although this has very little impact on performance it’s a good indicator of how lightweight and portable a library is. If you have to ship hundreds files with your project because of your DI choice, it can heavily impact the overall weight of your own application.

    包含的文件数。 尽管这对性能几乎没有影响,但是它很好地表明了库的轻量和可移植性。 如果由于选择DI而必须随项目一起发送数百个文件,则这可能会严重影响您自己的应用程序的整体重量。

测试环境 (Testing environment)

All tests were run on the same machine running Arch Linux (3.15 Kernel), PHP 5.5.13 and the latest versions of each container as of 03/07/2014.

所有测试均在运行Arch Linux(3.15内核),PHP 5.5.13和截至2014年3月7日的每个容器的最新版本的同一台计算机上运行。

All execution time numbers presented are an average of 10 runs after discarding any that are over 20% slower than the fastest.

显示的所有执行时间数字是在丢弃比最快速度慢20%以上的任何时间后平均运行10次。

测试1 –创建对象的实例 (Test 1 – Create an instance of an object)

This test uses each container to create a simple object 10,000 times

该测试使用每个容器创建一个简单对象10,000次

Without a Dependency Injection Container, this would be written as:

如果没有依赖注入容器,则将其写为:

for ($i = 0; $i < 10000; $i++) {
      $a = new A;
    }

Test code (on github): Aura, Dice, Orno\Di, PHP-DI, Symfony\DependencyInjection, Zend\Di

测试代码(在github上): AuraDiceOrno \ DiPHP-DISymfony \ DependencyInjectionZend \ Di

Test 1 - Execution Time

As you can see, there’s two clear camps here. Aura, Dice and Orno being roughly ten times faster than PHP-DI, Symfony and Zend\DI.

如您所见,这里有两个清晰的营地。 Aura,Dice和Orno的速度大约是PHP-DI,Symfony和Zend \ DI的十倍。

Test 1 - Memory Usage

Similar to Execution Time, there are two distinct groups with Symfony sitting somewhere in the middle ground.

与执行时间类似,Symfony有两个不同的组,它们位于中间位置。

Test 1 - Number of Files

This is very telling of how lightweight each container is and goes some way towards explaining the memory usage differences. It should be noted that a lot of the files used by Zend\Di are common framework files so if you’re using Zend Framework, then using Zend\Di will not incur the same memory overhead as files will likely be reused elsewhere in your application.

这很好地说明了每个容器的轻量化程度,并有助于解释内存使用差异。 应当注意,Zend \ Di使用的许多文件都是通用框架文件,因此,如果您使用Zend Framework,则使用Zend \ Di不会产生相同的内存开销,因为文件很可能会在应用程序中的其他地方重用。

Similarly, PHP-DI heavily relies on Doctrine libraries. If you’re using Doctrine in your project, then the memory overhead of PHP-DI is reduced.

同样,PHP-DI严重依赖于Doctrine库。 如果您在项目中使用Doctrine,则可以减少PHP-DI的内存开销。

However, It’s nice to see that Symfony\DependencyInjection, despite being part of the framework stack is entirely standalone and works without any dependencies from other Symfony projects.

但是,很高兴看到Symfony \ DependencyInjection尽管是框架堆栈的一部分,但它是完全独立的,并且可以在不依赖其他Symfony项目的情况下运行。

Aura, Dice and Orno do not have any external dependencies and this helps keep their file counts down.

Aura,Dice和Orno没有任何外部依赖关系,这有助于减少文件计数。

测试2 –忽略自动加载 (Test 2 – Ignoring autoloading)

As loading files can impact performance and both Zend and PHP-DI loaded a significant number of files, the same test was conducted ignoring the autoloader time by first creating a single instance of the class, ensuring any required classes were autoloaded before measuring the time.

由于加载文件会影响性能,并且Zend和PHP-DI都加载了大量文件,因此通过首先创建该类的单个实例,确保在测量时间之前自动加载了所有必需的类,从而忽略了自动加载器的时间,进行了相同的测试。

This may also have triggered any internal caching done by the container but the same treatment was applied to each container to keep it fair

这也可能触发了容器进行的任何内部缓存,但对每个容器都进行了相同的处理以保持公平

Equivalent PHP code:

等效PHP代码:

for ($i = 0; $i < 10000; $i++) {
          $a = new A;
    }

Test code (on github): Aura, Dice, Orno\Di, PHP-DI, Symfony\DependencyInjection, Zend\Di

测试代码(在github上): AuraDiceOrno \ DiPHP-DISymfony \ DependencyInjectionZend \ Di

Test 2 - Execution Time
Test 2 - Execution Time
Test 2 - Execution Time

As expected, memory usage is unchanged and performance is slightly better as the autoloader time isn’t being measured. However, this shows that PHP-DI, even loading 42 files has a negligible impact on the total execution time and the relative performance remains the same, loading dozens of files is not the cause of PHP-DI and Zend\DI having relatively slow performance.

正如预期的那样,由于未测量自动加载器的时间,因此内存使用情况保持不变,并且性能稍好一些。 但是,这表明PHP-DI甚至加载42个文件对总执行时间的影响微不足道,并且相对性能保持不变,加载数十个文件并不是PHP-DI和Zend \ DI性能相对较慢的原因。

Even after ignoring the overhead of loading files, there are still two distinct ballparks here. Aura, Dice and Orno are very similar in performance and memory usage while PHP-DI, Zend and Symfony are only in competition with each other.

即使忽略了加载文件的开销,这里仍然有两个截然不同的地方。 Aura,Dice和Orno在性能和内存使用方面非常相似,而PHP-DI,Zend和Symfony仅在竞争中。

All the tests going forward will ignore the autoloading time to ensure it’s truly the container’s performance that is being measured.

以后进行的所有测试都将忽略自动加载时间,以确保真正衡量的是容器的性能。

测试3 –深对象图 (Test 3 – Deep object graph)

This test is done by having the containers construct this set of objects 10,000 times:

通过使容器将这组对象构造10,000次来完成此测试:

for ($i = 0; $i < 10000; $i++) {
        $j = new J(new I(new H(new G(new F(new E(new D(new C(new B(new A())))))))));
    }

Test code (on github): Aura, Dice, Orno\Di, PHP-DI, Symfony\DependencyInjection, Zend\Di

测试代码(在github上): AuraDiceOrno \ DiPHP-DISymfony \ DependencyInjectionZend \ Di

Note: As you can see by looking at the test code, Symfony, PHP-DI and Aura require considerably more configuration code than the other containers to perform this test. The configuration time was not included in the test.

注意:通过查看测试代码可以看到,Symfony,PHP-DI和Aura需要比其他容器更多的配置代码才能执行此测试。 测试中不包括配置时间。

Test 3 - Execution Time

Again, there’s very little difference between the top 3, with Dice 20% faster than Aura and 70% faster than Orno. All three are considerably faster than Zend, PHP-DI and Symfony. The difference between the three top containers is so slight in real terms that you would never notice the speed difference outside an artificial benchmark like this.

同样,前3名之间的差异很小,Dice比Aura快20%,比Orno快70%。 这三个都比Zend,PHP-DI和Symfony快得多。 实际上,三个顶部容器之间的差异很小,以至于您永远不会注意到像这样的人工基准之外的速度差异。

Zend, PHP-DI and to a lesser extent Symfony are slow here. Zend takes 37 seconds to perform a task Dice manages in under 1 second; certainly not a trivial difference. Yet again, Symfony takes the lead among the big name containers.

Zend,PHP-DI和较小的Symfony在这里运行缓慢。 Zend花费37秒在1秒内完成Dice管理的任务; 肯定没有什么区别。 同样,Symfony在大型容器中处于领先地位。

Test 3 - Memory Usage
Test 3 - Memory Usage

Memory and file counts are consistent with what we’ve seen in other tests.

内存和文件计数与我们在其他测试中看到的一致。

测试4 –从容器中获取服务 (Test 4 – Fetching a Service from the container)

DI Containers also have to store and retrieve services which will be reused throughout the application. This test fetches a single instance from the container repeatedly.

DI容器还必须存储和检索将在整个应用程序中重复使用的服务。 此测试重复从容器获取单个实例。

Pure PHP Equivalent:

等同于纯PHP:

$a = new A;
    for ($i = 0; $i < 10000; $i++) {
      $a1 = $a;
    }

Test code (on github): Aura, Dice, Orno\Di, PHP-DI, Symfony\DependencyInjection, Zend\Di

测试代码(在github上): AuraDiceOrno \ DiPHP-DISymfony \ DependencyInjectionZend \ Di

Test 4 - Execution Time

This is unexpected based on previous results. All the containers except Zend and Symfony are roughly equal with just 0.01s separating the top 4 results. Symfony is not far behind, but Zend is well over ten times slower than the others.

根据以前的结果,这是意外的。 除Zend和Symfony以外的所有容器都大致相等,仅以0.01s间隔了前4个结果。 Symfony并不落后,但Zend的速度要比其他产品慢十倍以上。

Test 4 - Memory Usage
Test 4 - Number of Files

Memory usage and number of files results are becoming predictable with the same division between the containers that we’ve seen in execution time throughout.

存储器的使用和文件数量的结果变得可预测,容器之间的划分与整个执行时间相同。

测试5 –注入服务 (Test 5 – Inject a service)

The final test is to see how quickly an object can be constructed and have a service injected. This takes the format:

最终测试是查看可以多快构建一个对象并注入服务。 这采用以下格式:

$a = new A;
    for ($i = 0; $i < 10000; $i++) {
        $b = new B($a);
    }

Test code (on github): Aura, Dice, Orno\Di, PHP-DI, Symfony\DependencyInjection, Zend\Di

测试代码(在github上): AuraDiceOrno \ DiPHP-DISymfony \ DependencyInjectionZend \ Di

Test 5 - Execution Time

Interestingly, Aura has taken a slight lead in this test. However, it’s not quite a like-for-like test as Symfony and Aura require several lines of explicit configuration while the other containers automatically resolve the dependency. The time taken to configure the container was not part of the benchmark.

有趣的是,Aura在这项测试中略有领先。 但是,这并不是完全相同的测试,因为Symfony和Aura需要几行显式配置,而其他容器会自动解决依赖关系。 配置容器所花费的时间不属于基准测试的一部分。

Surprisingly, PHP-DI is the slowest at this task, with Zend taking its position ahead of PHP-DI and Symfony for the first time.

出乎意料的是,PHP-DI在此任务上的执行速度最慢,Zend首次在PHP-DI和Symfony之前领先。

Test 5 - Memory Usage
Test 5 - Number of Files

结论 (Conclusion)

On performance alone, Dice, Aura and Orno are all strong competitors, Dice is fastest overall and Aura fastest in the final test. The difference between the two distinct groups is apparent but its interesting to compare features of each container. Number of features and performance do not quite correlate as you’d expect. Both PHP-DI and Dice contain unique features but PHP-DI takes a heavy performance hit for doing so. Aura, although fast, requires a lot of manual configuration and does, as you’d expect, have very minimal features whereas Dice and Orno have very similar performance but require a lot less code to configure.

仅就性能而言,Dice,Aura和Orno都是强劲的竞争对手,Dice总体上最快,Aura在最终测试中最快。 两个不同组之间的差异是显而易见的,但是比较每个容器的功能很有趣。 功能数量和性能并不像您期望的那样完全相关。 PHP-DI和Dice都包含独特的功能,但是PHP-DI这样做会严重打击性能。 尽管速度很快,但Aura却需要大量的手动配置,并且确实具有极少的功能,而Dice和Orno的性能非常相似,但配置所需的代码却少得多。

Symfony is very much in the middle ground in all tests, although configuring it, as with Aura, is a much more difficult task as neither support type hinted parameters. If you’re looking for a container from a well known project, then Symfony has to be the container of choice if performance is important.

Symfony在所有测试中都处于中间位置,尽管与Aura一样配置Symfony更加困难,因为它们都不支持类型提示参数。 如果您正在寻找一个知名项目的容器,那么如果性能很重要,Symfony必须成为首选的容器。

That said, if pure performance is what you’re after then Dice and Aura are the clear winners with Orno very close behind. However, it’s worth taking a look at configuration syntax and features of each to see which you would prefer working with as the performance difference between Dice, Aura and Orno is negligible for any real application.

就是说,如果您只追求纯粹的表现,那么Dice和Aura无疑是赢家,而Orno紧随其后。 但是,值得一看的是每种的配置语法和功能,以了解您希望使用哪种配置,因为Dice,Aura和Orno之间的性能差异对于任何实际应用程序都是微不足道的。

All the code for the tests is available on github. Please note: The github repository contains copies of the libraries tested rather than using composer to include them in the project, this is to ensure that you can run the code with the exact versions I tested and get the same results.

测试的所有代码都可以在github上找到 请注意:github存储库包含测试过的库的副本,而不是使用composer将它们包括在项目中,这是为了确保您可以使用我测试过的确切版本运行代码并获得相同的结果。

翻译自: https://www.sitepoint.com/php-dependency-injection-container-performance-benchmarks/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值