# Yedi PHP framework'ü aynı yükte ölçtüm: fark, istek gerçek iş yaptıkça küçülüyor

> Yedi framework, tek PHP derlemesi, tek sunucu yığını ve elli rotalık ortak bir sözleşme. Yedisi de son kararlı sürümünde, izole konteynerlerde ve sırası her turda karıştırılarak ölçüldü.

- Tür: Ölçüm
- Soru: Aynı donanımda, aynı PHP sürümünde ve aynı yedi rotayla, Laravel, Symfony, CodeIgniter, Yii2, Phalcon, Laminas ve Slim saniyede kaç isteği ne gecikmeyle karşılıyor?
- Bulgu: Boş bir rotada en hızlı ile en yavaş arasında 4,4 kat var (Slim 25.975, Laravel 5.966 istek/sn). Ama istek gerçek iş yapmaya başlayınca fark kapanıyor: veritabanından tek satır çeken bir istekte 3,7 kata, yirmi satır çekende 3,5 kata iniyor. Phalcon boş rotada üçüncüyken veritabanı isteğinde beşinciye düşüyor — C eklentisi olmak, sorgu beklerken bir işe yaramıyor. Asıl pahalı olan şey framework seçimi değil: Laravel'in kendi varsayılan web middleware grubu, aynı yanıtı 5.858'den 2.176 istek/sn'ye düşürüyor — yani tek bir varsayılan, framework'ler arasındaki farkın çoğundan daha pahalı.
- Yöntem: Yedi aday tek bir PHP 8.4.24 derlemesinde, birebir aynı opcache/php.ini/php-fpm havuzunda (pm=static, 8 worker) ve tek bir nginx server bloğunda koştu. Her aday kendi resmî iskeletinde, kendi dokümante ettiği production kurulumuyla (route/config/view cache, APP_ENV=prod, YII_DEBUG=false, Volt önderlenmiş) ve aynı composer bayraklarıyla kuruldu. Yedisi de tam elli rota kaydediyor; parametreli rota her zaman 47. sırada. Ölçüm sırasında yalnız tek bir aday koşuyor; php-fpm 0-3, nginx 4-5, MySQL 6-7 ve yük üreteci 8-11 çekirdeklerinde, ayrık. Her senaryo 64 bağlantıyla 15 saniye, 9 tekrar; adayların sırası her turda karıştırılıyor. Her ölçümün önünde ve arkasında, PHP'ye hiç uğramayan sabit bir nginx referansı örneklenerek o anda makinenin verdiği kapasite kaydediliyor. Raporlanan değer tekrarların en iyisidir: makine sakinleştirilemediği için girişim throughput'u yalnız aşağı çekebilir, donanım tavanının üstüne çıkaramaz. Toplam 546 yük ölçümü, 150 host örneklemesi, sıfır non-200 yanıt.
- Ölçüm tarihi: 2026-08-20
- Güven: Orta güven
- Program: Servis & yük
- Ortam: PHP 8.4.24 NTS · opcache açık · JIT kapalı · Sunucu nginx 1.29.1 + php-fpm · pm=static · 8 worker · Veritabanı MySQL 8.4.11 · 10.000 satır · kalıcı bağlantı · Yük üreteci oha 1.15.0 · 64 bağlantı · 15 sn · Donanım Apple M4 Pro · 12 çekirdek · 24 GB · macOS 26.6.1 · Sanallaştırma Docker Desktop 29.7.2 · 12 vCPU / 7,75 GB · aarch64 · Çekirdek ayrımı fpm 0-3 · nginx 4-5 · MySQL 6-7 · yük 8-11 · Tekrar 9 (+6 takviye) · en iyi koşu raporlanır
- Teknolojiler: Laravel, Symfony, CodeIgniter, Yii2, Phalcon, Laminas, Slim, PHP, Docker, nginx, MySQL
- Ham veri: https://github.com/muhammetsafak/php-framework-bench/tree/main/results/2026-08-20
- Yayın: 2026-08-20
- Kaynak: https://www.muhammetsafak.com.tr/research/php-framework-yuk-testi/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
PHP framework karşılaştırması, Türkçe internette çoğunlukla yöntemsiz yapılıyor:
bir sayı veriliyor, hangi sürümde, hangi donanımda, kaç tekrarla ölçüldüğü
yazılmıyor. Bu kaydın katkısı sıralama değil — sıralamanın **yeniden
türetilebilir** olması. Aşağıdaki her rakam
[bench/run.sh](https://github.com/muhammetsafak/php-framework-bench)
çıktısından geliyor ve ham koşuların hepsi depoda duruyor.

## Ne ölçtüm

Yedi aday da son kararlı sürümünde, kendi resmî iskeletinde ve kendi dokümante
ettiği production kurulumunda koştu. Değişken tek bir şey: framework.

| Aday | Sürüm | Veri katmanı | Şablon |
| --- | --- | --- | --- |
| Slim | 4.15.2 | yok — ham PDO | yok — slim/php-view |
| Yii2 | 2.0.55 | ActiveRecord | Yii View |
| Phalcon | 5.19.0 | Phalcon Model | Volt |
| Symfony | 8.1.4 | Doctrine ORM | Twig |
| Laminas | 3.8.0 | laminas-db TableGateway | laminas-view |
| CodeIgniter | 4.7.4 | CI Model | CI View |
| Laravel | 13.26.1 | Eloquent | Blade |

Slim'in kendi veri katmanı ve şablon motoru yok; o iki senaryoda diğerlerinden daha az iş yapıyor. Sonucu okurken bu satır akılda tutulmalı.

Yedisi de **tam elli rota** kaydediyor ve parametreli rota her zaman 47. sırada
duruyor; böylece rota çözümü tek kayıtlı bir tabloda değil, gerçekçi bir tabloda
ölçülüyor. Senaryolar: düz metin, JSON, parametreli rota, beş katmanlı
middleware zinciri, yüz satırlık şablon (veritabanı yok), birincil anahtarla tek
satır ve yirmi satırlık liste.

## Sayı ne söylüyor

**Saniyede karşılanan istek, üç senaryoda**

Boş rotadan veritabanına inildikçe sütunlar birbirine yaklaşıyor: framework'ün kendi maliyeti, istek gerçek iş yaptığında baskın gider olmaktan çıkıyor.

Kaynak: 9 tekrarın en iyisi, 64 bağlantı, 15 sn — bench/run.sh çıktısı

|  | Slim | Yii2 | Phalcon | Symfony | Laminas | CodeIgniter | Laravel |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Boş rota | 25975 | 19834 | 15021 | 13067 | 8349 | 6431 | 5966 |
| Şablon (100 satır) | 22780 | 16995 | 10563 | 9355 | 7419 | 5557 | 5290 |
| Veritabanı (tek satır) | 14443 | 9366 | 5222 | 6972 | 5421 | 4527 | 3887 |

En çarpıcı hareket **Phalcon'da**. Boş rotada üçüncü (15.021), şablonda yine
üçüncü, ama veritabanı isteğinde **beşinciye** düşüyor (5.222) ve Symfony'nin
altında kalıyor. Yirmi satırlık listede daha da geriye, altıncılığa iniyor
(2.040) — Laminas ve CodeIgniter'ın gerisinde. Framework'ün C ile yazılmış
olması, süreç MySQL'den yanıt beklerken hiçbir şey kazandırmıyor; kazandırdığı
yer, PHP'nin kendi kodu çalıştırdığı yer.

| Aday | Boş rota | JSON | Rota (47/50) | Middleware | Şablon | DB tek satır | DB 20 satır |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Slim | 25.975 | 25.609 | 24.774 | 24.020 | 22.780 | 14.443 | 4.551 |
| Yii2 | 19.834 | 18.731 | 18.775 | 18.877 | 16.995 | 9.366 | 3.245 |
| Phalcon | 15.021 | 15.161 | 15.061 | 14.906 | 10.563 | 5.222 | 2.040 |
| Symfony | 13.067 | 12.714 | 12.187 | 12.964 | 9.355 | 6.972 | 3.060 |
| Laminas | 8.349 | 8.114 | 8.127 | 8.036 | 7.419 | 5.421 | 2.874 |
| CodeIgniter | 6.431 | 6.233 | 5.960 | 6.037 | 5.557 | 4.527 | 2.494 |
| Laravel | 5.966 | 5.848 | 5.603 | 5.704 | 5.290 | 3.887 | 1.293 |

İstek/saniye, 9 tekrarın en iyisi. Sıralama boş rotadaki hıza göre.

Farkın nasıl kapandığı tek bir satırda görünüyor: en hızlı adayın en yavaşa
oranı boş rotada **4,4×**, tek satırlık veritabanı isteğinde **3,7×**, yirmi
satırlıkta **3,5×**. Phalcon'un Laravel'e oranı ise 2,5×'ten 1,3×'e düşüyor.

## Gecikme

**JSON isteğinde gecikme yüzdelikleri**

Yedisi de p99'da milisaltı: bu yükte hiçbiri kullanıcıya yavaş gelmiyor. Fark, aynı donanımdan kaç kullanıcı geçirebildiklerinde.

Kaynak: En iyi throughput'u veren tekrarın kendisinden, 64 bağlantı

|  | Slim | Yii2 | Phalcon | Symfony | Laminas | CodeIgniter | Laravel |
| --- | --- | --- | --- | --- | --- | --- | --- |
| p50 | 0.25 ms | 0.35 ms | 0.46 ms | 0.58 ms | 0.88 ms | 1.16 ms | 0.75 ms |
| p95 | 0.43 ms | 0.59 ms | 0.73 ms | 0.89 ms | 1.52 ms | 1.84 ms | 1.97 ms |
| p99 | 0.53 ms | 0.73 ms | 0.94 ms | 0.96 ms | 2.23 ms | 1.98 ms | 2.59 ms |

Laravel'in p50'si (0,75 ms) Laminas ve CodeIgniter'dan **daha iyi**, ama p99'u
(2,59 ms) en kötüsü. Yani Laravel tipik isteği hızlı bitiriyor, kuyruğun ucunu
ise iyi yönetemiyor.

## Tartışılan şeyler ucuz, varsayılanlar pahalı

Elli rotalık tabloda parametreli rota çözmek, boş rotaya göre adaylara **%0-7**
arasında bir bedele mal oluyor. Beş katmanlı middleware zinciri **%1-8**. Yani
geliştiricilerin karşılaştırırken en çok konuştuğu iki şey, ölçüldüğünde tek
haneli yüzdeler.

Sonra Laravel'in kutudan çıkan varsayılanına bakıyorsunuz:

| Laravel rotası | İstek/sn | p50 | p99 |
| --- | --- | --- | --- |
| Middleware grubu yok | 5.858 | 1,32 ms | 2,88 ms |
| Varsayılan web grubu | 2.176 | 1,73 ms | 71,89 ms |

Aynı JSON yanıtı, aynı konteyner, aynı koşu. Tek fark rotanın web grubunun arkasında olması. p99 yirmi beş katına çıkıyor.

Bu ölçüm **`file` session sürücüsüyle** alındı. Laravel'in kutudan çıkan
varsayılanı `database` — yani her istekte bir okuma ve bir yazma daha. Rakam
oradan daha da kötüye gider.

> **Sonuç**
>
> Sonuç şu: framework seçiminiz size 4 kata kadar fark açabilir, ama tek bir
> varsayılan middleware grubu %63 götürebiliyor. Karşılaştırma tablosuna bakmadan
> önce kendi rotanızın arkasında ne olduğuna bakın.

## Doygunluk: tavan sekiz worker

Eşzamanlı bağlantı sayısını 8'den 256'ya çıkardım. Yedisinde de throughput ve
p99 **düz kaldı**.

| Bağlantı | Slim | Yii2 | Phalcon | Symfony | Laminas | CodeIgniter | Laravel |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 8 | 25.812 | 19.242 | 14.894 | 12.817 | 8.149 | 6.193 | 5.909 |
| 32 | 25.785 | 19.018 | 15.053 | 12.811 | 7.828 | 6.259 | 4.774 |
| 64 | 26.234 | 18.964 | 14.802 | 9.324 | 8.114 | 6.276 | 5.890 |
| 128 | 25.842 | 19.251 | 14.783 | 11.795 | 8.044 | 6.067 | 6.016 |
| 256 | 25.802 | 19.808 | 15.109 | 12.129 | 8.075 | 6.140 | 5.901 |

Sekiz php-fpm worker, dört çekirdek. Tavan sekiz bağlantıda zaten dolmuş; sonrası nginx'te kuyruğa giriyor. Bu tablo tavanı sınırlıyor, doyma eğrisi çizmiyor.

## Nasıl ölçtüğüm — ve iki kez baştan başladığım

Bu ölçüm üç kez koşuldu. İlk ikisi **iptal edildi** ve ikisi de gerçek bir kusur
buldu; ikisi de depoda gerekçesiyle duruyor.

**Birinci iptal — makine sakin değildi.** Slim `/json` bir turda 15.260, ertesi
turda 2.107 istek/sn verdi; **p50 ikisinde de 0,23 ms**. İstek başına maliyet
aynı, istek sayısı yedide bir: uygulama yavaşlamamış, koşu CPU alamamıştı. Host
bir dizüstü ve üstünde pencere sunucusu, terminal ve editör çalışıyor; cpuset
konteyneri VM'in *içinde* izole eder, VM'i macOS'ten izole etmez.

Bunun düzeltmesi ortalamayı almak değil. Girişim throughput'u yalnız **aşağı**
çekebilir — bir koşu gürültülü komşu yüzünden yavaşlayabilir, ama donanımın izin
verdiğinden hızlı olamaz. O yüzden raporlanan değer tekrarların **en iyisi**,
yanında medyanı ve yayılımıyla. Ayrıca PHP'ye hiç uğramayan sabit bir nginx
referansı her bloğun önünde ve arkasında örnekleniyor: 150 örneklemede en kötüsü
en iyinin %84'ü.

**İkinci iptal — port tükenmesi.** Veritabanı senaryolarında isteklerin yarısı
500 dönüyordu: `SQLSTATE[HY000] [2002] Cannot assign requested address`.
php-fpm her istekte MySQL'e yeni bir TCP bağlantısı açıyor ve konteyner saniyede
birkaç bin istekte ephemeral port'ları tüketiyor. Tek istekle yapılan ön kontrol
bunu yakalayamaz. Yedisinde de kalıcı bağlantıya geçildi (`PDO::ATTR_PERSISTENT`,
CodeIgniter'da `pConnect`) — php-fpm için dokümante edilmiş production ayarı.
Etkisi büyük: Slim'in `/db` sonucu 3.594'ten 14.074'e çıktı. Yani önceki ölçüm
veri katmanını değil port çalkantısını ölçüyormuş.

> **Sınır**
>
> Üç sınır açıkça duruyor. **Bir:** host sakinleştirilemedi ve yavaş rejim ~4-8k
> istek/sn'de tavan yapıyor, yani yalnız hızlı adayları kırpıyor — Laravel 9
> tekrarın 9'unda temizken Slim 3'ünde temiz. Bu yanlılık tek yönlü: hızlı adaylar
> olsa olsa **eksik** raporlanır. **İki:** oha her koşuda deadline'da kesilen 64
> bağlantıyı istek sayıyor, bu yüzden `mean` ve `max` kirli — kanıtı aritmetik:
> `max × istek/sn` yedi adayda ve üç senaryoda 59-65 milyon arasında çıkıyor, yani
> `max` yalnız throughput'un fonksiyonu. Bu iki değer ham veride duruyor ama
> raporlanmıyor; yüzdelikler etkilenmiyor. **Üç:** rakamlar bir Docker Desktop
> sanal makinesinden, Apple Silicon üzerinde. Mutlak değerler bare-metal üretimi
> temsil etmez; adaylar arası karşılaştırma geçerlidir, çünkü hepsi aynı VM'i,
> aynı çekirdekleri ve aynı koşuyu paylaştı.

## Atlanmayan bulgular

Ölçüm boyunca çıkan ve tabloya sığmayan her şey:

1. **Yedi framework'ün buluştuğu tek PHP sürümü var: 8.4.** Symfony 8.1 en az
   `8.4.1` istiyor, `laminas/laminas-mvc` 3.8 tavanı `~8.4.0`. Pencere tam bir
   minor sürüm geniş.
2. **Phalcon ile Symfony aynı PHP sürecinde çalışmıyor.** Phalcon `ext-psr`
   istiyor; o eklenti yüklüyken Symfony fatal veriyor:
   `Declaration of Symfony\Component\Cache\CacheItem::expiresAt(?DateTimeInterface $expiration): static must be compatible with PsrExt\Cache\CacheItemInterface::expiresAt($expiration)`.
   C eklentisi PSR arayüzlerini, userland paketlerinin kullandığı parametre
   tipleri olmadan tanımlıyor. "Tek imaj, tek eklenti seti" planı bu yüzden tam
   bir yerde çatallandı: Phalcon kendi runtime imajında koşuyor, geri kalan altısı
   ortak imajda.
3. **CodeIgniter 4'ün PDO sürücüsü yok** — MySQL desteği yalnız MySQLi. Eklenti
   seti aynı kalsın diye `ext-mysqli` yedisine birden kuruldu; diğer altısı
   kullanmıyor.
4. **Laminas'ın resmî iskeleti PHP 8.4 için yayınlanmamış.**
   `laminas/laminas-mvc-skeleton` 2.4.0 hâlâ `~8.1.0 || ~8.2.0 || ~8.3.0` diyor;
   kurulum `--ignore-platform-req=php` olmadan reddediliyor. Açtığı bileşen
   (`laminas/laminas-mvc` 3.8.0) `~8.4.0`'ı kabul ediyor.
5. **Yii2 hâlâ 2.0.x.** Yii3'ün kararlı sürümü yok, yani "son kararlı Yii",
   mimarisi diğerlerinin güncel sürümlerinden eski olan bir hat.
6. **Middleware yedisinde aynı kavram değil.** CodeIgniter filtreleri ve Yii2
   action filter'ları rotaya bağlı, diğer senaryolara hiçbir şeye mal olmuyor.
   Symfony, Laminas ve Phalcon'da rota bazlı bir pipeline yok; dokümante edilmiş
   karşılık global bir event listener, yani beş katman o uygulamalarda **her**
   istekte yoklanıp erken dönüyor. Bu onların mimarisi, buraya uydurulmuş bir
   handikap değil.
7. **Slim iki senaryoda daha az iş yapıyor.** Kendi veri katmanı yok (`/db` ham
   PDO üstünde), kendi şablon motoru yok (`slim/php-view`). Birincilik bu iki
   satırda bu bağlamla okunmalı.
8. **Bir hücre kendi kendisiyle çelişti ve takviye edildi.** Slim'in `/route`
   sonucu 9 tekrarda 6.778 istek/sn çıkmıştı — sahanın en düşük p50'si (0,23 ms)
   ile, kendi boş rotasının %26'sı. Dokuz tekrarın hiçbiri kırpılmamış pencereye
   denk gelmemişti. Önceden sabitlenmiş iki kural (temiz tekrar sayısı ≤2, veya
   throughput'un `8/p50`'nin yarısının altında kalması) altı hücreyi işaretledi;
   hepsi Slim ve Yii2, yani sahanın en hızlı ikilisi — yanlılığın öngörülen
   yönü. Altısına altışar tekrar eklendi, Slim `/route` 24.774'e oturdu ve hiçbir
   hücre işaretli kalmadı.
9. **Sıfır non-200.** 546 yük ölçümünün tamamı, kalıcı bağlantı düzeltmesinden
   sonra, %100 HTTP 200 döndü.
10. **JIT kapalı.** Yedisinden hiçbiri opcache JIT'i production adımı olarak
    dokümante etmiyor ve açmak ikinci bir değişken eklerdi. Açık JIT ile sonuç
    farklı olabilir; bu ayrı bir ölçüm.
11. **Worker mode ölçülmedi.** FrankenPHP/Octane gibi kalıcı süreç modelleri
    yedisinde de resmî olarak desteklenmiyor; klasik php-fpm hepsinin eşit
    zeminidir. Worker mode ayrı bir kayıt konusudur.
