PHP 8 ile birlikte gelen JIT (Just-In-Time) derleyicisi, duyurulduğu günden beri hakkında en çok yanlış beklenti kurulan özellik oldu. "PHP artık derleniyor, siteler uçacak" cümlesini çok duydunuz; sonra JIT'i açtınız, sayfa hızında hiçbir değişiklik göremediniz ve neyi yanlış yaptığınızı merak ettiniz. Cevap şu: muhtemelen hiçbir şeyi yanlış yapmadınız. PHP JIT gerçekten çalışıyor ve gerçekten hızlandırıyor — sadece tipik bir web sayfasının zaman harcadığı yerde değil.
Bu rehberde JIT'in ne olduğunu, OPcache ile ilişkisini, opcache.jit ayarındaki dört haneli sayının ne anlama geldiğini ve hangi iş yüklerinde ölçülebilir kazanç verdiğini anlatacağım. Ayrıca JIT'i açmadan önce ölçmeniz gereken şeyi, açtıktan sonra gerçekten aktif olduğunu nasıl doğrulayacağınızı ve neden çoğu web sitesinde JIT yerine başka katmanlara yatırım yapmanız gerektiğini göstereceğim. Amaç, kararınızı reklam sloganıyla değil kendi ölçümünüzle vermeniz.
PHP Kodu Normalde Nasıl Çalışır#
JIT'i anlamak için önce onsuz ne olduğunu bilmeniz gerekir. PHP yorumlanan bir dildir ve bir istek geldiğinde şu adımlar işler: kaynak dosya okunur, sözcüksel çözümleme (lexing) ve ayrıştırma (parsing) yapılır, soyut sözdizimi ağacı üretilir, bu ağaçtan opcode adı verilen ara komutlar derlenir ve Zend sanal makinesi (VM) bu opcode'ları tek tek çalıştırır.
Bu zincirin ilk yarısı — okuma, ayrıştırma, opcode üretme — dosya değişmediği sürece her istekte aynı sonucu verir. İşte OPcache tam olarak burayı ortadan kaldırır: üretilen opcode'ları paylaşımlı bellekte tutar ve sonraki isteklerde derleme adımını tamamen atlar. Bu yüzden OPcache, PHP dünyasındaki tek en büyük hızlandırmadır ve JIT'ten önce mutlaka doğru kurulmuş olması gerekir.
JIT ise zincirin ikinci yarısına müdahale eder. OPcache opcode'ları hazırlar; JIT ise bu opcode'ların bir kısmını sanal makinede yorumlamak yerine doğrudan CPU'nun anlayacağı makine koduna çevirir ve o makine kodunu çalıştırır. Yani "sanal makine döngüsü" aradan çıkar.
| Aşama | OPcache olmadan | OPcache ile | OPcache + JIT ile |
|---|---|---|---|
| Ayrıştırma ve derleme | Her istekte | Bir kez | Bir kez |
| Opcode çalıştırma | VM yorumlar | VM yorumlar | Sıcak yollar makine kodu |
| Tipik kazanç kaynağı | — | Derleme maliyeti sıfırlanır | CPU yoğun döngüler hızlanır |
Tabloya dikkat edin: JIT'in kazanç sağladığı sütun yalnızca "opcode çalıştırma" satırıdır. Eğer isteğinizin süresi opcode çalıştırmakla değil, veritabanı yanıtı beklemekle geçiyorsa JIT hiçbir şey değiştirmez. Bu, yazının geri kalanını özetleyen tek cümledir.
JIT Nasıl Açılır: opcache.jit Ayarları#
JIT, OPcache uzantısının içindedir; ayrı bir uzantı kurmanız gerekmez. İki ayar birlikte çalışır: JIT için ayrılan tampon boyutu ve JIT modunu belirleyen dört haneli sayı.
; /etc/php/8.3/fpm/conf.d/10-opcache.ini
; OPcache önce doğru kurulmuş olmalı
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
; JIT için ayrılan bellek. 0 ise JIT KAPALIDIR.
opcache.jit_buffer_size=128M
; JIT modu (dört haneli sayı, aşağıda açıklanıyor)
opcache.jit=tracing
opcache.jit_buffer_size değeri sıfır olduğu sürece opcache.jit ne yazarsanız yazın JIT çalışmaz — bu, en sık yapılan "açtım ama olmadı" hatasıdır. Tampon, üretilen makine kodunun tutulduğu alandır; 64M–128M çoğu uygulama için fazlasıyla yeterlidir, çünkü JIT tüm kodu değil yalnızca sık çalışan yolları derler.
opcache.jit için tracing ve function adında iki hazır takma ad vardır ve pratikte kullanacağınız değerler bunlardır:
| Değer | Karşılığı | Davranış |
|---|---|---|
disable | — | Tamamen kapalı, çalışma zamanında açılamaz |
off | — | Kapalı ama çalışma zamanında açılabilir |
function | 1205 | Fonksiyon bazında derleme, daha basit |
tracing | 1254 | Sıcak yolları izleyip derler, genelde daha hızlı |
Dört haneli sayının her hanesi ayrı bir kararı temsil eder: soldan sağa CPU optimizasyon bayrağı, register tahsis stratejisi, tetikleyici (ne zaman derlensin) ve optimizasyon seviyesi. Uygulamada bu haneleri elle kurcalamanız gereken bir senaryo neredeyse yoktur; tracing varsayılan olarak önerilen değerdir ve karşılaştırma yapacaksanız function ile kıyaslamanız yeterlidir.
Ayarı uyguladıktan sonra servisi yeniden yükleyin ve gerçekten aktif olduğunu doğrulayın:
# Servisi kesintisiz yeniden yükle
systemctl reload php8.3-fpm
# CLI tarafında hızlı kontrol
php -i | grep -E 'opcache.jit|jit_buffer_size'
# opcache.jit => tracing => tracing
# opcache.jit_buffer_size => 128M => 128M
# JIT gerçekten bellek kullanıyor mu (tampon doluluğu)
php -r '$s = opcache_get_status(); var_dump($s["jit"]);'
opcache_get_status() çıktısındaki jit dizisinde enabled alanı true ve buffer_free değeri toplam tampondan küçükse, JIT çalışıyor ve kod derliyor demektir. buffer_free hiç azalmıyorsa ya JIT kapalıdır ya da hiçbir kod yolu "sıcak" sayılacak kadar tekrarlanmıyordur.
JIT Gerçekten Hangi İş Yükünde Kazandırır#
Şimdi asıl soruya gelelim. JIT'in tasarımı gereği hızlandırdığı şey, sanal makine yorumlama maliyetinin toplam süre içinde büyük paya sahip olduğu kodlardır. Bu, pratikte şu profile uyar: uzun süren döngüler, matematiksel hesaplama, dizi üzerinde yoğun işlem, görüntü işleme, sıkıştırma, şifreleme benzeri saf CPU işleri.
Tipik bir web isteğinin zaman dağılımı ise bambaşkadır. Sıradan bir CMS sayfasında süre kabaca şöyle bölünür:
| Nerede geçiyor | Tipik pay | JIT etkiler mi |
|---|---|---|
| Veritabanı sorguları ve bekleme | %40–60 | Hayır |
| Dosya sistemi, ağ, harici API | %10–25 | Hayır |
| Şablon üretimi, dize işlemleri | %15–30 | Çok az |
| Saf hesaplama / döngü | %2–10 | Evet |
Yani JIT, toplam sürenin belki onda birini oluşturan bir bölümü hızlandırır. O bölümü ikiye katlasanız bile sayfa süresinde göreceğiniz fark ölçüm gürültüsünün içinde kaybolur. WordPress benzeri uygulamalarda JIT'in "neredeyse fark etmemesinin" sebebi budur — bir eksiklik değil, iş yükünün doğası.
JIT'in parladığı gerçek senaryolar şunlardır:
- Uzun süren CLI işleri. Toplu veri dönüştürme, rapor üretimi, büyük CSV işleme, matris hesapları. Süreç uzun yaşadığı için JIT'in derleme maliyeti amorti olur.
- Görüntü ve medya işleme. PHP ile piksel düzeyinde işlem yapan kodlar (saf PHP filtreler, barkod/QR üretimi, grafik çizimi).
- Kalıcı süreç sunucuları. Uygulamanın bellekte kalıcı çalıştığı çalışma zamanlarında (uzun ömürlü işçi süreçleri) sıcak yollar tekrar tekrar çalıştığı için JIT gerçekten devreye girer.
- Şifreleme ve sıkıştırma benzeri saf PHP algoritmalar. Yerel bir uzantı yoksa ve iş PHP tarafında yapılıyorsa fark belirgindir.
Kendi kodunuzun hangi profile girdiğini tahmin etmek yerine ölçün. En basit yöntem, aynı işi JIT açık ve kapalıyken çalıştırıp süreyi karşılaştırmaktır:
# JIT kapalıyken
php -d opcache.enable_cli=1 -d opcache.jit_buffer_size=0 hesap.php
# Süre: 4.812 sn
# JIT açıkken (tracing)
php -d opcache.enable_cli=1 -d opcache.jit_buffer_size=64M -d opcache.jit=tracing hesap.php
# Süre: 1.937 sn
CPU yoğun bir betikte bu kadar belirgin bir fark görürsünüz. Aynı testi web isteğine benzeyen, veritabanına bağlanan bir betikle tekrarlarsanız farkın nasıl eridiğini kendi gözünüzle görmüş olursunuz — ki bu, karar vermenin en dürüst yoludur.
Web Sunucusunda JIT Açmadan Önce Bakılacaklar#
JIT'i açmak zararlı değildir ama sıra beklemesi gereken bir adımdır. Bir web sitesinde performans arıyorsanız, JIT'ten önce ele alınması gereken katmanlar şunlardır ve hepsi JIT'ten kat kat fazla kazandırır:
- OPcache doğru mu?
opcache.enable=1vemax_accelerated_filesproje dosya sayısından büyük mü? Bu ayar yanlışsa JIT'in üzerine kurulacağı temel eksiktir. - PHP sürümünüz güncel mi? Eski bir sürümden yeni sürüme geçmek, JIT'in verebileceğinden çok daha büyük bir kazançtır. PHP sürüm yükseltmenin hıza etkisi yazısı bunun büyüklüğünü tabloyla anlatıyor.
- Veritabanı sorgularınız verimli mi? Süre orada geçiyorsa çözüm indeks ve sorgu düzeltmesidir; veritabanı sorguları sayfa hızını nasıl etkiler yazısındaki teşhis sırasını izleyin.
- Tam sayfa önbelleğiniz var mı? En hızlı PHP isteği, hiç çalışmayan PHP isteğidir. Sunucu tarafı önbellekleme katmanları bu zinciri baştan sona kuruyor.
- PHP-FPM havuzunuz doğru boyutlanmış mı? Tıkanma varsa mesele işlem hızı değil, eşzamanlılık kapasitesidir; PHP-FPM havuz ayarları hesabı gösteriyor.
Bu beş maddeyi geçtikten sonra JIT'i açmak, ölçülebilir bir artı getirebilir — özellikle sitenizde ağır hesaplama yapan özel bölümler varsa. Ama sırayı atlayıp JIT ile başlarsanız, çabanızın karşılığını göremezsiniz.
Riskler, Sınırlar ve Hata Ayıklama#
JIT'in bilinmesi gereken birkaç kenar durumu vardır. Birincisi, JIT ile derlenmiş kodda hata ayıklamak zorlaşır. Bir yığın izi (stack trace) beklediğinizden farklı görünebilir, profilleyici araçların bir kısmı JIT'li kodu doğru raporlamayabilir. Bu yüzden geliştirme ortamında JIT'i kapalı tutmak, canlıda açmak yaygın bir tercihtir.
İkincisi, tampon boyutu süreçler arasında paylaşılır. opcache.jit_buffer_size değeri paylaşımlı bellekten ayrılır; gereğinden büyük vermek, OPcache'in opcode'lar için kullanabileceği alanı azaltmaz ama boşuna bellek rezerve eder. 64M ile başlayıp opcache_get_status() çıktısındaki buffer_free değerini izleyerek karar verin.
Üçüncüsü, JIT bir hata ihtimali ekler. Derleyici katmanı, yorumlayıcıya göre daha karmaşıktır; nadir de olsa belirli kod desenleriyle beklenmedik davranış raporlanmıştır. Canlıya almadan önce uygulamanızın test paketini JIT açıkken bir kez çalıştırmak iyi bir alışkanlıktır.
Sorun yaşadığınızda hızlı geri dönüş için JIT'i tek satırla kapatabilirsiniz:
; Anında devre dışı bırakma: tampon sıfırlanınca JIT çalışmaz
opcache.jit_buffer_size=0
systemctl reload php8.3-fpm
php -r 'var_dump(opcache_get_status()["jit"]["enabled"]);'
# bool(false)
Bir de sık karıştırılan bir nokta var: opcache.jit=disable ile off farklıdır. disable JIT'i tamamen kapatır ve çalışma zamanında ini_set ile açılamaz; off ise kapalıdır ama çalışma zamanında etkinleştirilebilir. Canlı sunucuda öngörülebilirlik istiyorsanız disable daha nettir.
Ölçüm Yapmadan Karar Vermeyin#
JIT tartışmasının kısır döngüye girmesinin sebebi, herkesin farklı iş yükünden bahsedip aynı sonucu beklemesidir. Kendi cevabınızı üretmek için ihtiyacınız olan şey, tekrarlanabilir bir ölçümdür.
Yöntem şudur: uygulamanızın gerçek trafiğini temsil eden birkaç uç noktayı belirleyin (ana sayfa, listeleme, arama, sepet), JIT kapalıyken belirli bir eşzamanlılıkla yük uygulayın ve p95 yanıt süresini kaydedin. Sonra JIT'i açıp aynı testi tekrarlayın. Tek bir isteğin süresine bakmak yanıltıcıdır; asıl fark yük altında ortaya çıkar. Bu tür ölçümü ayrıntılı olarak k6 ile yük testi yazısında anlattım; oradaki senaryoyu JIT açık/kapalı iki koşuda çalıştırmanız yeterli.
Ölçümde iki tuzağa dikkat edin. Birincisi, ilk isteklerde JIT henüz kod derlememiştir; "ısınma" için testin başındaki ilk saniyeleri sonuçtan çıkarın. İkincisi, aynı sunucuda başka bir iş çalışıyorsa (yedekleme, cron, indeksleme) ölçüm kirlenir; testleri sunucu sakinken yapın ve her koşuyu en az iki kez tekrarlayın.
Bir de "ortalama" tuzağı var: ortalama yanıt süresi birkaç hızlı istekle kolayca güzelleşir. Karar verirken p95 ve p99 değerlerine bakın; kullanıcı deneyimini belirleyen, en kötü yüzde beştir.
Sıkça Sorulan Sorular#
PHP JIT'i açmalı mıyım#
Sıradan bir web sitesi için acele etmeyin; önce OPcache'i doğru kurun, PHP sürümünüzü güncelleyin, sorgularınızı ve önbelleğinizi ele alın. Uygulamanızda hesaplama ağırlıklı bölümler ya da uzun süren CLI işleri varsa JIT ölçülebilir kazanç verir; o durumda opcache.jit_buffer_size=64M ve opcache.jit=tracing ile başlayıp önce/sonra ölçüm yapın.
JIT açtım ama hiçbir fark yok, neden#
En yaygın iki sebep var. Birincisi, opcache.jit_buffer_size değeri sıfır kalmıştır; bu durumda JIT modu ne olursa olsun çalışmaz. İkincisi ve daha sık olanı, isteğinizin süresinin PHP'de değil veritabanında, dosya sisteminde ya da harici bir servis çağrısında geçiyor olmasıdır. JIT yalnızca opcode çalıştırma maliyetini azaltır; beklemeyi kısaltmaz.
JIT ile OPcache aynı şey mi#
Hayır, ama JIT OPcache uzantısının içinde gelir ve onsuz çalışmaz. OPcache, PHP kodunun derlenmiş opcode hâlini bellekte tutarak her istekte yeniden derlenmesini engeller. JIT ise bu opcode'ların sık çalışan bölümlerini makine koduna çevirir. OPcache neredeyse her kurulumda büyük kazanç verir; JIT yalnızca belirli iş yüklerinde.
tracing mi function mı seçmeliyim#
Genel öneri tracing'dir; sıcak kod yollarını çalışma sırasında izleyip derlediği için tipik uygulamalarda daha iyi sonuç verir. function daha basit bir strateji izler ve bazı özel iş yüklerinde öne geçebilir. Kararı tahminle değil ölçümle verin: aynı yük testini iki modda çalıştırıp p95 değerlerini karşılaştırın.
JIT paylaşımlı hostingde kullanılabilir mi#
Genellikle hayır; JIT ayarları PHP-FPM havuz düzeyinde tanımlanır ve paylaşımlı ortamlarda bu ayarlar sağlayıcı tarafından yönetilir. Kullanıcıya açılan php.ini düzenleyicileri çoğunlukla memory_limit gibi güvenli değerlerle sınırlıdır. JIT'i kendiniz yönetmek istiyorsanız root erişimi olan bir sanal ya da özel sunucuya ihtiyacınız vardır.
JIT bellek kullanımını artırır mı#
Evet, opcache.jit_buffer_size kadar ek paylaşımlı bellek rezerve edilir ve bu alan üretilen makine kodu için kullanılır. 64M–128M çoğu uygulama için yeterlidir; gereğinden büyük vermek boşa rezerve etmek olur. opcache_get_status() çıktısındaki jit bölümündeki buffer_free değerini izleyerek gerçekte ne kadarının kullanıldığını görebilirsiniz.
JIT'i kapatmak için sunucuyu yeniden başlatmam gerekir mi#
Hayır. opcache.jit_buffer_size=0 yazıp systemctl reload php8.3-fpm çalıştırmanız yeterlidir; reload çalışan istekleri kesmeden yapılandırmayı uygular. Kapandığını opcache_get_status() çıktısındaki jit.enabled alanının false dönmesiyle doğrulayabilirsiniz.
Kapanış#
PHP JIT, dilin olgunlaşmasının güzel bir işareti ve doğru iş yükünde gerçekten etkileyici sonuçlar veriyor; ama tipik bir web sayfasının hızını belirleyen darboğazların çoğu JIT'in dokunduğu yerde değil. Aklınızda kalması gereken dört şey şudur: JIT'ten önce OPcache'i doğru kurmak, jit_buffer_size sıfırken hiçbir modun çalışmadığını bilmek, kazancı p95 üzerinden ve yük altında ölçmek, ve süre nerede geçiyorsa oraya yatırım yapmak. Bu dördü, sizi "açtım ama fark etmedi" kısır döngüsünden kurtarır.
Altyapı tarafını kendiniz kurmak ve JIT dahil tüm PHP ayarlarını yönetmek isterseniz Clou.TR tarafında tam root erişimli VDS ve bulut sunucu seçenekleri buna uygundur. Hesaplama ağırlıklı işler için GPU VDS çözümlerimize göz atabilir, ayarlarla uğraşmadan güncel ve optimize bir PHP yığını isterseniz kurumsal hosting paketlerimizi ya da yapılandırmayı uçtan uca üstlenen sunucu yönetimi hizmetimizi tercih edebilirsiniz.