Ölçüm · 21–23 Ağustos 2026 · English
Aynı API. On dil. Üç ölçek. Otuz uygulama. Hepsi bütün testleri geçti. Sonra tokenleri saydık. Sonra hızı, CPU'yu ve RAM'i ölçtük.
İki önemli sonuç. Uygulama büyüdükçe token farkı daralıyor. Ve token sıralaması, hız sıralamasının neredeyse tam tersi.
Küçük = sade CRUD, 7 rota. Orta = kimlik doğrulama, roller, satır bazlı erişim, ara katman, yapılandırılmış günlük, hata kodları, sayfalama, sıralama, durum makinesi ve kademeli silme eklenir. 16 rota. Büyük = modül ayrımı, ETag eşzamanlılığı, idempotanlık anahtarları, mantıksal silme, denetim kaydı, giden kutusu, kota, toplu yazma, arama, raporlar, metrikler, yorumlar ve kullanıcı yönetimi eklenir. 34 rota.
İlk önce şartname yazıldı. Sonra testler. Kod en son yazıldı. Gerçek bir sunucu çalışıp gerçek HTTP üzerinden bütün testleri geçmeden hiçbir ölçüm sayılmadı. Orta ve büyük ölçek ayrıca günlük denetimini de geçmek zorunda: bu denetim sunucunun stdout çıktısını okur ve her günlük satırını doğrular.
Çubuk = o ölçekteki en ucuz dile göre maliyet. Her dil için üç çubuk: küçük, orta, büyük. Pahalı diller uygulama büyüdükçe belirgin biçimde ucuzluyor.
C, C++ ve Zig; HTTP ayrıştırıcısını, JSON ayrıştırıcısını, JSON yazıcısını ve soket döngüsünü bir kez yazar. Python ve C# bunların tamamını hazır alır. Yani Python çok önde başlar, sonra ek bir kazanç elde etmez. 35. rotanın maliyeti her dilde aynıdır.
En kötü ile en iyi arasındaki fark: 7 rotada 5.05× → 16 rotada 3.43× → 34 rotada 2.80×.
Sonuç: oyuncak bir uygulamada ölçüm yaparsanız C'yi fazla cezalandırırsınız — neredeyse iki kat.
Sıralamak için herhangi bir başlığa tıklayın.
| Dil | küçük | orta | büyük | büyük token | büyük satır |
|---|---|---|---|---|---|
| Python | 1.00× | 1.00× | 1.00× | 10,558 | 1,321 |
| TypeScript | 1.28× | 1.13× | 1.12× | 11,874 | 1,493 |
| C# | 1.12× | 1.08× | 1.15× | 12,180 | 1,360 |
| Java | 1.51× | 1.35× | 1.38× | 14,521 | 1,601 |
| PHP | 1.94× | 1.45× | 1.48× | 15,607 | 1,771 |
| Go | 1.75× | 1.75× | 1.56× | 16,518 | 2,338 |
| Rust | 1.66× | 1.72× | 1.66× | 17,560 | 2,147 |
| Zig | 2.08× | 1.87× | 1.84× | 19,418 | 1,995 |
| C++ | 4.24× | 2.50× | 2.01× | 21,254 | 2,467 |
| C | 5.05× | 3.43× | 2.80× | 29,532 | 3,245 |
Büyük uygulama. 10,000 istek, teker teker. p50 = ortadaki istek. p99 değil p50 kullanın: Windows zamanlayıcı adımı p99'u yanıltıyor. Soğuk başlangıçtan ölçüm aracının kendi tabanı çıkarıldı.
Sıralamak için herhangi bir başlığa tıklayın. Sıralamayı p50 üzerinden yapın:
milisaniyenin altındaki uygulamalar için req/s gürültülüdür. Ayrıntı:
METHODOLOGY.md.
| Dil | p50 ms | req/s | CPU ms/istek | boşta RAM | soğuk başlangıç |
|---|---|---|---|---|---|
| C++ | 0.218 | 2,543 | 0.070 | 5.2 MB | 58 ms |
| C | 0.240 | 2,084 | 0.059 | 4.2 MB | 47 ms |
| Zig | 0.254 | 1,986 | 0.069 | 3.3 MB | 57 ms |
| Go | 0.311 | 1,888 | 0.230 | 8.6 MB | 55 ms |
| Rust | 0.327 | 1,412 | 0.150 | 6.2 MB | 69 ms |
| TypeScript | 0.441 | 1,198 | 0.356 | 67.0 MB | 452 ms |
| C# | 0.444 | 850 | 0.653 | 50.9 MB | 712 ms |
| Java | 0.595 | 760 | 1.613 | 191.0 MB | 5,275 ms |
| Python | 1.621 | 266 | 1.764 | 50.0 MB | 1,012 ms |
| PHP | 8.636 | 62 | 5.097 | 34.5 MB | 166 ms |
C ve C++ en çok tokeni harcıyor — ve hızda birinci ile ikinci oluyor. Python en az tokeni harcıyor — ve hızda 10 dil içinde 9. sırada. İki liste neredeyse birbirinin aynası.
Yani burada tek bir “en iyi dil” yok. Sadece bilerek seçtiğiniz bir denge var. Hiçbir dil iki uçta da iyi değil.
Sıralamak için herhangi bir başlığa tıklayın.
| Dil | token sırası | hız sırası | kayma | Kısa yorum |
|---|---|---|---|---|
| C++ | 9 | 1 | +8 | en hızlı, token'da sondan ikinci |
| C | 10 | 2 | +8 | en az CPU, en hızlı başlangıç, en çok token |
| Zig | 8 | 3 | +5 | en az RAM, 3.3 MB |
| Go | 6 | 4 | +2 | her alanda dengeli, çok satır |
| Rust | 7 | 5 | +2 | hızlı, güvenli, çok token |
| TypeScript | 2 | 6 | −4 | en dengeli, 67 MB yer kaplıyor |
| C# | 3 | 7 | −4 | yoğun kod, orta hız |
| Java | 4 | 8 | −4 | JIT sonradan hızlandırıyor, 5 s başlangıç, 191 MB |
| PHP | 5 | 10 | −5 | sıfır bağımlılık, ama dosya deposu yavaşlatıyor |
| Python | 1 | 9 | −8 | en az token, yavaş |
Kayma = token sırası eksi hız sırası. Artı değer, dilin token maliyetinin ima ettiğinden daha hızlı olduğu anlamına gelir.
PHP'de OPcache kapalıydı. php -S CLI SAPI ile çalışır ve
orada opcache.enable_cli varsayılan olarak kapalıdır. Bu yüzden PHP
her istekte uygulamanın tamamını kaynaktan yeniden derliyordu. Hiçbir gerçek
kurulum böyle çalışmaz. Bunu düzeltmek orta ölçekte PHP'nin p50 değerini neredeyse yarıya
indirdi.
C ve C++ keep-alive kullanmıyordu. İkisi de her yanıtta
Connection: close gönderiyordu, yani her istek için yeni bir TCP el sıkışması.
HTTP/1.1 varsayılanı kalıcı bağlantıdır. Zig de çıplak soketle, çerçeve olmadan yazıldı ve
bunu doğru yapıyor; hatanın bize ait olduğunu bu kanıtladı. Düzeltmeden sonra C küçük
ölçekte 96 → 3,454 req/s, p50
11.59 → 0.166 ms. Düzeltmeden önce C'yi hızda 8. sıraya koymuştuk.
C aslında zirveye yakın.
Doğru keep-alive, C ve C++'a yaklaşık %26 daha fazla token'a mal oldu. Gerçek bir denge: protokole uygun kod daha fazla koddur. Buradaki bütün sayılar düzeltilmiş hâlleridir.
OPcache düzeltmesinden sonra katman katman ölçtük: aynı sunucu, temiz depo, sadece GET. Sonuç bizi şaşırttı.
| Katman | p50 | bu katmanın eklediği |
|---|---|---|
| çıplak PHP, çerçeve yok | 0.874 ms | — |
| + Slim kurulumu, depo yok, iş mantığı yok | 5.113 ms | +4.24 ms |
| + küçük ölçek depomuz ve rotalar | 5.384 ms | +0.27 ms |
| + büyük ölçek depomuz ve rotalar | 6.410 ms | +1.30 ms |
Çıplak PHP 0.874 ms — C# ve Python'u geçiyor. Farkın yaklaşık %94'ü, Slim'in konteyneri, yönlendiricisi ve ara katman yığınının her istekte sıfırdan kurulmasından geliyor. Bu, PHP'nin gerektirdiği paylaşımsız modeldir. Yavaş olan PHP dili değil. Yavaş olan bizim depomuz da değil. Diğer bütün diller yönlendiricisini başlangıçta bir kez kurar ve süreç boyunca saklar.
Go veya Rust'ta çerçeve tabandır; daha azıyla HTTP sunamazsınız. PHP'de çerçeve
bir tercihtir. PHP tasarımı gereği bir istek işleyicisidir;
$_SERVER['REQUEST_URI'] üzerinde çalışan tek bir ön denetleyici sıradan
PHP'dir ve üretimde kullanılır. Sadece Slim'i ölçmek, PHP'yi birçok PHP geliştiricisinin
hiç vermediği bir karar için cezalandırır.
Yani buradaki PHP sıfır bağımlılıklıdır: composer yok, vendor yok, otomatik yükleyici
yok. Sadece public/index.php ve kendi dosyaları. Aynı depo, aynı isimler,
aynı iş mantığı. Aynı 22 / 98 / 139 testi geçiyor.
Çerçeveli sürümü çıkarmadan önce iki yolu da ölçtük. Bu yüzden çerçevenin maliyeti bir tahmin değil, ölçülmüş bir sayıdır:
| 10,000 istek | çerçeve yok | Slim ile | kazanç |
|---|---|---|---|
| küçük ölçek p50 | 1.362 ms | 6.102 ms | 4.5× |
| orta ölçek p50 | 1.452 ms | 6.306 ms | 4.3× |
| büyük ölçek p50 | 8.636 ms | 17.588 ms | 2.0× |
| büyük CPU ms/istek | 5.097 | 9.355 | 1.8× |
| büyük token | 15,607 | 16,238 | 1.04× |
Çerçeve olmadan küçük ölçekte 4.5×, orta ölçekte 4.3×,
büyük ölçekte 2.0× daha hızlı, 5× daha az CPU — ve token maliyeti de daha
düşük. Üstüne composer dosyası olmadığı için sıfır manifest. Yani çerçeve her
istekte yaklaşık 4.2 ms'e mal oldu ve ölçtüğümüz hiçbir şeyi iyileştirmedi. Eski Slim
ölçümleri perf-variance/removed-slim-run*.json içinde saklanıyor, isteyen
kontrol edebilir.
Buradaki PHP sayıları üç koşunun ortancasıdır. Aslında buna pek gerek yoktu: üç koşu küçük ölçekte 1.362, 1.361, 1.376 ms verdi — %1.1 aralığında. PHP, bütün kıyaslamada en tekrarlanabilir uygulamalardan biri. Eski çerçeveli sürüm ise 13.73, 6.07, 6.10 ms arasında salınıyordu, çünkü otomatik yükleyicisi her istekte yaklaşık yüz dosyaya dokunuyordu. Yani oynaklık çerçeveden geliyordu, dilden değil.
Çerçeve olmadan bile PHP büyük ölçekte kötü görünüyordu. Nedenini ölçtük ve suç yine bizdeydi.
| Depo işlemi | küçük depo 501 B | büyük depo 144 KB |
|---|---|---|
| file_get_contents | 0.049 ms | 0.039 ms |
| file_put_contents | 0.327 ms | 0.741 ms |
| json_decode | 0.016 ms | 8.581 ms |
| tam okuma + çözme + kodlama + yazma | 0.641 ms | 11.519 ms |
Sorun hiçbir zaman dosya G/Ç değildi. JSON'du. Büyük ölçek bir denetim kaydı ve giden kutusu biriktiriyor; bizim depomuz ise her istekte tüm veri kümesini yeniden serileştiriyordu. Yani PHP, diğer bütün dillerin RAM'deki bir listeye O(1) ekleme olarak yaptığı iş için istek başına O(toplam durum) ödüyordu. Bu bizim tasarımımız, PHP değil.
Düzeltme: denetim kaydı ve giden kutusu, yalnızca ekleme yapılan JSON Lines
dosyalarına taşındı; /stats ve /metrics O(1) kalsın diye
store.json içine sayaçlar eklendi; boşaltma O(1) kalsın ve
delivered yeniden yazılmak yerine türetilsin diye bir su seviyesi işareti
eklendi.
| Tek bir görevde 2,000 durum değişikliği | p50 başlangıç | p50 bitiş | sapma |
|---|---|---|---|
| düzeltmeden önce | 7.783 ms | 18.402 ms | 2.36× |
| düzeltmeden sonra | 7.523 ms | 7.547 ms | 1.00× |
Düz. Büyük ölçekte p50 25.2 → 8.6 ms'ye düştü. Düzeltmenin maliyeti: +1,216 token, çünkü O(1) kalıcılık O(n)'den daha fazla koddur. Bu, PHP'yi büyük ölçek token sıralamasında 4.'lükten 5.'liğe taşıdı. Dürüst bir denge ve buradaki sayılar bunu içeriyor.
OPcache kapalı. Çerçeve her istekte yeniden kuruluyor. Depo O(n). Üçünden ikisi, katman katman ölçene kadar görünmezdi. Ders: PHP'nin paylaşımsız modeli, durumun bellekte yaşadığını varsayan her kıyaslamayla çatışır ve saf bir aktarım bu bedeli sessizce PHP'ye yazar. Her PHP kıyaslamasını — bunu da — bunu bilerek okuyun.
Depo düzeltmesinden sonra büyük ölçekte PHP, 100 istekte 2.36 ms'den 10,000 istekte 8.64 ms'ye çıkıyor. Kalan artış, depoda canlı alan verisi olarak duran 1,000 mantıksal silinmiş görev satırından geliyor — bu satırları o ölçekteki her dil de tutuyor. Meşru bir maliyet, bu yüzden kalıyor.
Çerçeve olmadan hem daha hızlı hem daha küçük: küçük ölçekte 4.5×, orta ölçekte
4.3×, büyük ölçekte 2.0× daha hızlı p50, 5× daha az CPU ve 16,238
yerine 15,607 token. Çerçeve ayrıca bir composer.json ve bir
vendor/ ağacı ekliyor. Ölçtüğümüz hiçbir şey bununla iyileşmedi, bu yüzden
PHP çerçevesiz ölçülüyor.
Java çalışırken hızlanıyor: p50 1.304 → 0.595 ms. Belirgin biçimde iyileşen tek dil, sapma 0.46×. Ama bedeli 5,275 ms soğuk başlangıç ve 191 MB RAM. Uzun süre açık kalan sunucu için uygun. Sıfıra ölçeklenen kurulum için kötü.
Büyük uygulamada istek başına 0.059 CPU ms. Bu, PHP'den 86×, Java'dan 27× daha az. Üstelik en hızlı soğuk başlangıç: 47 ms.
Boşta 3.3 MB. Java 191 MB kullanıyor — 57× fazlası. Zig bunu sadece standart kütüphaneyle, sıfır bağımlılıkla ve üç ölçeğin hepsinde yapıyor.
C#, küçük ve orta ölçekte satır sayısında Python'u geçiyor — 138'e 134 ve 472'ye 451. Modern C#, eski kurumsal kalıp kod değil.
Token farkı 2.80×. Soğuk başlangıç 112×. CPU 86×. RAM 57×. Hız 40×. Kaynak kod boyutu, burada ölçülen en düz eksen.
409
yanıtı aldı. Gerçek bir sınır ve C'nin oradaki gecikmesini olduğundan biraz daha iyi
gösteriyor.