Drupal → Производительность Drupal::token()->replace() vs strtr() vs inline_template

10.04.2025

Результаты тестирования производительности \Drupal::token()->replace() против strtr().

Код теста:

use Drupal\Component\Utility\Timer;
use Drupal\node\Entity\Node;

$template = 'site name "[site:name]", current year "[current-date:custom:Y]", node label "[node:title]"';
$token_service = \Drupal::token();
$site_config = \Drupal::config('system.site');
$node = Node::create(['type' => 'page', 'title' => 'Test node']);

// Static cache warm up
echo 'strtr result: ' . strtr($template, [
  '[site:name]' => $site_config->get('name'),
  '[current-date:custom:Y]' => date('Y'),
  '[node:title]' => $node->label(),
]) . PHP_EOL;
echo 'token result: ' . $token_service->replace($template, ['node' => $node]) . PHP_EOL;

// Test strtr()
Timer::start('strtr');
for ($i = 0; $i < 1000; $i++) {
  strtr($template . ' ' . $i, [
    '[site:name]' => $site_config->get('name'),
    '[current-date:custom:Y]' => date('Y'),
    '[node:title]' => $node->label(),
  ]);
}
echo 'strtr time: ' . Timer::read('strtr') . ' ms' . PHP_EOL;

// Test \Drupal::token()->replace()
Timer::start('token');
for ($i = 0; $i < 1000; $i++) {
  $token_service->replace($template . ' ' . $i, ['node' => $node]);
}
echo 'token time: ' . Timer::read('token') . ' ms' . PHP_EOL;

Результаты:

strtr time: 9.91 ms
token time: 878.24 ms

Неожиданно. Я думал токены не сильно отстанут, а по факту на порядки медленнее. Очень печально.

Бонус 1: время замены токенов [current-date:custom:Y] vs [node:title] (клик чтобы раскрыть)

Код:

use Drupal\Component\Utility\Timer;
use Drupal\node\Entity\Node;

$template1 = '[current-date:custom:Y]';
$template2 = '[node:title]';
$token_service = \Drupal::token();
$node = Node::create(['type' => 'page', 'title' => 'Test node']);

// Static cache warm up
echo 'template1 result: ' . $token_service->replace($template1, ['node' => $node]) . PHP_EOL;
echo 'template2 result: ' . $token_service->replace($template2, ['node' => $node]) . PHP_EOL;

// Test [current-date:custom:Y]
Timer::start('template1');
for ($i = 0; $i < 1000; $i++) {
  $token_service->replace($template1 . ' ' . $i, ['node' => $node]);
}
echo '[current-date:custom:Y] time: ' . Timer::read('template1') . ' ms' . PHP_EOL;

// Test [node:title]
Timer::start('template2');
for ($i = 0; $i < 1000; $i++) {
  $token_service->replace($template2 . ' ' . $i, ['node' => $node]);
}
echo '[node:title] time: ' . Timer::read('template2') . ' ms' . PHP_EOL;

Результат:

[current-date:custom:Y] time: 544.72 ms
[node:title] time: 212.97 ms

Многоуровневые токены, которые повторно вызывают \Drupal::token()->generate(), работают в два+ раза медленнее обычных токенов.

Бонус 2: производительность inline_template (клик чтобы раскрыть)

Код:

use Drupal\Component\Utility\Timer;
use Drupal\node\Entity\Node;

$template = "site name '{{ site.get('name') }}', current year '{{ 'now'|date('Y') }}', node label '{{ node.label }}'";
$site_config = \Drupal::config('system.site');
$node = Node::create(['type' => 'page', 'title' => 'Test node']);
$renderer = \Drupal::service('renderer');

// Static cache warm up
$build = [
  '#type' => 'inline_template',
  '#template' => $template,
  '#context' => [
    'site' => $site_config,
    'node' => $node,
  ],
];
echo 'inline_template result: ' . $renderer->renderRoot($build) . PHP_EOL;

// Test
Timer::start('inline_template');
for ($i = 0; $i < 1000; $i++) {
  $build = [
    '#type' => 'inline_template',
    '#template' => $template . ' ' . $i,
    '#context' => [
      'site' => $site_config,
      'node' => $node,
    ],
  ];
  $renderer->renderRoot($build) . PHP_EOL;
}
echo 'inline_template time: ' . Timer::read('inline_template') . ' ms' . PHP_EOL;

Результат:

time: 860.64 ms

Так же медленно как токены. Здесь надо помнить, что на каждое значение в #template твиг создаст скомпилированный файл в public://php/twig (т.е. после запуска этого теста будет создан 1001 файл).

Файлы на гитхабе

Написанное актуально для
Drupal 10.4, PHP 8.3 (opcache=on)
Похожие записи

Добавить комментарий