
# 성능

shikiphp는 순수 PHP에서 실제 TextMate 토큰화를 수행하므로, 어디서 빠르고 어디서 그렇지 않은지 솔직히 설명하겠습니다.

## 기대할 수 있는 성능

파일당 수십~수백 밀리초를 예상하세요. 마이크로초 단위는 아닙니다. 토크나이저는 컴파일된 규칙과 스캐너를 캐시하고, 문법은 지연 로드됩니다(포함된 언어를 전혀 사용하지 않는 샘플은 해당 언어를 디코딩하는 비용이 들지 않습니다). 또한 대부분의 문법 패턴은 동등성 검사를 통과한 PCRE 빠른 경로에서 네이티브 `preg_*`를 사용하고, 나머지는 순수-PHP 매처가 처리합니다([아키텍처](https://shikiphp.inline0.dev/ko/docs/architecture#the-scanner-and-its-pcre-fast-path) 참조).

다음은 저장소의 벤치마크(`bench/bench.php`, 테마 `github-dark`)에서 한 대의 머신으로 약 55~105줄인 코퍼스 파일을 대상으로 측정한, 워밍업 후 단일 호출 시간입니다:

| 문법 | 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/ko/docs/options#tokenizemaxlinelength)로 줄별 작업량을 제한할 수 있습니다. 지정한 길이 이상인 줄은 일반 토큰 하나로 출력하여 악의적인 단일 줄 입력을 방지합니다.

## 프로덕션 환경에서 캐싱하기

요청 처리 경로에서 강조 표시 작업을 제외하는 확실한 방법은 매 요청마다 실행하지 않는 것입니다. 같은 옵션으로 같은 코드를 강조 표시하면 항상 동일한 HTML가 생성되므로 캐시에 아주 적합합니다:

- 정적 사이트와 문서는 빌드 시점에 강조 표시합니다.
- 사용자가 제공하거나 데이터베이스에 저장된 코드 조각의 렌더링된 HTML를 캐시(코드 + 옵션을 키로 사용)하고 소스가 바뀔 때까지 재사용합니다.

프로세스 내에서는 하이라이터를 하나만 만들어 재사용하세요(`Shikiphp` 파사드가 이를 처리합니다). 그러면 호출 간에 문법 및 테마 캐시가 공유됩니다.
