Laravel üzerinde istekleri engelleyici işçiler yerine coroutine’ler ile ele alarak hızınızı ne kadar artırabilirsiniz? TrueAsync‘ın üç farklı Laravel Octane yapılandırması ile karşılaştırmalarını yaptık.
Performans Testi
Performans Testi
Ortam
Ortam
- OS: WSL2 (Linux 5.15), 16 çekirdek, 7.8 GB RAM
- DB: PostgreSQL 16 (
max_connections=500) - Yük aracı:
k6,constant-arrival-rate, 1,000 req/s, 30 saniye boyunca
| Parametre | TrueAsync FrankenPHP | Octane Swoole (NTS) | Octane Swoole (ZTS) | Octane FrankenPHP |
|---|---|---|---|---|
| PHP | 8.6.0-dev (ZTS) | 8.5.4 (NTS) | 8.5.4 (ZTS) | 8.5.4 (NTS) |
| Sunucu | FrankenPHP (true-async fork) | Swoole 6.2.0 | Swoole 6.2.0 | FrankenPHP (official) |
| Laravel | 13.2.0 | 13.2.0 | 13.2.0 | 13.2.0 |
| Model | Coroutines (libuv) | Processes (fork) | Threads (ZTS) | Processes (fork) |
Not: Swoole, burada coroutine modu olmadan çalışmaktadır çünkü Laravel buna uyumlu değildir. Saf bir testte, Swoole, FrankenPHP + TrueAsync‘dan biraz daha iyi değerler göstermektedir. Her iki sunucu da sentetik yüklerde ~10,000 req/s değerine ulaşmaktadır.
Tüm benchmark deposu: github.com/YanGusik/ta_benchmark
Yük
Yük
/bench uç noktası, 10 ardışık SQL sorgusu gerçekleştirir: kullanıcı sorgulama, gönderi listeleme, INSERT bir görünüm kaydı, UPDATE bir sayacı, toplama işlemleri, TOP-N seçimler. Veritabanı: 100 kullanıcı, 1,000 gönderi, büyüyen post_views tablosu.
Bu, sentetik bir “Hello World” değil, gerçekçi bir yük türüdür.
Sonuçlar
Sonuçlar
Üretkenlik (req/s)
Üretkenlik (req/s)
| İşçiler | TrueAsync | Swoole NTS | Swoole ZTS | FrankenPHP Octane |
|---|---|---|---|---|
| 4 | 989 | 183 | 185 | 189 |
| 8 | 993 | 342 | 341 | 346 |
| 12 | 990 | 483 | 476 | 489 |
| 16 | 987 | 599 | 601 | 556 |
16 işçi ile, TrueAsync 987 req/s yönetmektedir. En iyi Octane sonucu Swoole ZTS ile 601 req/s’dir, bu durumda %64 daha az performans göstermektedir.
Engelleyici sunuculara 16 işçi verdik, bu cömertlik. Ancak TrueAsync bunlara ihtiyaç duymuyor. Dört işçi 989 req/s yönetiyor, bu da onaltısına eşdeğerdir. Coroutine’ler her PDO::query() üzerinde beklediği için, bir işçi onlarla birlikte çalışarak pek çok isteği yönetebiliyor. Bir coroutine PostgreSQL‘yi beklerken, diğerleri çalışmaya devam eder.
Medyan Gecikme (P50)
Medyan Gecikme (P50)
| İşçiler | TrueAsync | Swoole NTS | Swoole ZTS | FrankenPHP Octane |
|---|---|---|---|---|
| 4 | 28 ms | 5,440 ms | 5,320 ms | 5,240 ms |
| 8 | 27 ms | 2,870 ms | 2,900 ms | 2,800 ms |
| 12 | 28 ms | 2,040 ms | 2,050 ms | 1,990 ms |
| 16 | 29 ms | 1,640 ms | 1,660 ms | 1,780 ms |
29 ms ile 1,640 ms arasında büyük bir fark var. Bu yükseklik nereden geliyor?
| Aşama | TrueAsync (4w) | Swoole (4w) |
|---|---|---|
| PHP yürütme | ~5 ms | ~5 ms |
| SQL I/O bekleme (10 sorgu) | ~23 ms | ~23 ms |
| Kuyruk bekleme | ~0 ms | ~5,400 ms |
| Toplam | ~28 ms | ~5,440 ms |
PHP ve SQL, aynı hızda çalışıyor. Farkın tamamı kuyruk bekleme süresinden kaynaklanıyor: Engelleyici bir sunucu, mevcut isteği tamamlamadan yeni isteğe başlayamaz. TrueAsync ile CPU kullanımı daha yüksektir çünkü coroutine’ler I/O sırasında beklemek yerine işçiyi bloke etmeden çalışır.
Bir sihir yok. Sadece daha iyi kaynak kullanımı.
Yük Altında Bellek Kullanımı
Yük Altında Bellek Kullanımı
| İşçiler | TrueAsync | Swoole ZTS | FrankenPHP Octane |
|---|---|---|---|
| 4 | 277 MB | 508 MB | 401 MB |
| 8 | 286 MB | 600 MB | 417 MB |
| 16 | 308 MB | 765 MB | 403 MB |
Engelleyici modelde, her işçi, tam bir Laravel kopyasıyla ayrı bir süreçtir: konteyner, yapılandırma, yönlendirici, middleware, veritabanı yöneticisi. TrueAsync ile coroutine’ler ortak bir bootstrap paylaşır. Sadece isteğe özgü veriler (request, session, auth) çoğaltılır. Bu nedenle 308 MB ile 765 MB arasında büyük bir fark vardır.
Önemli Çıkarımlar
Önemli Çıkarımlar
Testlere tamamen güvenmemek gerekir. Farklı senaryolar mümkün. Ancak burada sihir yok.
Maksimum işçi sayısında bile, TrueAsync yüzde 30-40 daha etkili. Aynı üretkenliği elde edebilmek için 22-27 engelleyici işçi çalıştırabilirsiniz, ancak burada gecikme ve bellek açısından kaybınız olacaktır. Peki, neden 22 işçi kullanasınız ki, 4’ü yeterken?
Sonuç: IO-bound yükler (ki çoğu web uygulaması böyledir) için, TrueAsync aynı trafiği 5-6 kat daha az işçi ile, 56 kat daha düşük gecikme ile ve yarı bellek ile sunar.
Kaynak: Orijinal Makale




