İçeriğe geç
Muhammet Şafak
en

Research

son güncelleme:

Derin Araştırma ve Ölçüm

Bir iddia kaynağa ya da sayıya dayanmıyorsa varsayımsal bir tercihtir. Bu sayfa araştırmalarımın merkezi: hangi soruyu kovaladım, nasıl araştırdım, ne buldum ve ne kadar güveniyorum.

5
program
10
kayıt
9
ölçüm
3
kaynak

Bulguyu nasıl üretiyorum?

Bir araştırmanın değeri tekrar edilebilir olmasında yatar. Burada paylaştıklarım için kurallarım var; bu kuralların dışına çıkan bir kaydı yayınlamıyorum.

  1. 01

    Künye zorunludur

    Ölçümde: donanım, sürümler ve yapılandırma ortam künyesine yazılır.

    Analizde: okunan her kaynak başlığı, adresi ve erişim tarihiyle künyeye girer.

  2. 02

    Tek örnek yetmez

    Ölçümde: tek çalıştırma ölçüm değildir; tekrar sayısı ve raporlanan değer yazılır.

    Analizde: tek kaynak bulgu değildir; bir iddia en az iki bağımsız kaynakla karşılanır.

  3. 03

    Kanıt bağlanır

    Ölçümde: ham veri indirilebilir bir adrese bağlanır, tekrar komutu verilir.

    Analizde: her kaynağın kendi adresi verilir; alıntı özetlenmez, bağlanır.

  4. 04

    Negatif sonuç da yayınlanır

    Beklentiyi doğrulamayan sonuç da sonuçtur. Yayınlanmayan bulgu, yapılmamış araştırmadır.

Öne çıkan kayıt

Veritabanı & sorgu Ölçüm

Partial index kuyruk tablosunu kırk bir kat küçültüyor — planner onu seçtiği sürece

Milyonlarca ölü satır biriken bir Postgres kuyruk tablosunda partial index ne kazandırıyor, ve planner onu ne zaman seçmiyor?

Bulgu

10 milyon ölü satırda partial index saniyede 11.537 iş çıkarıyor, index'siz tablo 7. Composite index'le hız farkı küçük (%6,9) ama boyut farkı değil: 7,6 MB'a karşı 310,4 MB, ve partial tabloyla birlikte büyümüyor çünkü yalnız 5.000 canlı satırı indeksliyor. Asıl bulgu bunların hiçbiri: planner hazırlanmış bir deyimde generic plana geçtiği anda partial index tamamen devre dışı kalıyor — 11.752 tps 7'ye, 0,68 ms 1,1 saniyeye düşüyor. Bin altı yüz otuz beş kat. Aynı koşulda composite index etkilenmiyor.

11.537 tps
Partial index, 10M ölü satır
7 tps
Aynı tablo, index yokken
7,6 / 310,4 MB
Index boyutu, partial / composite
Yüksek güven Raporu oku
Arayüz performansı Ölçüm

Chart.js'i nasıl import ettiğin, ziyaretçiye kaç kilobayt gönderdiğini belirliyor

`chart.js/auto` ile seçmeli `Chart.register()` arasındaki fark, gerçek bir üretim derlemesinde kaç kilobayt?

Bulgu

Seçmeli register, `chart.js/auto` yerine 9,7 kB gzip tasarruf ettiriyor (67,8 → 58,1 kB, %14,3). Asıl büyük düşüş kütüphanenin kendisinde değil, hiç kullanılmayan controller'ları dışarıda bırakmakta: yalnız çubuk grafiği kaydeden bir sayfa 46,0 kB'a iniyor — auto'nun üçte ikisi.

58,1 kB
Seçmeli register
67,8 kB
chart.js/auto
46,0 kB
Yalnız çubuk
Yüksek güven Raporu oku
Dil & çalışma zamanı Ölçüm

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

`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.

2,50 ms
Symfony, soğuk ilk istek
2 / 7
Resmî preload taşıyan aday
+2.340 ms
Laravel classmap, fpm bedeli
Yüksek güven Raporu oku
Servis & yük Ölçüm

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ı.

25.975 istek/sn
Boş rota, en hızlı
5.966 istek/sn
Boş rota, en yavaş
4,4× → 3,7×
Fark: boş rota → veritabanı
Orta güven Raporu oku

6 araştırma programı

Kayıt rastgele seçilmiyor: her biri bu programlardan birinin sorusunu daraltıyor. Bir programa dokun, liste ona göre süzülsün.

Türe göre süz

Bulgu defteri

Her kaydın sorusu ve çıkan sonucu tek satırda. Ayrıntı için satıra gir.

10 kayıt gösteriliyor — Tüm programlar

  • Servis & yük

    4 metrik

    bugün ölçüldü

    Soru

    PHP ile Go'yu aynı OAuth2 API'de ölçtüm: 10.000 yazmada fark yok, 50.000 okumada var

    Her istekte OAuth2 token'ı doğrulayıp PostgreSQL'e yazan ya da okuyan aynı API, dört çekirdekte PHP-FPM, FrankenPHP worker ve Go ile saniyede 10.000 yazmayı ve 50.000 okumayı kaç CPU'yla karşılıyor?

    Bulgu

    Saniyede 10.000 yazmada üç aday da hedefi beş tekrarın beşinde tutturdu, p99 üçünde de 2,5 ms'yi aşmadı: bu yükte dil bir kapasite kalemi değil. Saniyede 50.000 okumayı dört çekirdekte yalnız Go tutturdu (p99 6,45 ms); PHP-FPM 23.528'de, FrankenPHP 22.859'da kaldı. İstek başına CPU okumada Go'da 64, FrankenPHP'de 117, PHP-FPM'de 168 mikrosaniye. 50.000 okuma için instance hesabı Go'ya 3,4, iki PHP adayına 8,2–8,8 çekirdek yazdırıyor. FrankenPHP'nin CPU tasarrufu kapasiteye dönmüyor: doygunken dört çekirdeğin birini boşta bırakıyor.

    Ölçüm Orta güven
  • Veritabanı & sorgu

    4 metrik

    25 gün önce ölçüldü

    Soru

    Partial index on beş dakikada üç yüz beş kat şişti — ve autovacuum bir kez bile gelmedi

    Sürekli churn altındaki bir kuyruk tablosunda partial index'in küçüklüğü kalıcı mı, ve varsayılan autovacuum ayarları ona yetişiyor mu?

    Bulgu

    Canlı küme beş bin satırda sabit dururken partial index 0,125 MB'dan 38,2 MB'a çıktı — üç yüz beş kat. Küçüklüğü canlı satır sayısından geliyor, şişme hızı iş hacminden, ve ikisi arasında hiçbir bağ yok. Composite index oransal olarak daha az şişti (%42) ama mutlak olarak daha çok (+126 MB) ve şişerken belleğe sığmayı bıraktı: gecikmesi 0,52 ms'den 61 saniyeye çıktı, kuyruğu 126 bine tırmandı. On beş dakikada 1,75 milyon ölü satır birikti ve autovacuum **bir kez bile koşmadı** — varsayılan eşik tablonun tamamına göre ölçekleniyor (50 + 0,2 × 10 milyon ≈ 2 milyon), churn ise küçük canlı kümede oluyor.

    Ölçüm Yüksek güven
  • Dil & çalışma zamanı

    4 metrik

    25 gün önce ölçüldü

    Soru

    Laravel'in preload eğrisi: 123 dosya, 1.912 dosyadan sekiz kat fazla kazandırıyor

    Laravel için elle seçilmiş bir preload nereye kadar iner, ve her dilim ne kadar açılış bedeline mal olur?

    Bulgu

    Eğri hacimle orantılı değil. İlk 1.592 dosya (Laravel çekirdeği) 30 ms kazandırıyor ve açılışa 1,2 saniye ekliyor. Sonraki 1.094 Symfony dosyası 9,5 ms kazandırıyor, bedava. Ondan sonraki **123 dosya** (psr, carbon) 15,7 ms kazandırıyor — kendinden önceki 1.094 dosyadan fazla. Ve son 1.912 dosya yalnız 1,8 ms kazandırıp açılışa 1,2 saniye daha yazıyor. Yani önceki kaydın tavan olarak ölçtüğü "hepsini derle", eğrinin başlangıç noktası dışındaki en kötü fiyat/performans bölgesi: 2.809 dosyada durmak 12,77 ms ve 1.514 ms açılış verirken, 4.721 dosya 10,96 ms için 2.691 ms istiyor.

    Ölçüm Yüksek güven
  • Veritabanı & sorgu

    4 metrik

    25 gün önce ölçüldü

    Soru

    Partial index kuyruk tablosunu kırk bir kat küçültüyor — planner onu seçtiği sürece

    Milyonlarca ölü satır biriken bir Postgres kuyruk tablosunda partial index ne kazandırıyor, ve planner onu ne zaman seçmiyor?

    Bulgu

    10 milyon ölü satırda partial index saniyede 11.537 iş çıkarıyor, index'siz tablo 7. Composite index'le hız farkı küçük (%6,9) ama boyut farkı değil: 7,6 MB'a karşı 310,4 MB, ve partial tabloyla birlikte büyümüyor çünkü yalnız 5.000 canlı satırı indeksliyor. Asıl bulgu bunların hiçbiri: planner hazırlanmış bir deyimde generic plana geçtiği anda partial index tamamen devre dışı kalıyor — 11.752 tps 7'ye, 0,68 ms 1,1 saniyeye düşüyor. Bin altı yüz otuz beş kat. Aynı koşulda composite index etkilenmiyor.

    Ölçüm Yüksek güven
  • Veritabanı & sorgu

    4 metrik

    25 gün önce ölçüldü

    Soru

    Postgres partial index'i generic plana çevirmedi: kırk çalıştırma, kırk custom plan

    Hazırlanmış bir deyimde Postgres partial index'li sorguyu kendiliğinden generic plana çeviriyor mu — yoksa bin altı yüz otuz beş katlık uçuruma ancak elle mi düşülüyor?

    Bulgu

    Postgres geçişi reddediyor. Partial index'te kırk çalıştırmanın kırkı da custom plan — sayaç 40/0. Reddetmesinin sebebi tam olarak felaketin kendisi: generic plan partial index'i kullanamaz, bu yüzden tahmini maliyeti yüksek çıkar ve planner onu seçmez. Composite index ise ders kitabındaki gibi altıncı çalıştırmada geçiyor (5/35) ve hiçbir şey kaybetmiyor. Yani bin altı yüz otuz beş katlık uçurum gerçek ama çitli: ona düşmek için `plan_cache_mode = force_generic_plan` yazmak gerekiyor.

    Ölçüm Yüksek güven
  • Arayüz performansı

    4 metrik

    28 gün önce ölçüldü

    Soru

    Chart.js'i nasıl import ettiğin, ziyaretçiye kaç kilobayt gönderdiğini belirliyor

    `chart.js/auto` ile seçmeli `Chart.register()` arasındaki fark, gerçek bir üretim derlemesinde kaç kilobayt?

    Bulgu

    Seçmeli register, `chart.js/auto` yerine 9,7 kB gzip tasarruf ettiriyor (67,8 → 58,1 kB, %14,3). Asıl büyük düşüş kütüphanenin kendisinde değil, hiç kullanılmayan controller'ları dışarıda bırakmakta: yalnız çubuk grafiği kaydeden bir sayfa 46,0 kB'a iniyor — auto'nun üçte ikisi.

    Ölçüm Yüksek güven
  • Dil & çalışma zamanı

    4 metrik

    25 gün önce ölçüldü

    Soru

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

    `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.

    Ölçüm Yüksek güven
  • Dil & çalışma zamanı

    4 metrik · 3 kaynak

    25 gün önce doğrulandı

    Soru

    PHP ekosistemi yeni sürümü beklemiyor — ama desteklediğini de söylemiyor

    Bir PHP sürümü çıktıktan sonra en çok kurulan 500 Composer paketi onu desteklediğini ne zaman beyan ediyor, ve o beyan ne kadar bilgi taşıyor?

    Bulgu

    Kurulumların %43,5'i üst sınırı hiç yazmayan bir kısıtla geliyor — `symfony/console` bugün `>=8.4.1` diyor, yani PHP 12'yi de desteklediğini iddia ediyor. Üst sınır yazan 280 paketin 247'si taahhüdünü sürüm daha doğmadan vermiş: `guzzlehttp/guzzle` 8.4'ü Ekim 2020'de, dört yıl önceden kapsamış. Geriye gerçekten bekleyen 33 paket kalıyor, medyanları 325 gün. Ham sayılar sürümden sürüme düşüp 'ekosistem hızlanıyor' diye okunuyor; eşit gözlem penceresinde bakınca trend tersine dönüyor (238 → 215 → 325 gün).

    Tarama Yüksek güven
  • Araç karşılaştırması

    4 metrik

    27 gün önce ölçüldü

    Soru

    Bir PHP framework'ünü kurmanın sabit maliyeti: disk boyutu hiçbir şey söylemiyor

    Yedi PHP framework'ü kurulduğunda diskte kaç megabayt, istek başına kaç dosya ve ilk istekte kaç milisaniye tutuyor — ve bu sayılardan hangisi gerçekten yük altındaki hızı öngörüyor?

    Bulgu

    Disk boyutu hiçbir şey öngörmüyor: Yii2 en büyük vendor'a sahip (34,1 MB) ama istek başına yalnız 62 dosya yüklüyor — sahanın en azlarından. İstek başına dosya sayısı da öngörmüyor: CodeIgniter 96 dosya yükleyip 6.431 istek/sn veriyor, Symfony 224 dosya yükleyip 13.067 veriyor. Gerçekten ayrışan tek şey opcache soğukken ödenen ilk istek: Phalcon 2,2 ms, Laravel 72,2 ms — otuz üç kat. Bu, her deploy'dan sonra ilk ziyaretçinin ödediği derleme faturasıdır ve framework başına birkaç kilobayt değil, onlarca milisaniye tutuyor.

    Ölçüm Yüksek güven
  • Servis & yük

    4 metrik

    27 gün önce ölçüldü

    Soru

    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ı.

    Ölçüm Orta güven

Araştırılmasını istediğin bir şey mi var

Merak ettiğin bir soru ya da karşılaştırma varsa yaz — sıradaki kayıt o olabilir.

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi