跳到内容

性能

编辑此页

Symfony 开箱即用就很快。但是,如果您按照以下性能检查清单中的说明优化您的服务器和应用程序,您可以使其更快。

性能检查清单

使用这些检查清单来验证您的应用程序和服务器是否配置为获得最佳性能

如果您的服务器使用 APC,请安装 APCu Polyfill

如果您的生产服务器仍然使用旧的 APC PHP 扩展而不是 OPcache,请在您的应用程序中安装 APCu Polyfill 组件,以启用与 APCu PHP 函数的兼容性,并解锁对高级 Symfony 功能的支持,例如 APCu 缓存适配器。

限制应用程序中启用的区域设置数量

使用 framework.enabled_locales 选项仅生成您的应用程序中实际使用的翻译文件。

将服务容器转储到单个文件

默认情况下,Symfony 将 服务容器 编译成多个小文件。将此参数设置为 true 以将整个容器编译成单个文件,这可以在 PHP 7.4 或更高版本中使用“类预加载”时提高性能

1
2
3
4
# config/services.yaml
parameters:
    # ...
    .container.dumper.inline_factories: true

提示

. 前缀表示仅在容器编译期间使用的参数。有关更多详细信息,请参阅 配置参数

使用 OPcache 字节码缓存

OPcache 存储编译后的 PHP 文件,以避免为每个请求重新编译它们。有一些可用的 字节码缓存,但从 PHP 5.5 开始,PHP 自带了内置的 OPcache。对于旧版本,最广泛使用的字节码缓存是 APC。

使用 OPcache 类预加载

从 PHP 7.4 开始,OPcache 可以在启动时编译和加载类,并使它们可用于所有请求,直到服务器重新启动,从而显着提高性能。

在容器编译期间(例如,当运行 cache:clear 命令时),Symfony 会生成一个文件,其中包含要预加载到 var/cache/ 目录中的类列表。与其直接使用此文件,不如使用在使用 Symfony Flex 在您的项目中 时创建的 config/preload.php 文件

1
2
3
4
5
; php.ini
opcache.preload=/path/to/project/config/preload.php

; required for opcache.preload:
opcache.preload_user=www-data

如果此文件丢失,请运行以下命令以更新 Symfony Flex 配方:composer recipes:update symfony/framework-bundle

使用 container.preloadcontainer.no_preload 服务标签来定义哪些类应该或不应该由 PHP 预加载。

配置 OPcache 以获得最佳性能

默认的 OPcache 配置不适合 Symfony 应用程序,因此建议按如下方式更改这些设置

1
2
3
4
5
6
; php.ini
; maximum memory that OPcache can use to store compiled PHP files
opcache.memory_consumption=256

; maximum number of files that can be stored in the cache
opcache.max_accelerated_files=20000

不要检查 PHP 文件时间戳

在生产服务器中,PHP 文件永远不应更改,除非部署新的应用程序版本。但是,默认情况下,OPcache 会检查缓存文件自缓存以来是否已更改其内容。此检查会引入一些开销,可以通过以下方式避免

1
2
; php.ini
opcache.validate_timestamps=0

每次部署后,您必须清空并重新生成 OPcache 的缓存。否则,您将看不到应用程序中所做的更新。鉴于在 PHP 中,CLI 和 Web 进程不共享同一个 OPcache,您无法通过在终端中执行某些命令来清除 Web 服务器 OPcache。以下是一些可能的解决方案

  1. 重启 Web 服务器;
  2. 通过 Web 服务器调用 apc_clear_cache()opcache_reset() 函数(即通过在您通过 Web 执行的脚本中包含这些函数);
  3. 使用 cachetool 实用程序从 CLI 控制 APC 和 OPcache。

配置 PHP realpath 缓存

当相对路径转换为其真实和绝对路径时,PHP 会缓存结果以提高性能。打开许多 PHP 文件的应用程序(例如 Symfony 项目)应至少使用以下值

1
2
3
4
5
6
; php.ini
; maximum memory allocated to store the results
realpath_cache_size=4096K

; save the results for 10 minutes (600 seconds)
realpath_cache_ttl=600

注意

当启用 open_basedir 配置选项时,PHP 会禁用 realpath 缓存。

优化 Composer 自动加载器

在开发应用程序时使用的类加载器经过优化,可以查找新的和更改的类。在生产服务器中,PHP 文件永远不应更改,除非部署新的应用程序版本。这就是为什么您可以优化 Composer 的自动加载器,以扫描整个应用程序一次并构建优化的“类映射”,这是一个包含所有类位置的大型数组,它存储在 vendor/composer/autoload_classmap.php 中。

执行以下命令以生成新的类映射(并使其成为您部署过程的一部分)

1
$ composer dump-autoload --no-dev --classmap-authoritative
  • --no-dev 排除仅在开发环境中需要的类(即 require-dev 依赖项和 autoload-dev 规则);
  • --classmap-authoritative 为您的应用程序中使用的 PSR-0 和 PSR-4 兼容类创建类映射,并防止 Composer 扫描文件系统中类映射中未找到的类。(请参阅:Composer 的自动加载器优化)。

在调试模式下禁用将容器转储为 XML

调试模式 下,Symfony 生成一个 XML 文件,其中包含所有 服务容器 信息(服务、参数等)。此 XML 文件供各种调试命令使用,例如 debug:containerdebug:autowiring

当容器变得越来越大时,文件的大小和生成时间也会随之增加。如果此 XML 文件的优势没有超过性能下降,您可以按如下方式停止生成该文件

1
2
3
4
# config/services.yaml
parameters:
    # ...
    debug.container.dump: false

Symfony 应用性能分析

使用 Blackfire 进行性能分析

Blackfire 是在开发、测试和生产期间分析和优化 Symfony 应用程序性能的最佳工具。它是一项商业服务,但提供 功能齐全的演示

使用 Symfony Stopwatch 进行性能分析

Symfony 在开发 配置环境 中提供了一个基本的性能分析器。单击 Web 调试工具栏 的“时间面板”,查看 Symfony 在执行数据库查询和渲染模板等任务上花费了多少时间。

借助 Stopwatch 组件,您可以测量自己的代码的执行时间和内存消耗,并在 Symfony 分析器中显示结果。

当使用 自动装配 时,使用 Stopwatch 类类型提示任何控制器或服务参数,Symfony 将注入 debug.stopwatch 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use Symfony\Component\Stopwatch\Stopwatch;

class DataExporter
{
    public function __construct(
        private Stopwatch $stopwatch,
    ) {
    }

    public function export(): void
    {
        // the argument is the name of the "profiling event"
        $this->stopwatch->start('export-data');

        // ...do things to export data...

        // reset the stopwatch to delete all the data measured so far
        // $this->stopwatch->reset();

        $this->stopwatch->stop('export-data');
    }
}

如果请求在其执行期间调用此服务,您将在 Symfony 分析器中看到一个名为 export-data 的新事件。

start()stop()getEvent() 方法返回一个 StopwatchEvent 对象,该对象提供有关当前事件的信息,即使它仍在运行。此对象可以转换为字符串以进行快速摘要

1
2
// ...
dump((string) $this->stopwatch->getEvent('export-data')); // dumps e.g. '4.50 MiB - 26 ms'

您还可以使用 stopwatch Twig 标签分析您的模板代码

1
2
3
4
5
{% stopwatch 'render-blog-posts' %}
    {% for post in blog_posts %}
        {# ... #}
    {% endfor %}
{% endstopwatch %}

性能分析类别

使用 start() 方法的第二个可选参数来定义事件的类别或标签。这有助于按类型组织事件

1
$this->stopwatch->start('export-data', 'export');

性能分析周期

一个 真实世界的秒表 不仅包括开始/停止按钮,还包括一个“单圈按钮”来测量每个部分单圈。这正是 lap() 方法的作用,它停止一个事件,然后立即重新启动它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$this->stopwatch->start('process-data-records', 'export');

foreach ($records as $record) {
    // ... some code goes here
    $this->stopwatch->lap('process-data-records');
}

$event = $this->stopwatch->stop('process-data-records');
// $event->getDuration(), $event->getMemory(), etc.

// Lap information is stored as "periods" within the event:
// $event->getPeriods();

// Gets the last event period:
// $event->getLastPeriod();

7.2

getLastPeriod() 方法在 Symfony 7.2 中引入。

性能分析部分

部分是将性能分析时间线分成组的一种方式。例如

1
2
3
4
5
6
7
8
9
10
$this->stopwatch->openSection();
$this->stopwatch->start('validating-file', 'validation');
$this->stopwatch->stopSection('parsing');

$events = $this->stopwatch->getSectionEvents('parsing');

// later you can reopen a section passing its name to the openSection() method
$this->stopwatch->openSection('parsing');
$this->stopwatch->start('processing-file');
$this->stopwatch->stopSection('parsing');

所有不属于任何命名部分的事件都将添加到名为 __root__ 的特殊部分。这样,即使您不知道它们的名称,也可以获取所有秒表事件,如下所示

1
2
3
4
5
use Symfony\Component\Stopwatch\Stopwatch;

foreach($this->stopwatch->getSectionEvents(Stopwatch::ROOT) as $event) {
    echo (string) $event;
}

7.2

作为 __root__ 快捷方式的 Stopwatch::ROOT 常量在 Symfony 7.2 中引入。

这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。
TOC
    版本