性能
Symfony极其之快。当然了,如果你真正需要速度,还有许多能让你令Symfony变得更快的方法。本章,你将探索一些方法,来让Symfony程序快上加快。
使用Byte Code缓存(如OPcache) ¶
改善性能时你应该做的第一件事是使用一种“byte code cache”。这些缓存存储了编译后的PHP文件以避免在每次请求时重复编译它们。
有很多 byte code caches 可以利用,其中的一些还是开源的。截止到PHP 5.5, PHP内置了 OPcache 。老版本中最广泛使用的byte code cache是 APC。
使用byte code cache有百利而无一害,Symfony被打造成“可以在这种类型的环境中表现极佳”。
监控源文件的改变 ¶
多数byte code cache监控着源文件的改变。这可确保如果文件源代码发生改变,byte code将被自动编译。这非常方便,但有些过载。
因此,一些byte code caches提供了一个选项来关闭这些检查。例如,要在APC中关闭检查,直接添加 apc.stat=0
到你的 php.ini
配置文件中。
当关闭这些检查时,将由服务器管理员来负责“确保缓存在任何源文件发生改变时被清除”。否则,你的更新将不会在程序中被看到。
同理,byte code缓存必须在部署程序时被清除 (例如,使用APC时通过调用 apc_clear_cache()
PHP函数,以及,使用Opcache时通过 opcache_reset()
)。
在PHP中,命令行以及web进程并不共享相同的OPcache。这意味着你不能通过执行终端中的某些命令来清除web服务器上的OPcache。你可以重启服务器或者通过web服务器调用 apc_clear_cache()
或 opcache_reset()
函数(如,在执行web脚本时包容它们)。
优化全部Symfony使用的文件 ¶
默认时,PHP的OPcache在byte code缓存中存了2000个文件。这个数字对于一般的Symfony程序来说还是太小,因此你必须设置 opcache.max_accelerated_files 配置选项为更高的值:
1 2 |
; php.ini
opcache.max_accelerated_files = 20000 |
配置PHP realpath缓存 ¶
PHP使用了一个内部缓存来存储“类文件路径”映射到“文件系统真实路径”的结果。这提高了Symfony这种“开启许多PHP文件”的程序之性能,特别是在Windows平台上。
默认时PHP设置了一个 16K
的 realpath_cache_size
,这对Symfony来说实在太小。将这个值更新到至少 4096K
。此外,缓存路径默认时只保存 120
秒,同样考虑通过 realpath_cache_ttl
选项来更新此值:
1 2 3 |
; php.ini
realpath_cache_size=4096K
realpath_cache_ttl=600 |
使用Composer的类映射功能 ¶
默认时,Symfony标准版使用的是 autoload.php 文件中的Composer自动加载器(autoloader)。这个加载器很容易使用,因为它自动寻找任何“你在已注册目录中放置了”的新类。
不幸的是,这有使用成本,因为类加载器要遍历全部已配置的命名空间,以便找到一个特定文件,发起 file_exists()
的调用直到最终找到它想要的文件为止。
最简单的方案是告诉Composer构建一个优化过的"class map"(类映射),这是一个所有类所在位置的大数组,并且存放在 vendor/composer/autoload_classmap.php
中。
这个类映射可以由命令行生成,可能会成为你部署过程的一部分。
1 |
$ composer dump-autoload --optimize --no-dev --classmap-authoritative |
--optimize
- 剥离你程序中的每一个兼容PSR-0 和 PSR-4 的类。
--no-dev
- 排除那些你只在开发环境下使用的类(如tests)。
--classmap-authoritative
- 防止Composer在文件系统中寻找那些没有出现在类映射中的类。
用APC缓存Autoloader ¶
另一个方案是在类被首次定位之再来缓存其位置。Symfony自带了一个类 - ApcClassLoader
- 专门用来干这个。要使用它,只需适配你的前端控制器文件。如果你使用了标准版框架,可作出以下改变:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// app.php
// ...
use Symfony\Component\ClassLoader\ApcClassLoader;
$loader = require __DIR__.'/../app/autoload.php';
include_once __DIR__.'/../app/bootstrap.php.cache';
// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you wAnt in order
// to prevent key conflict with another application
// 使用APC自动加载以提升性能,改变'sf2'为你希望的前缀,
// 以防止同其他程序发生key冲突
$loader = new ApcClassLoader('sf2', $loader);
$loader->register(true);
// ... |
更多细节,参考 对Class Loader进行缓存 一文。
当使用APC autoloader时,如果你添加了新类,它们将被自动找到,所有东西的运作一如往常(即,并无必要“清除”缓存)。但是,如果你改变了某个特定命名空间或前缀的位置,你就需要flush你的APC缓存。否则,自动加载器仍将在那个命名空间的旧位置来寻找所有的类。
使用Bootstrap文件 ¶
为确保弹性优化和代码复用,Symfony程序利用了多样化的类和第三方组件。但在每次请求中从分散位置加载全部这些类会导致一定程度的过载。为减轻负责,Symfony提供了一个脚本来生成一个被称为 bootstrap file 文件,考量的是在单一文件中加载多个类定义。通过包容这个文件 (它包含了各种核心类的拷贝),Symfony不再需要包容任何“含有那些类”的源文件。这将减少不少的硬盘吞吐(disc IO)。
如果你正在使用Symfony标准版,那你应该已经使用了这个bootstrap启动文件。为确保使用,打开你的前端控制器(通常是 app.php
),然后检查以下代码行确实存在:
1 |
include_once __DIR__.'/../var/bootstrap.php.cache'; |
注意,当使用bootstrap文件时有两个不利点:
- 此文件会在任意原始资源发生改变时重新生成 (如,当你更新了Symfony的src代码或vendor三方类库时);
- 调试时,开发者需要在bootstrap文件中设置断点。
如果你使用的是Symfony标准版,启动文件将在vendor类库更新之后,透过 composer install
命令来自动重建(译注:指composer.json中的post脚本等,也可手动执行)
Bootstrap文件和Byte Code缓存 ¶
即便使用了一种byte code缓存,在使用bootstrap文件时仍会提高性能,这是因为需要监控“发生改变”的文件变少了。当然这个功能如果在byte code cache中被关闭的话 (即在APC中设置 apc.stat=0
),就再无理由使用bootstrap文件。