Yedi PHP framework'ü aynı yükte ölçtüm: fark, istek gerçek iş yaptıkça küçülüyor
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ı.
- Boş rota, en hızlı
- 25.975 istek/sn
- Boş rota, en yavaş
- 5.966 istek/sn
- Fark: boş rota → veritabanı
- 4,4× → 3,7×
- Laravel web grubu
- −%63
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
- Yayın
2 gün önce ölçüldü
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
Tekrarlamak için
./bench/build.sh && STAMP=$(date -u +%F) ./bench/run.sh --all 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 çı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 |
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.
- Boş rota
- Şablon (100 satır)
- Veritabanı (tek satır)
Kaynak: 9 tekrarın en iyisi, 64 bağlantı, 15 sn — bench/run.sh çıktısı
Veri tablosu
| Seri | Slim | Yii2 | Phalcon | Symfony | Laminas | CodeIgniter | Laravel |
|---|---|---|---|---|---|---|---|
| Boş rota | 25.975 | 19.834 | 15.021 | 13.067 | 8.349 | 6.431 | 5.966 |
| Şablon (100 satır) | 22.780 | 16.995 | 10.563 | 9.355 | 7.419 | 5.557 | 5.290 |
| Veritabanı (tek satır) | 14.443 | 9.366 | 5.222 | 6.972 | 5.421 | 4.527 | 3.887 |
Grafik tarayıcıda çizilir; aşağıdaki tablo aynı veriyi taşır.
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 |
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.
- p50
- p95
- p99
ms düşük olan iyi Kaynak: En iyi throughput'u veren tekrarın kendisinden, 64 bağlantı
Veri tablosu
| Seri | 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 |
Grafik tarayıcıda çizilir; aşağıdaki tablo aynı veriyi taşır.
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 session + cookie şifreleme + CSRF | 2.176 | 1,73 ms | 71,89 ms |
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.
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 |
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ş.
Atlanmayan bulgular
Ölçüm boyunca çıkan ve tabloya sığmayan her şey:
- Yedi framework’ün buluştuğu tek PHP sürümü var: 8.4. Symfony 8.1 en az
8.4.1istiyor,laminas/laminas-mvc3.8 tavanı~8.4.0. Pencere tam bir minor sürüm geniş. - Phalcon ile Symfony aynı PHP sürecinde çalışmıyor. Phalcon
ext-psristiyor; 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. - CodeIgniter 4’ün PDO sürücüsü yok — MySQL desteği yalnız MySQLi. Eklenti
seti aynı kalsın diye
ext-mysqliyedisine birden kuruldu; diğer altısı kullanmıyor. - Laminas’ın resmî iskeleti PHP 8.4 için yayınlanmamış.
laminas/laminas-mvc-skeleton2.4.0 hâlâ~8.1.0 || ~8.2.0 || ~8.3.0diyor; kurulum--ignore-platform-req=phpolmadan reddediliyor. Açtığı bileşen (laminas/laminas-mvc3.8.0)~8.4.0’ı kabul ediyor. - 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.
- 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.
- Slim iki senaryoda daha az iş yapıyor. Kendi veri katmanı yok (
/dbham PDO üstünde), kendi şablon motoru yok (slim/php-view). Birincilik bu iki satırda bu bağlamla okunmalı. - Bir hücre kendi kendisiyle çelişti ve takviye edildi. Slim’in
/routesonucu 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’un8/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/route24.774’e oturdu ve hiçbir hücre işaretli kalmadı. - 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ü.
- 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.
- 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.
İlgili yazılar
2026'da PHP ile uygulama geliştirmek: ekosistemin hali
PHP'nin 2026'daki gerçek durumu: dil olgunluğu, ekosistem sağlığı ve 'öldü' söyleminin neden hâlâ yanlış olduğu.
Laravel'le on iki yıl: bir framework'le büyümek
2014'ten 2026'ya Laravel ile geçirilen on iki yıl: bir araçla birlikte olgunlaşmanın, onu aşmanın ve yeniden benimsemenin hikâyesi.
PHP Öldü mü? 2026 Tablosu, Veriyle
18 yıllık bir PHP geliştiricisinin gözünden — W3Techs, Stack Overflow, JetBrains ve Packagist verileriyle PHP'nin 2026 fotoğrafı, ve dilin görmezden gelinen zayıflıkları.