有没有办法预加载(而不是自动加载(PHP项目的所有类/函数?
我正在考虑一个使用 PHPFastCGI 运行的 Web 应用程序(因此我们可以引导它的一部分并在请求之间重用此位(,并且使用 composer(它的类映射可以用于此目的吗?
以下是一些上下文:
"常规"PHP 应用程序处理单个请求,然后它们被杀死。预加载所有类/函数意味着具有更大的引导时间,仅自动加载用于请求的类是一个聪明的优化,但可以进一步改进(它们需要许多缓慢的"读取文件系统"操作(,通常通过分组到可能用于所有请求的单个文件类中(这是 ClassPreloader 解决的问题(。
然而,引导应用程序只处理一个请求,然后杀死它并不是唯一的选择:使用 PHP FastCGI,可以在请求之间保持应用程序的活动状态。这使我们能够缩短请求/响应时间的启动时间(例如,从DIC实例化所有服务一次(。
在分析我的应用程序时,我注意到自动加载总是出现在前 10 个最昂贵的独占函数调用中。在 PHP FastCGI 应用程序中,在引导阶段移动类加载以将其从请求/响应时间中完全删除可能是有意义的。我正在尝试找出答案(我将进行一些基准测试并发布结果(。
有关这种运行 PHP 应用程序的"奇特"方式的更多信息,请参阅:
- 使用 ReactPHP 保持应用程序存活:http://marcjschmidt.de/blog/2014/02/08/php-high-performance.html
- Fabien Potencier谈论它:https://youtu.be/gpNbmEnRLBU
- 使用 PHPFastCGI 让 FastCGI(例如.php-fpm(管理 PHP 进程:http://andrewcarteruk.github.io/slides/breaking-boundaries-with-fastcgi/
- 使用 Aerys,一个非阻塞 HTTP 应用程序:http://blog.kelunik.com/2015/10/21/getting-started-with-aerys.html
- 使用应用服务器,本机 PHP Web 服务器:http://www.sitepoint.com/appserver-a-production-ready-php-based-server/
不要。如果启用 opcache,则不会带来任何性能优势,而且还可能浪费内存(您并不总是需要加载所有类(。
这是基准: https://phpixie.com/blog/benchmarking-autoloading-vs-combining-classes-into-a-single-file.html
事实证明,作曲家可以选择预先包含文件。请参阅文档。从文档复制:
{
"autoload": {
"files": ["src/preload.php"]
}
}
您可以运行必要的代码启动/预加载,并在您的情况下使用:
class_exists(SomeClass1::class, TRUE);
class_exists(SomeClass2::class, TRUE);
这是强制自动加载类的技巧。
如果您使用的是 composer,则 composer include 语句的返回值将是 Composer\Autoload\ClassLoader 的实例。在此对象上调用 loadClass(( 方法将包含类文件。因此,当你实际需要这个类时,PHP 已经知道它的定义,并且不需要调用作曲家用 'spl_autoload_register' 注册的回调。
<?php
/** @var ComposerAutoloadClassLoader **/
$classLoader = include 'vendor/autoload.php';
$classLoader->loadClass('Path\To\MyClass');
$classLoader->loadClass('Path\To\OtherClass');
// ...
编辑:请注意,在你的方案中可能更有用的是预加载服务。实际上,实例化应用程序所需的类可能比让 PHP 读取其定义的成本更高。如何预加载服务将取决于您的依赖注入容器,但只需"获取"服务将强制容器实例化它并记住它。
OP编辑:这是使用ReactPHP在一个"空"symfony应用程序上完成的实验。
- 使用预加载类进行基准测试,损失 8% 的性能:https://github.com/gnugat-examples/bench-sf-standard/commit/c23d681cddc105b3a78f05679b2cffa84657f742 在预加载类
- 之上使用预加载服务进行基准测试,与没有预加载类/服务的性能相同:https://github.com/gnugat-examples/bench-sf-standard/commit/79a16cd3a7184aea6ed35461c4368dec32289ac9
因此,令人惊讶的结论是,在启动服务器之前预热服务或类不会带来任何性能改进。