Ölçemediğiniz unsurları geliştiremezsiniz.
Lord Kelvin
HTML5 oyunlarınızın daha hızlı çalışmasını sağlamak için önce performans darboğazlarını tespit etmeniz gerekir. Ancak bu işlem zor olabilir. Saniyedeki kare sayısı (FPS) verilerini değerlendirmek iyi bir başlangıçtır ancak tüm resmi görmek için Chrome etkinliklerindeki ayrıntıları anlamanız gerekir.
about:tracing
aracı, performansı iyileştirmeyi amaçlayan ancak temelde iyi niyetli tahminlerden ibaret olan aceleci geçici çözümlerden kaçınmanıza yardımcı olacak analizler sunar. Böylece çok fazla zaman ve enerji tasarrufu sağlar, Chrome'un her karede ne yaptığına dair daha net bir fikir edinir ve bu bilgileri oyununuzu optimize etmek için kullanabilirsiniz.
Merhaba about:tracing
Chrome'un about:tracing
aracı, Chrome'un belirli bir dönemdeki tüm etkinliklerini size gösterir. Bu araç, ilk başta çok ayrıntılı görünebilir. Chrome'daki işlevlerin çoğu, izleme için hazır olarak donatılmıştır. Bu nedenle, manuel araç kullanmadan da performansınızı izlemek için about:tracing
'ü kullanabilirsiniz. (JS'nizi manuel olarak enstrümante etmeyle ilgili sonraki bir bölüme bakın.)
İzleme görünümünü görmek için Chrome'un her şey bir arada kutusuna (adres çubuğu) "about:tracing" yazın.
İzleme aracından kaydı başlatabilir, oyununuzu birkaç saniye çalıştırabilir ve ardından izleme verilerini görüntüleyebilirsiniz. Verilerin nasıl görünebileceğine dair bir örnek:
Evet, kafa karıştırıcı bir durum. Bu raporu nasıl okuyacağınızdan bahsedelim.
Her satır, profil oluşturulan bir süreci temsil eder. Sol-sağ ekseni zamanı gösterir ve her renkli kutu, enstrümante edilmiş bir işlev çağrısıdır. Çeşitli kaynaklar için satırlar vardır. Oyun profilleme için en ilginç olan, Grafik İşlem Birimi'nin (GPU) ne yaptığını gösteren CrGpuMain ve CrRendererMain'dir. Her izleme, izleme dönemi boyunca açık olan her sekme (about:tracing
sekmesi dahil) için CrRendererMain satırları içerir.
İzleme verilerini okurken ilk işiniz, oyununuza karşılık gelen CrRendererMain satırını belirlemektir.
Bu örnekte iki aday şunlardır: 2216 ve 6516. Maalesef şu anda uygulamanızı seçmenin, çok sayıda düzenli güncelleme yapan satırı aramak (veya kodunuzu manuel olarak izleme noktalarıyla donattıysanız izleme verilerinizi içeren satırı aramak) dışında mükemmel bir yolu yoktur. Bu örnekte, 6516'ın güncelleme sıklığından bir ana döngü çalıştırdığı görülüyor. İzlemeye başlamadan önce diğer tüm sekmeleri kapatırsanız doğru CrRendererMain'i bulmak daha kolay olur. Ancak oyununuz dışındaki işlemler için CrRendererMain satırları olabilir.
Çerçevenizi bulma
Oyununuzun izleme aracında doğru satırı bulduktan sonra ana döngüyü bulmanız gerekir. Ana döngü, izleme verilerinde tekrarlanan bir kalıp gibi görünür. W, A, S, D tuşlarını kullanarak izleme verilerinde gezinebilirsiniz: A ve D tuşlarını kullanarak sola veya sağa (zaman içinde ileri geri) hareket edebilir, W ve S tuşlarını kullanarak verileri yakınlaştırabilir veya uzaklaştırabilirsiniz. Oyununuz 60 Hz'de çalışıyorsa ana döngünüzün 16 milisaniyede bir tekrar eden bir kalıp olmasını beklersiniz.
Oyununuzun kalp atışını bulduktan sonra, kodunuzun her karede tam olarak ne yaptığını inceleyebilirsiniz. İşlev kutularındaki metni okuyana kadar yakınlaştırmak için W, A, S, D tuşlarını kullanın.
Bu kutu koleksiyonu, her biri renkli bir kutuyla temsil edilen bir dizi işlev çağrısını gösterir. Her işlev, üzerindeki kutu tarafından çağrılmıştır. Bu durumda, MessageLoop::RunTask'ın RenderWidget::OnSwapBuffersComplete'i, bunun da RenderWidget::DoDeferredUpdate'yi çağırdığını görebilirsiniz. Bu verileri okuyarak nelerin neyi çağırdığını ve her bir yürütmenin ne kadar sürdüğünü tam olarak görebilirsiniz.
Ancak burada işler biraz karışıyor. about:tracing
tarafından sunulan bilgiler, Chrome kaynak kodundaki ham işlev çağrılarıdır. Her işlevin ne yaptığı hakkında adından tahmin yürütebilirsiniz ancak bu bilgiler tam olarak kullanıcı dostu değildir. Çerçevenizin genel akışını görmek yararlı olsa da neler olduğunu gerçekten anlamak için biraz daha kullanıcı dostu bir şeye ihtiyacınız vardır.
İzleme etiketleri ekleme
Neyse ki izleme verileri oluşturmak için kodunuza manuel enstrümantasyon eklemenin kolay bir yolu var: console.time
ve console.timeEnd
.
console.time("update");
update();
console.timeEnd("update");
console.time("render");
update();
console.timeEnd("render");
Yukarıdaki kod, izleme görünümünde belirtilen etiketlerle yeni kutular oluşturur. Bu nedenle, uygulamayı yeniden çalıştırırsanız her etiketin başlangıç ve bitiş çağrıları arasında geçen süreyi gösteren "güncelleme" ve "oluşturma" kutularını görürsünüz.
Bu sayede, kodunuzdaki yoğun noktaları izlemek için kullanıcı tarafından okunabilir izleme verileri oluşturabilirsiniz.
GPU mu yoksa CPU mu?
Donanım hızlandırmalı grafiklerde, profil oluşturma sırasında sormanız gereken en önemli sorulardan biri şudur: Bu kod GPU'ya mı yoksa CPU'ya mı bağlı? Her karede GPU'da bazı oluşturma çalışmaları ve CPU'da bazı mantık çalışmaları yaparsınız. Oyununuzun yavaşlamasını neyin sağladığını anlamak için çalışmaların iki kaynak arasında nasıl dengelendiğini görmeniz gerekir.
Öncelikle, izleme görünümünde CrGPUMain adlı satırı bulun. Bu satır, GPU'nun belirli bir zamanda meşgul olup olmadığını gösterir.
Oyununuzun her karesinin hem CrRendererMain'de hem de GPU'da CPU çalışmasına neden olduğunu görebilirsiniz. Yukarıdaki izleme, hem CPU hem de GPU'nun her 16 ms çerçevenin çoğunda boşta olduğu çok basit bir kullanım alanını gösterir.
Yavaş çalışan bir oyununuz varsa ve hangi kaynağın sınırına ulaştığınızdan emin değilseniz izleme görünümü gerçekten faydalı olur. Hata ayıklamanın anahtarı, GPU ve CPU satırlarının nasıl ilişkili olduğuna bakmaktır. Önceki örnekle aynısını yapın ancak güncelleme döngüsüne biraz daha fazla iş ekleyin.
console.time("update");
doExtraWork();
update(Math.min(50, now - time));
console.timeEnd("update");
console.time("render");
render();
console.timeEnd("render");
Ardından aşağıdaki gibi bir izleme görürsünüz:
Bu izleme bize neyi gösteriyor? Resimdeki karenin yaklaşık 2.270 ms ile 2.320 ms arasında değiştiğini görüyoruz. Bu da her karenin yaklaşık 50 ms (20 Hz kare hızı) sürdüğü anlamına gelir. Güncelleme kutusunun yanında, oluşturma işlevini temsil eden renkli kutuların küçük parçalarını görebilirsiniz ancak çerçevenin tamamı güncellemenin kendisi tarafından kaplanmıştır.
CPU'da olanın aksine, GPU'nun her karenin çoğunda boşta kaldığını görebilirsiniz. Bu kodu optimize etmek için gölgelendirici kodunda yapılabilecek işlemleri arayabilir ve kaynakları en iyi şekilde kullanmak için bunları GPU'ya taşıyabilirsiniz.
Gölgelendirici kodunun kendisi yavaşsa ve GPU aşırı çalışıyorsa ne olur? CPU'dan gereksiz işlemleri kaldırıp bunun yerine parçacık gölgelendirici koduna bazı işlemler eklesek ne olur? Gereksiz yere pahalı bir parçacık gölgelendiriciyi aşağıda bulabilirsiniz:
#ifdef GL_ES
precision highp float;
#endif
void main(void) {
for(int i=0; i<9999; i++) {
gl_FragColor = vec4(1.0, 0, 0, 1.0);
}
}
Bu gölgelendiriciyi kullanan bir kod izleme nasıl görünür?
Bir karenin süresini tekrar not edin. Burada tekrarlanan kalıp yaklaşık 2750 ms ile 2950 ms arasındadır. Bu da 200 ms'lik bir süreye (yaklaşık 5 Hz kare hızı) karşılık gelir. CrRendererMain satırı neredeyse tamamen boştur. Bu, CPU'nun çoğu zaman boşta olduğu, GPU'nun ise aşırı yüklendiği anlamına gelir. Bu, gölgelendiricilerinizin çok ağır olduğunun kesin bir işaretidir.
Düşük kare hızına tam olarak neyin neden olduğunu bilmiyorsanız 5 Hz güncellemesini gözlemleyebilir ve oyun koduna gidip oyun mantığını optimize etmeye veya kaldırmaya çalışabilirsiniz. Bu durumda, oyun döngüsünde yer alan mantık zaman alıcı olmadığından bu işlem kesinlikle işe yaramaz. Aslında bu izleme, her karede daha fazla CPU çalışmasının yapılmasının temelde "ücretsiz" olacağını gösterir. Bunun nedeni, CPU'nun boşta beklemesidir. Bu nedenle, CPU'ya daha fazla iş verilmesi, karenin ne kadar süreceğini etkilemez.
Gerçek Örnekler
Şimdi de gerçek bir oyundan alınan izleme verilerinin nasıl göründüğüne bakalım. Açık web teknolojileri ile geliştirilen oyunların en iyi özelliklerinden biri, en sevdiğiniz ürünlerde neler olup bittiğini görebilmenizdir. Profil oluşturma araçlarını test etmek istiyorsanız Chrome Web Mağazası'ndan en sevdiğiniz WebGL başlığını seçip about:tracing
ile profilini oluşturabilirsiniz. Bu, mükemmel WebGL oyunu Skid Racer'dan alınan bir örnek izlemedir.
Her karenin yaklaşık 20 ms sürdüğü anlaşılıyor. Bu da kare hızının yaklaşık 50 FPS olduğu anlamına geliyor. İşin CPU ve GPU arasında dengeli olduğunu ancak en çok talep gören kaynağın GPU olduğunu görebilirsiniz. WebGL oyunlarının gerçek örneklerini profillemenin nasıl bir şey olduğunu görmek istiyorsanız aşağıdakiler gibi WebGL ile oluşturulmuş Chrome Web Mağazası oyunlarından bazılarını deneyebilirsiniz:
Sonuç
Oyununuzun 60 Hz'de çalışmasını istiyorsanız her kare için tüm işlemlerinizin 16 ms CPU ve 16 ms GPU süresine sığması gerekir. Paralel olarak kullanılabilecek iki kaynağınız vardır ve performansı en üst düzeye çıkarmak için işleri bunlar arasında taşıyabilirsiniz. Chrome'un about:tracing
görünümü, kodunuzun gerçekte ne yaptığı hakkında bilgi edinmek için paha biçilmez bir araçtır ve doğru sorunları ele alarak geliştirme sürenizi en üst düzeye çıkarmanıza yardımcı olur.
Sırada ne var?
GPU'nun yanı sıra Chrome çalışma ortamının diğer bölümlerini de izleyebilirsiniz. Chrome'un erken aşama sürümü olan Chrome Canary, IO, IndexedDB ve diğer çeşitli etkinlikleri izlemek için donatılmıştır. İzleme etkinliklerinin mevcut durumunu daha iyi anlamak için bu Chromium makalesini okumanız gerekir.
Web oyunu geliştiriciyseniz aşağıdaki videoyu izlemeyi unutmayın. Google'ın Oyun Geliştirici Destek Ekibi'nin GDC 2012'de Chrome oyunları için performans optimizasyonu hakkında yaptığı bir sunudur: