如何优化symfony(PHP)的性能

Symfony 很快,开箱即用。但是,如果按照以下性能检查表中的说明优化服务器和应用程序,则可以加快速度。

性能优化清单

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

 

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

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

 

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

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

 

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

Symfony默认将服务容器编译成多个小文件。将此参数设置true为将整个容器编译为单个文件,这可以提高在 PHP 7.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 Flexconfig/preload.php时创建的 文件 :

; php.ini
opcache.preload=/path/to/project/config/preload.php

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

如果此文件丢失,请运行此命令以重新安装 Symfony Flex 配方: composer recipes:install symfony/framework-bundle --force -v.

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

 

配置 OPcache 以获得最佳性能

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

; 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 会检查缓存文件自被缓存以来是否更改了它们的内容。此检查引入了一些可以避免的开销,如下所示:

; php.ini
opcache.validate_timestamps=0

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

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

 

配置 PHPrealpath缓存

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

; 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

realpathopen_basedir配置选项启用时,PHP 会禁用缓存。

 

优化 Composer 自动加载器

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

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

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

 

分析 Symfony 应用程序

使用 Blackfire 进行分析

Blackfire是在开发、测试和生产过程中分析和优化 Symfony 应用程序性能的最佳工具。这是一项商业服务,但提供免费功能,您可以使用这些功能查找项目中的瓶颈。

使用 Symfony 秒表进行分析

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

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

使用autowiring 时,使用Stopwatch类对任何控制器或服务参数进行类型提示,Symfony 将注入debug.stopwatch服务:

use Symfony\Component\Stopwatch\Stopwatch;

class DataExporter
{
    private $stopwatch;

    public function __construct(Stopwatch $stopwatch)
    {
        $this->stopwatch = $stopwatch;
    }

    public function export()
    {
        // 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');
    }
}

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

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

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

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

{% stopwatch 'render-blog-posts' %}
    {% for post in blog_posts %}
        {# ... #}
    {% endfor %}
{% endstopwatch %}

分析类别

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

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

分析期

一个真实世界的秒表不仅包括启动/停止按钮,但也有“一圈按钮”来衡量每个部分的大腿上。这正是该lap() 方法所做的,它停止一个事件,然后立即重新启动它:

$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();

分析部分

部分是将配置文件时间线分成组的一种方式。例子:

$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');

如何优化symfony(PHP)的性能
标签: