PHP - 预加载所有类/函数

时间:2016-02-12 08:23:19

标签: php composer-php fastcgi

有没有办法为PHP项目预加载(而不是自动加载)所有类/函数?

我正在考虑使用PHPFastCGI运行的Web应用程序(因此我们可以引导它的一部分并在请求之间重用此位),并使用composer(它的类映射可以用于此目的吗?)。 / p>

这里有一些背景信息:

"定期" PHP应用程序处理单个请求然后它们被杀死。预加载所有类/函数意味着具有更大的启动时间,自动加载仅用于请求的类是一个聪明的优化,但它可以进一步改进(它们需要许多"读取文件系统"操作很慢),通常由在可能用于所有请求的单个文件类中进行分组(这是ClassPreloader解决的问题。)

然而,引导应用程序只处理一个请求然后终止它并不是唯一的选择:使用PHP FastCGI可以在请求之间保持应用程序处于活动状态。这允许我们在请求/响应时间之外减少启动时间(例如,从DIC实例化所有服务一次)。

在分析我的应用程序时,我注意到自动加载总是出现在前十大最昂贵的独占函数调用中。在PHP FastCGI应用程序中,在引导阶段移动类加载以将其从请求/响应时间完全移除可能是有意义的。我试图找出答案(我会做一些基准测试并发布结果)。

有关这个"异国情调"的更多信息。运行PHP应用程序的方法,请参阅:

3 个答案:

答案 0 :(得分:4)

别。如果启用了opcache,则没有性能优势,并且它也可能浪费内存(您并不总是需要加载所有类)。

以下是基准:https://phpixie.com/blog/benchmarking-autoloading-vs-combining-classes-into-a-single-file.html

答案 1 :(得分:1)

如果您正在使用composer,则composer include语句的返回值将是Composer\Autoload\ClassLoader的实例。在此对象上调用loadClass()方法将包含类文件。因此,当你真正需要这个类时,PHP已经知道它的定义,并且不需要调用composer在'spl_autoload_register'中注册的回调。

<?php

/** @var Composer\Autoload\ClassLoader **/
$classLoader = include 'vendor/autoload.php';

$classLoader->loadClass('Path\\To\\MyClass');
$classLoader->loadClass('Path\\To\\OtherClass');
// ...

编辑:请注意,在您的方案中可能更有用的是预加载服务。实际上,实例化应用程序所需的类可能比让PHP读取它们的定义更昂贵。如何预加载服务将取决于您的依赖注入容器,但只是“获取”服务将强制容器实例化并记住它。

OP编辑:以下是使用ReactPHP在“空”symfony应用程序上完成的实验。

  1. 使用预装课程的基准测试,失去8%的表现:https://github.com/gnugat-examples/bench-sf-standard/commit/c23d681cddc105b3a78f05679b2cffa84657f742
  2. 在预加载的类之上使用预加载的服务进行基准测试,与没有增殖类/服务的性能相同:https://github.com/gnugat-examples/bench-sf-standard/commit/79a16cd3a7184aea6ed35461c4368dec32289ac9
  3. 因此,令人惊讶的是,在启动服务器之前预热服务或类别不会带来性能提升。

答案 2 :(得分:1)

事实证明,作曲家可以选择预先包含文件。请参阅doc。 复制自doc:

{
  "autoload": {
    "files": ["src/preload.php"]
  }
}

您可以运行必要的代码启动/预加载,在您的情况下使用:

class_exists(SomeClass1::class, TRUE);
class_exists(SomeClass2::class, TRUE);

强制类的自动加载是一种技巧。