# opcache preload deploy faturasını on dört kata kadar siliyor — ama yedi framework'ün beşi onu size vermiyor

> Ayak izi ölçümünün ortam künyesinde bir satır vardı: 'preload yok'. Aynı imajlar, aynı rota, aynı ölçüm — bu kez preload açık. Üç varyant: yok, framework'ün kendi dosyası, ve Composer classmap'inden üretilmiş tek tip bir tavan.

- Tür: Ölçüm
- Soru: `opcache.preload` açıkken yedi PHP framework'ünün deploy sonrası ilk isteği ne kadar sürüyor, bu kazanç neye mal oluyor, ve kimler ona erişebiliyor?
- Bulgu: Preload, soğuk ilk isteği 3,5 ile 14,2 kat arasında kısaltıyor: Symfony 35,58 ms'den 2,50 ms'ye, yani Phalcon'un çıplak seviyesine iniyor. Ama yedi adayın yalnız ikisi (Symfony, CodeIgniter) resmî bir preload dosyası yayınlıyor; kalan beşinde kazanç masada duruyor ve kullanıcının kendi yazmasını bekliyor. Yazmak da göründüğü kadar kolay değil: classmap'ten körlemesine üretilen preload Symfony'yi hiç ayağa kaldırmıyor, CodeIgniter'da ise elle seçilmiş resmî dosyadan (3,13 ms) daha kötü sonuç veriyor (5,29 ms). Ve bedel kaybolmuyor: Laravel'in classmap preload'ı ziyaretçiden aldığı 62 ms'yi php-fpm'in ayağa kalkışına 2.340 ms olarak yazıyor.
- Yöntem: Ayak izi ve yük ölçümleriyle birebir aynı imajlar, aynı PHP 8.4 derlemesi, aynı nginx + php-fpm yığını. Hiçbir imaj yeniden derlenmedi: opcache `conf.d`'yi sırayla okuduğu için çalışma anında mount edilen bir `02-*.ini`, imaja gömülü `00-bench-opcache.ini`'yi eziyor. Aday başına üç varyant koşuldu — preload yok, framework'ün kendi dosyası (konteyner içinde aranarak bulunur, elle yazılmaz), ve Composer classmap'indeki her sınıfı `opcache_compile_file` ile derleyen tek tip bir dosya. Her varyant için taze konteyner ayağa kaldırıldı ve **konteynerin sunduğu ilk istek** ölçüldü; hazırlık yoklamasının kendisi o istektir, çünkü ayrı bir yoklama ilk isteği harcayıp geriye sıcak bir ölçüm bırakıyor. Üç tekrar, medyan raporlanıyor. Preload'ın bedeli php-fpm'in ilk 200 yanıtı verene kadar geçen süreyle ölçülüyor; bu pencere nginx'in kendi açılışını da içeriyor ama üç varyantta da aynı sabit. Doğrulama: `preload yok` varyantı 20 Ağustos'ta yayınlanan bağımsız koşunun soğuk sayılarını ±%6 içinde yeniden üretiyor.
- Metrikler: Symfony, soğuk ilk istek: 2,50 ms (−%93) · Resmî preload taşıyan aday: 2 / 7 · Laravel classmap, fpm bedeli: +2.340 ms · Elle seçim vs hepsini derle: 3,13 → 5,29 ms
- Ölçüm tarihi: 2026-08-22
- Güven: Yüksek güven
- Durum: Yürürlükte
- Program: Dil & çalışma zamanı
- Ortam: PHP 8.4.24 NTS · opcache açık · JIT kapalı · opcache validate_timestamps=0 · 256 MB · preload varyanta göre açık/kapalı · Sunucu nginx 1.29.1 + php-fpm · pm=static · 8 worker · Donanım Apple M4 Pro · 12 çekirdek · 24 GB · macOS 26.6.1 · Sanallaştırma Docker Desktop 29.7.2 · aarch64 · Tekrar 3 · medyan raporlanır · Temel çizgi doğrulaması 2026-08-20 koşusuna göre ±%6
- Teknolojiler: PHP, opcache, Laravel, Symfony, CodeIgniter, Yii2, Phalcon, Laminas, Slim, Docker, nginx, Composer
- Tekrarlamak için: REPEATS=3 ./bench/preload.sh
- Kaynak kodu: https://github.com/muhammetsafak/php-framework-bench
- Ham veri: https://github.com/muhammetsafak/php-framework-bench/blob/main/results/2026-08-22/preload.json
- Ham veri lisansı: https://github.com/muhammetsafak/php-framework-bench/blob/main/LICENSE
- Yayın: 2026-08-22
- Kaynak: https://www.muhammetsafak.com.tr/research/opcache-preload-deploy-faturasi/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
[Ayak izi ölçümü](/research/php-framework-ayak-izi/) bir sayı bırakmıştı: taze bir
konteynerin karşıladığı ilk istekte Phalcon 2,2 ms, Laravel 72,2 ms — otuz üç
kat. Deploy'dan sonraki ilk ziyaretçinin ödediği derleme faturası bu. Aynı
kaydın ortam künyesinde de bir satır vardı: **preload yok.**

Bu kayıt o satırı kapatıyor. Tek değişken.

## Kazanç

**Deploy sonrası ilk isteğin süresi, preload açık ve kapalıyken**

Her adayın en iyi preload varyantı gösteriliyor: Symfony ve CodeIgniter'da kendi resmî dosyaları, diğerlerinde classmap'ten üretilen tavan.

Kaynak: bench/preload.sh, üç tekrarın medyanı

|  | Laravel | Symfony | Laminas | CodeIgniter | Yii2 | Slim | Phalcon |
| --- | --- | --- | --- | --- | --- | --- | --- |
| preload yok | 76.31 ms | 35.58 ms | 26.7 ms | 20.75 ms | 16.98 ms | 7.46 ms | 2.68 ms |
| preload açık | 13.98 ms | 2.5 ms | 3.81 ms | 3.13 ms | 4.8 ms | 1.86 ms | 1.99 ms |

| Aday | preload yok | resmî | classmap | En iyi kazanç | fpm bedeli |
| --- | --- | --- | --- | --- | --- |
| Laravel | 76,31 ms | yok | 13,98 ms | 5,5× | +2.340 ms |
| Symfony | 35,58 ms | 2,50 ms | kırıldı | 14,2× | −40 ms |
| Laminas | 26,70 ms | yok | 3,81 ms | 7,0× | −7 ms |
| CodeIgniter | 20,75 ms | 3,13 ms | 5,29 ms | 6,6× | −12 ms |
| Yii2 | 16,98 ms | yok | 4,80 ms | 3,5× | +13 ms |
| Slim | 7,46 ms | yok | 1,86 ms | 4,0× | +28 ms |
| Phalcon | 2,68 ms | yok | 1,99 ms | 1,3× | +43 ms |

fpm bedeli = konteynerin ilk 200 yanıtı verene kadar geçen sürenin preload'sız hâle göre farkı. Negatif değerler ölçüm gürültüsüdür, kazanç değil.

Ayak izi kaydının otuz üç kat farkı preload'la kapanıyor: Symfony 2,50 ms'ye,
yani Phalcon'un **çıplak** seviyesine iniyor. Fark framework'ün ağırlığından
değil, opcache'in soğuk olmasından geliyormuş.

## Ama beşinde yok

| Aday | Resmî preload | Nerede |
| --- | --- | --- |
| Symfony | var | var/cache/prod/*.preload.php (warm-up üretiyor) |
| CodeIgniter | var | preload.php (başlangıç şablonunda) |
| Laravel | yok | — |
| Yii2 | yok | — |
| Laminas | yok | — |
| Slim | yok | — |
| Phalcon | yok | gerekmiyor |

Dosyalar imajın içinde arandı, listeye elle yazılmadı: yol bir framework kararıdır ve sürümler arasında taşınır.

Tablonun ikinci sütunu birinci sütundan daha çok şey söylüyor. Kazanç var ama
**beş adayda kullanıcının kendi yazmasını bekliyor** — ve en çok kazanacak olan
Laravel (76,31 ms) tam da o beşin içinde.

## "Hepsini derle" doğru cevap değil

Resmî dosyası olmayan framework için akla gelen ilk çözüm şu: Composer zaten
bütün sınıfları biliyor, classmap'i gezip hepsini derle. Ölçüm bunu iki farklı
biçimde çürütüyor.

**Symfony'de konteyner hiç ayağa kalkmıyor.** 4.721 dosyayı yükleme anında
derlemek, env değişkeni çözen sınıflara çarpıyor:

```
NOTICE: PHP message: [critical] Uncaught Exception:
Environment variable not found: "DEFAULT_URI".
```

Preload php-fpm'in master sürecinde koşuyor; orada ölen bir şey servisi hiç
başlatmıyor. Ölçüm bunu `ready: false` diye kaydediyor.

**CodeIgniter'da daha kötü sonuç veriyor.** Resmî dosya 3,13 ms, classmap 5,29
ms. Elle seçilmiş kırk küsur sınıf, körlemesine derlenmiş 479 dosyadan iyi.
Preload paylaşılan belleği dolduruyor ve gereksiz sınıflar yer kaplıyor.

> **Sonuç**
>
> Preload bir ayar değil, bir **bakım işi**. Kazancı framework'ün ne kadar ağır
> olduğuna değil, birinin oturup hangi sınıfların önden derleneceğini seçmiş
> olmasına bağlı. Seçen varsa 14 kat; yoksa ya hiç, ya da kendi yazdığınız ve
> kırılabilen bir dosya.

## Bedel kaybolmuyor, yer değiştiriyor

Preload derleme işini isteğin içinden alıp php-fpm'in açılışına taşıyor. Küçük
preload'larda bu bedel ölçülemiyor; büyük olanda çok net:

| Aday | Derlenen dosya | fpm hazır olma süresi | Fark |
| --- | --- | --- | --- |
| Laravel | 4.721 | 2.755 ms | +2.340 ms |
| Laminas | 1.195 | 352 ms | −7 ms |
| Yii2 | 992 | 352 ms | +13 ms |
| CodeIgniter | 479 | 324 ms | −12 ms |
| Slim | 138 | 359 ms | +28 ms |
| Phalcon | 3 | 362 ms | +43 ms |

Yalnız classmap varyantı; Symfony kırıldığı için listede yok.

Laravel'in classmap preload'ı her ziyaretçiden 62 ms alıp deploy'a 2,3 saniye
yazıyor. Sürekli trafiği olan bir serviste bu iyi bir takas — ilk ziyaretçi bir
kez ödüyor, sonrakiler hiç. Günde on kez deploy eden bir serviste ise takas
tersine dönüyor: yirmi üç saniyelik açılış gecikmesi karşılığında birkaç yüz
ziyaretçinin 62 ms'si.

## Phalcon negatif kontrol oldu

Phalcon'un classmap'inden yalnız **3 dosya** derlendi — sınıfları PHP'de değil C
eklentisinde. Kazanç da en düşük: 1,3×. Bu, ölçümün ne ölçtüğünü doğrulayan
kontrol: preload PHP kaynak derlemesini siliyorsa, derlenecek PHP kaynağı
olmayan adayda etkisiz olmalı. Öyle oldu.

> **Sınır**
>
> "Soğuk" burada **opcache'in boş olması** demek, sayfa önbelleğinin soğuk olması
> değil. İlk kez çalıştırılan bir imajın diskten okunması ayrı bir maliyet ve bu
> ölçüm onu içermiyor; tek atışlık bir denemede Symfony 76,5 ms verdi, üç
> tekrarın medyanı 35,58 ms. Rakamlar tek makinede, tek mimaride (aarch64) ve tek
> PHP sürümünde alındı. `fpm bedeli` penceresi nginx'in kendi açılışını da
> içeriyor — üç varyantta sabit olduğu için farklar anlamlı, mutlak değerler
> değil. Ve `classmap` varyantı kimsenin dağıttığı bir yapılandırma değil; bir
> tavan ölçüsü olarak duruyor.

## Ayak izi kaydına geri dönüş

O kayıt "disk boyutu hiçbir şey öngörmüyor, gerçekten ayrışan tek şey opcache
soğukken ödenen ilk istek" demişti. Bu ölçüm o cümleye bir şart ekliyor:
**opcache soğuk kalmak zorunda değil** — ama kalmaması, framework'ünüzün size
bir preload dosyası verip vermemesine bağlı.
