
# Производительность и тестирование

TailwindPHP в первую очередь оптимизируется ради корректности. Если изменение для PHP ускоряет работу и не меняет результат, его применяют и помечают как `@port-deviation:performance`. Соответствие TailwindCSS не предполагается — оно постоянно проверяется набором тестов Tailwind.

## Производительность

Порт PHP ставит соответствие результатам TailwindCSS выше максимальной пропускной способности, а исходный TypeScript в любом случае быстрее: JIT-компилятор V8 компилирует часто выполняемые участки в машинный код так, как PHP не может. Для CSS, генерируемого при каждом запросе или для каждой страницы, используйте один компилятор повторно (см. [generateExact()](https://tailwindphp.inline0.dev/ru/docs/api#accumulating-vs-exact-generation)) и сохраняйте его состояние после создания с помощью [`stateCacheFile`](https://tailwindphp.inline0.dev/ru/docs/advanced/caching#compiler-state-cache).

Некоторые часто выполняемые участки кода оптимизированы вручную так, чтобы **сохранять идентичный результат**:

- **`ast.php` `toCss()`** — накапливает фрагменты в массиве и один раз вызывает `implode`, вместо многократной конкатенации строк, а также использует заранее вычисленные строки отступов.
- **`css-parser.php`** — сравнивает символы напрямую, не обращаясь к `ord()`, и отслеживает длину буферов вместо повторного вычисления `strlen()`.

Обе оптимизации задокументированы с помощью `@port-deviation:performance` и проверяются набором тестов — они не могут изменить сгенерированный CSS.

### Сравнительные тесты

В директории `benchmarks/` находится средство для сравнительных тестов. Запустите его командой:

```bash
composer bench         # PHP vs TypeScript
composer bench:save    # write benchmarks/results.json
```

Примеры результатов на PHP 8.4.5 / Node.js v22.17.0 (Apple M1):

| Тест | PHP | TypeScript |
|-----------|-----|------------|
| `css-parser` в preflight.css | ~816 ops/s | ~15.45K ops/s (≈в 20 раз быстрее) |
| `toCss` | ~65.85K ops/s | ~2.59M ops/s (≈в 39 раз быстрее) |

TypeScript быстрее в этих низкоуровневых операциях, как и ожидалось. Для генерации CSS целых страниц — реального сценария использования — производительности PHP достаточно (примерно 14 мс на страницу в тестовом запуске). При повторении одинакового ввода [файловый кэш](https://tailwindphp.inline0.dev/ru/docs/advanced/caching) полностью устраняет эти затраты.

## Тестирование и соответствие

Тесты гарантируют, что порт PHP выдаёт тот же результат, что и TailwindCSS. Для этого вместе используются два подхода.

**1. Тесты на основе извлечения.** Скрипты в `test-coverage/` анализируют собственные файлы `.test.ts` проекта TailwindCSS и извлекают тестовые случаи в JSON. Затем PHPUnit прогоняет их через TailwindPHP и сравнивает результат с ожидаемым CSS. Поскольку эталонные результаты берутся непосредственно из исходного проекта, любое расхождение в поведении PHP обнаруживается как ошибка. Эти тесты охватывают сложные области: утилиты, варианты, интеграцию, функции CSS и тесты уровня браузера `ui.spec`.

**2. Перенесённые вручную модульные тесты.** Более простые тестовые файлы TypeScript (AST, разбор CSS, экранирование, разбор кандидатов и значений, …) напрямую перенесены в PHP и размещены рядом с исходным кодом как `*.test.php`, повторяя структуру и проверки оригиналов.

Цикл состоит из этапов **извлечь → запустить → проверить**: повторно извлечь тесты из текущего эталона TailwindCSS, запустить набор тестов, и любое расхождение приведёт к ошибке. Так порт остаётся синхронизированным с исходным проектом, а обновление TailwindCSS можно проверять автоматически, а не вручную. При расхождении сборка CI завершается с ошибкой.

```bash
composer extract   # re-extract test cases from the TailwindCSS reference
composer test      # run the full suite
```

По состоянию на выпуск 1.7.0 (эталон TailwindCSS v4.3.3) пройдено **4,427 тестов**:

| Набор | Тесты | Источник |
|-------|-------|--------|
| Извлечённые наборы TailwindCSS (утилиты 706, варианты 164, index 148, css-functions 64, `ui.spec` 68) | 1,150 | извлечены из `.test.ts` / `.spec.ts` |
| Покрытие API (утилиты, модификаторы, варианты, директивы, плагины, импорты, `@source`, кэширование, публичный API) | 2,252 | `tests/` |
| Модульные тесты рядом с исходным кодом (парсер, AST, кандидаты, тема, утилиты, парсер селекторов, преобразования lightningcss, минификатор) | 767 | порты `*.test.php` и тесты для PHP |
| CLI (разбор аргументов, вывод, сборки) | 84 | `tests/Cli*Test.php` |
| Порты плагинов (типографика, формы) | 45 | `*.test.php` рядом с плагинами |
| Вспомогательные библиотеки (clsx, tailwind-merge, CVA) | 129 | эталонные наборы |

## Качество кода

Форматирование и статический анализ выполняются скриптами Composer:

```bash
composer lint      # Pint --test  (check formatting)
composer format    # Pint         (fix formatting)
composer analyse   # PHPStan      (static analysis, level 4)
composer quality   # lint + analyse
```

PHPStan выполняет проверку на уровне 4 (`phpstan.neon`); для динамических форм массивов, используемых в архитектуре на основе функций, задан небольшой список игнорируемых шаблонов. Анализируются все исходные файлы, тестовые файлы исключены.

О структуре, проверяемой этими тестами, и регистрации отклонений см. в разделе [Архитектура](https://tailwindphp.inline0.dev/ru/docs/advanced/architecture).
