
# パフォーマンス

shikiphpは純粋なPHPでTextMateのトークン化を実行します。得意な処理とそうでない処理を正直に説明します。

## 期待できること

ファイルごとに数十〜数百ミリ秒かかると考えてください。マイクロ秒単位ではありません。トークナイザーはコンパイル済みルールとスキャナーをキャッシュし、文法は遅延読み込みされます（埋め込み言語に触れないサンプルでは、その文法のデコードは発生しません）。多くの文法パターンは、同等性を検証したPCRE高速パスでネイティブ`preg_*`を通して実行され、残りは純粋なPHPマッチャーが処理します（[アーキテクチャ](https://shikiphp.inline0.dev/ja/docs/architecture#the-scanner-and-its-pcre-fast-path)を参照）。

以下は、リポジトリのベンチマーク（`bench/bench.php`、テーマ`github-dark`）で、約55〜105行のコーパスファイルを1台のマシンで処理した際の、ウォーム状態での単一呼び出しの時間です：

| 文法 | PHP 8.2 | PHP 8.4 |
| --- | --- | --- |
| JSON、YAML | 30–65 ms | 25–45 ms |
| CSS、HTML | 100–120 ms | 80–100 ms |
| Python、Rust、Go、Bash、Markdown | 190–220 ms | 125–175 ms |
| PHP | 約290 ms | 約170 ms |
| TypeScript、TSX | 490–510 ms | 310–370 ms |

プロセス内である言語を初めて処理する際は、文法の読み込みとコンパイルに一度だけ時間がかかります。同じ実行ではJSONの50〜70 msから、Markdownの1秒強まで幅がありました。コストは文法の複雑さと入力サイズに応じて変わり、ハードウェアによって数値も異なるため、手元の環境で計測してください。リポジトリをクローンして、`composer install`、続けて`composer bench`を実行します。

## 安全対策

正規表現エンジンには失敗のメモ化とReDoS対策が組み込まれており、極端なパターンでも処理が停止せず、性能が低下するだけです。[`tokenizeMaxLineLength`](https://shikiphp.inline0.dev/ja/docs/options#tokenizemaxlinelength)を使って行ごとの処理量を制限することもできます。指定した長さ以上の行は単一のプレーンなトークンとして出力され、悪意のある極端な単一行入力への対策になります。

## 本番環境でのキャッシュ

リクエスト処理で強調表示を実行しないための確実な方法は、**毎回のリクエストで実行しないこと**です。同じオプションで同じコードを強調表示すれば、常に同じHTMLが生成されるため、完全にキャッシュできます：

- 静的サイトやドキュメントでは、ビルド時に強調表示します。
- ユーザー入力やデータベースに保存されたコード断片は、レンダリング済みのHTMLを（コードとオプションをキーにして）キャッシュし、ソースが変更されるまで再利用します。

プロセス内では、単一のハイライターを再利用してください（`Shikiphp`ファサードが自動で処理します）。呼び出し間で文法とテーマのキャッシュが共有されます。
