성능
시놀로지 Web Station PHP opcache 포화 확인하고 512MB로 늘리기
PHP 사이트 23개가 한 프로파일을 쓰던 Web Station에서 opcache 적중률 45.8%를 확인하고, user_settings.ini와 PHPSettings.json을 함께 고쳐 512MB로 늘린 뒤 TTFB가 0.3~0.45초로 줄어든 기록입니다.
시놀로지 Web Station에서 PHP 사이트 23개를 PHP 8.4 프로파일 하나로 돌리고 있습니다. 워드프레스 몇 곳의 첫 화면이 0.8초에서 길게는 1.9초까지 걸려서 원인을 보다가, PHP가 요청의 절반 가까이를 매번 다시 컴파일하고 있다는 걸 알았습니다. opcache가 꽉 차 있었습니다.
opcache는 PHP 파일을 한 번 컴파일한 결과를 메모리에 두고 재사용하는 캐시입니다. 기본 크기가 128MB인데, 사이트 23개가 한 풀을 나눠 쓰니 금방 넘쳤습니다.
처음엔 아예 꺼져 있었습니다
9월 22일에 처음 봤을 때는 opcache가 로드조차 안 돼 있었습니다. 이 프로파일의 캐시 설정(enable_cache)이 꺼져 있었고, 런타임에서 확인해도 opcache가 없었습니다. 같은 NAS의 PHP 8.2 프로파일은 켜져 있었으니, 8.4로 옮기면서 빠진 것으로 보입니다.
다음 날 다시 보니 opcache는 올라와 있었지만 이번엔 128MB가 꽉 차 있었습니다.
포화 여부는 opcache_get_status로 봅니다
웹 루트에 임시 PHP 파일을 하나 만들어 브라우저로 열어 봅니다. CLI로 실행하면 웹 서버의 PHP-FPM과 다른 프로세스라 의미가 없습니다. 확인이 끝나면 반드시 지웁니다.
<?php
$s = opcache_get_status(false);
header('Content-Type: text/plain');
printf("used %d MB\n", $s['memory_usage']['used_memory'] / 1048576);
printf("free %d MB\n", $s['memory_usage']['free_memory'] / 1048576);
printf("full %s\n", var_export($s['cache_full'], true));
printf("hit %.1f %%\n", $s['opcache_statistics']['opcache_hit_rate']);
printf("oom %d\n", $s['opcache_statistics']['oom_restarts']);
포화 신호는 네 가지입니다.
free_memory가 0에 가까움cache_full이true- 적중률(
opcache_hit_rate)이 90% 아래 oom_restarts가 늘어남 — 메모리가 모자라 캐시를 통째로 비우고 다시 시작한 횟수
제 결과는 적중률 45.8%, 빈 메모리 0, 캐시 가득, OOM 재시작 하루 2번이었습니다. 요청 절반 이상을 다시 컴파일하고 있었다는 뜻입니다.
설정 파일은 두 곳을 같이 고칩니다
Web Station의 PHP 프로파일 설정은 두 군데에 있습니다. 여기서 한 번 헛걸음을 했습니다.
| 파일 | 역할 |
|---|---|
/usr/syno/etc/packages/WebStation/php_profile/<UUID>/conf.d/user_settings.ini | PHP가 실제로 읽는 ini (PHP_INI_SCAN_DIR) |
/usr/syno/etc/packages/WebStation/PHPSettings.json | Web Station 화면이 기억하는 값. 화면에서 저장하면 이걸 기준으로 ini를 다시 만듦 |
처음엔 PHPSettings.json의 php_settings만 고치고 서비스를 재시작했는데 반영이 안 됐습니다. ini는 화면에서 저장할 때만 다시 만들어지기 때문입니다. 그렇다고 ini만 고치면 나중에 누가 화면에서 저장하는 순간 128MB로 돌아갑니다. 그래서 둘 다 고쳤습니다.
user_settings.ini 끝에 넣은 값입니다.
opcache.memory_consumption = 512
opcache.interned_strings_buffer = 32
opcache.max_accelerated_files = 20000
PHPSettings.json에서는 해당 프로파일의 php_settings에 같은 키를 넣었습니다.
"php_settings": {
"opcache.memory_consumption": "512",
"opcache.interned_strings_buffer": "32",
"opcache.max_accelerated_files": "20000"
}
max_accelerated_files는 캐시할 수 있는 파일 개수 상한입니다. 워드프레스는 코어와 플러그인만으로 PHP 파일이 수천 개라, 사이트 여러 개를 한 풀에 두면 메모리보다 이 개수가 먼저 찰 수 있습니다.
재시작은 이 프로파일만
적용은 root에서 이 프로파일의 FPM 서비스만 재시작했습니다. 몇 초 끊깁니다.
systemctl restart pkg-WebStation-php84@<UUID>.service
synoservice --restart pkgctl-PHP8.4를 쓰면 PHP 8.4 프로파일 전체가 재시작되니, 프로파일이 여러 개라면 범위가 더 넓어집니다. 시작 전에 두 파일은 백업해 뒀습니다.
결과
| 사이트 | 바꾸기 전 (9/23) | 바꾼 직후 (9/23) | 나흘 뒤 (9/27) |
|---|---|---|---|
| 사이트 A | 1.3~1.9초 | 0.45초 | 0.37초 |
| 사이트 B | 0.9~1.0초 | 0.28초 | 0.28~0.36초 |
| 사이트 C | 0.83초 | 0.40초 | 0.40~0.43초 |
| 사이트 D | 0.78초 | 0.31초 | 0.30~0.31초 |
9월 27일 값은 같은 첫 화면을 네 번씩 요청해 두 번째부터의 값입니다. 첫 요청은 사이트에 따라 0.34~0.8초가 나왔습니다. 워밍업 뒤 기준으로는 나흘 동안 그대로 유지되고 있습니다.
이 NAS는 사용 가능한 메모리가 10GB 넘게 남아 있어서 512MB는 부담이 없었습니다. 메모리가 작은 모델이라면 먼저 used_memory를 보고 여유를 두고 정하는 게 맞습니다.
주의할 점이 하나 남습니다. Web Station 화면에서 이 프로파일을 저장하면 ini가 JSON 기준으로 다시 만들어집니다. JSON에도 넣어 뒀으니 유지될 거라고 보고 있지만, 화면에서 뭔가 저장한 뒤에는 위의 확인 파일로 한 번 더 보는 게 안전합니다. 디스크 쪽 병목과 헷갈리지 않으려면 관리자 화면만 느렸던 경우와 나눠서 보세요. 그건 원인이 전혀 달랐습니다.
확인한 공식 자료
구현 과정에서 판단 기준을 교차 확인한 공식 문서입니다. 글의 사례와 결론은 운영자가 직접 겪은 작업을 바탕으로 작성했습니다.