Ölçemezseniz geliştiremezsiniz.
Lord Kelvin
HTML5 oyunlarınızın daha hızlı çalışmasını sağlamak için öncelikle performans sorunlarını tespit etmeniz gerekir, ancak bu zor olabilir. Saniyedeki kare sayısı (FPS) verilerinin değerlendirilmesi başlangıçtır, ancak resmin tamamını görebilmek için Chrome etkinliklerindeki incelikleri kavramanız gerekir.
about:izleme aracı, performansı artırmaya yönelik ama aslında iyi planlanmış tahminlerden oluşan aceleyle yapılabilecek geçici çözümlerden kaçınmanıza yardımcı olacak bilgiler sağlar. Yüksek zaman ve enerji tasarrufu yapabilir, Chrome'un her karede neler yaptığını daha net bir şekilde görebilir ve bu bilgileri oyununuzu optimize etmek için kullanabilirsiniz.
Merhaba about:izleme
Chrome'un hakkında:izleme aracı, ilk başta zorlayıcı bulabileceğiniz kadar ayrıntı düzeyiyle belirli bir süre boyunca Chrome'un tüm etkinlikleri için size bir pencere sunar. Chrome'daki işlevlerin birçoğu, yeni çıktıları izlemeye yöneliktir. Dolayısıyla, herhangi bir manuel araç kullanmadan performansınızı izlemek için about:tracing özelliğini kullanmaya devam edebilirsiniz. (JS'nizi manuel olarak ayarlama ile ilgili sonraki bölüme bakın)
İzleme görünümünü görmek için "about:tracing" yazmanız yeterlidir yazın.
![Chrome çok amaçlı adres çubuğu](https://web.dev/static/articles/abouttracing/image/chrome-omnibox-cd7c2b0952da3.png?authuser=5&hl=tr)
İzleme aracını kullanarak kaydetmeye başlayabilir, oyununuzu birkaç saniye çalıştırabilir ve ardından iz verilerini görüntüleyebilirsiniz. Aşağıda, verilerin nasıl görünebileceğine dair bir örnek verilmiştir:
![Basit izleme sonucu](https://web.dev/static/articles/abouttracing/image/simple-tracing-result-1d9ca669e5fb8.png?authuser=5&hl=tr)
Evet, bu kafa karıştırıcı. Şimdi, belgenin nasıl okunacağından bahsedelim.
Her satır, profili oluşturulan bir işlemi temsil eder, soldaki sağ eksen ise zamanı gösterir ve renkli kutulardan her biri araçlı bir işlev çağrısıdır. Çeşitli kaynak türleri için satırlar bulunur. Oyun profili oluşturma konusunda en çok ilgi çekenler, Graphics Processing Unit (GPU)'nun (Grafik İşleme Birimi) ne yaptığını gösteren CrGpuMain ve CrRendererMain'dir. Her iz, izleme dönemi boyunca açık olan her sekme için (about:tracing sekmesinin kendisi dahil) CrRendererMain satırları içerir.
İz verilerini okurken ilk göreviniz, hangi CrRendererMain satırının oyununuza karşılık geldiğini belirlemektir.
![Vurgulanmış basit izleme sonucu](https://web.dev/static/articles/abouttracing/image/simple-tracing-result-hig-27a40f191d328.png?authuser=5&hl=tr)
Bu örnekte iki aday şunlardır: 2216 ve 6516. Maalesef çok sayıda düzenli güncelleme yapan satırı aramak (veya kodunuza izleme noktalarıyla manuel olarak ayarladıysanız) giderek iz verilerinizi içeren satırı bulmak dışında uygulamanızı seçmenin şu an için gösterişli bir yolu yoktur. Bu örnekte, 6516'nın güncellemelerin sıklığına göre bir ana döngü çalıştırdığı anlaşı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 hâlâ CrRendererMain satırları olabilir.
Çerçeveniz bulunuyor
Oyununuzun izleme aracında doğru satırı bulduktan sonraki adım ana döngüyü bulmaktır. Ana döngü, izleme verilerinde tekrar eden bir kalıp gibi görünür. İzleme verilerinde W, A, S, D tuşlarını kullanarak sola veya sağa (zamanda geri ve ileri) gitmek için A ve D, verileri yakınlaştırmak ve uzaklaştırmak için W ve S tuşlarını kullanabilirsiniz. Oyununuz 60 Hz hızında çalışıyorsa ana döngünüzün her 16 milisaniyede bir tekrar eden bir kalıp olmasını beklersiniz.
![Üç yürütme çerçevesi gibi görünüyor](https://web.dev/static/articles/abouttracing/image/looks-three-execution-fr-f47b55db5f581.png?authuser=5&hl=tr)
Oyununuzun sinyalini tespit ettikten sonra kodunuzun her karede tam olarak ne yaptığını ayrıntılı olarak inceleyebilirsiniz. İşlev kutularındaki metinleri okuyabilene kadar yakınlaştırmak için W, A, S, D tuşlarını kullanın.
![Yürütme çerçevesinin derinlikleri](https://web.dev/static/articles/abouttracing/image/deep-an-execution-frame-c862ec9cb9343.png?authuser=5&hl=tr)
Bu kutu koleksiyonu, her çağrının renkli bir kutuyla temsil edildiği bir dizi işlev çağrısını gösterir. Her bir işlev üzerindeki kutuyla çağrılmıştır. Bu nedenle, bu örnekte RenderWidget::OnSwapBuffersComplete olarak adlandırılan MessageLoop::RunTask'in RenderWidget::DoDeestimatedUpdate vb. olarak adlandırıldığını görebilirsiniz. Bu verileri okuyarak her yürütmenin ne olarak adlandırıldığını ve ne kadar sürdüğünü eksiksiz olarak görebilirsiniz.
Ama burası burada biraz sabitleniyor. about:tracing tarafından sunulan bilgiler, Chrome kaynak kodundan gelen ham işlev çağrılarıdır. Adından her bir işlevin ne yaptığı hakkında bilgiye dayalı tahminlerde bulunabilirsiniz, ancak bilgiler tam olarak kullanıcı dostu değildir. Kadrajınızın genel akışını görmek faydalı olabilir, ancak sorunun gerçek nedenini anlamak için daha fazla insan tarafından okunabilecek bir şeye ihtiyacınız vardır.
İz etiketleri ekleme
Neyse ki iz 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ü adında belirtilen etiketlerle yeni kutular oluşturur. Dolayısıyla, uygulamayı yeniden çalıştırırsanız "güncelle" ifadesini görürsünüz. ve "render" adlı her bir etiket için başlangıç ve bitiş çağrıları arasında geçen süreyi gösteren kutular
![Manuel olarak eklenen etiketler](https://web.dev/static/articles/abouttracing/image/tags-added-manually-97406d4b80c0e.png?authuser=5&hl=tr)
Bunu kullanarak, kodunuzdaki hotspot'ları izlemek için insan tarafından okunabilen izleme verileri oluşturabilirsiniz.
GPU mu CPU mu?
Donanım hızlandırmalı grafiklerle ilgili olarak, profil çıkarma sırasında sorabileceğiniz en önemli sorulardan biri şudur: Bu kod GPU'ya mı bağlı mı yoksa CPU'ya mı bağlı? Her kareyle birlikte GPU üzerinde bazı oluşturma çalışmaları yapacaksınız ve CPU üzerinde bazı mantıklar yapacaksınız. Oyununuzu yavaşlatan şeyin ne olduğunu anlamak için işin bu iki kaynak arasında nasıl dengelendiğini görmeniz gerekir.
Öncelikle, izleme görünümündeki CrGPUMain adlı satırı bulun. Bu satır, GPU'nun belirli bir zamanda meşgul olup olmadığını gösterir.
![GPU ve CPU izleri](https://web.dev/static/articles/abouttracing/image/gpu-cpu-traces-4f4eb3986da83.png?authuser=5&hl=tr)
Oyununuzun her karesinin hem CrRendererMain'de hem de GPU'da CPU çalışmasına neden olduğunu görebilirsiniz. Yukarıdaki iz, her 16 ms'lik karenin çoğunda hem CPU hem de GPU'nun boşta olduğu çok basit bir kullanım durumunu gösterir.
İzleme görünümü, yavaş çalışan bir oyununuz olduğunda ve hangi kaynağı en üst düzeye çıkardığınızdan emin değilseniz gerçekten işinize yarar. Hata ayıklamanın anahtarı, GPU ve CPU çizgilerinin ilişkisine bakmaktır. Öncekiyle aynı örneği ele alalım ancak güncelleme döngüsüne biraz daha fazla çalışma ekleyin.
console.time("update");
doExtraWork();
update(Math.min(50, now - time));
console.timeEnd("update");
console.time("render");
render();
console.timeEnd("render");
Şimdi şuna benzer bir iz görürsünüz:
![GPU ve CPU izleri](https://web.dev/static/articles/abouttracing/image/gpu-cpu-traces-803b8ee665596.png?authuser=5&hl=tr)
Bu iz bize ne anlatıyor? Resimdeki karenin 2.270 ms. ile 2.320 ms. arasında olduğunu, yani her karenin yaklaşık 50 ms (20 Hz kare hızı) sürdüğünü görüyoruz. Güncelleme kutusunun yanında oluşturma işlevini temsil eden renkli kutulardan oluşan şeritler görebilirsiniz ancak çerçeve tamamen güncellemenin kendisi tarafından hakimdir.
CPU'da olanlardan farklı olarak, her karenin büyük bir kısmında GPU'nun boşta kaldığını görebilirsiniz. Bu kodu optimize etmek için gölgelendirici kodunda yapılabilecek işlemleri arayabilir ve kaynaklardan en iyi şekilde yararlanmak için bunları GPU'ya taşıyabilirsiniz.
Gölgelendirici kodunun kendisi yavaşsa ve GPU'nun aşırı çalışması durumunda ne olacak? Gereksiz iş yükünü CPU'dan kaldırıp bunun yerine parça gölgelendirici koduna iş eklersek ne olur? Gereksiz maliyetli bir parça 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 kod izi nasıl görünür?
![Yavaş GPU kodu kullanılırken GPU ve CPU izleri](https://web.dev/static/articles/abouttracing/image/gpu-cpu-traces-using-sl-ffb0094996429.png?authuser=5&hl=tr)
Yine, bir karenin süresine dikkat edin. Burada tekrar eden kalıp yaklaşık 2.750 ms. ile 2.950 ms. arasında, 200 ms. sürer (yaklaşık 5 Hz kare hızı). CrRendererMain satırı neredeyse tamamen boştur, yani GPU aşırı yüklüyken CPU çoğu zaman boştadır. Bu durum, gölgelendiricilerinizin çok ağır olduğunun kesin bir işaretidir.
Düşük kare hızına neden olan nedeni tam olarak göremiyorsanız 5 Hz güncellemesini gözlemleyebilir ve oyun koduna girip oyun mantığını optimize etmeyi veya kaldırmayı deneyebilirsiniz. Bu durumda bu kesinlikle işe yaramaz çünkü oyun döngüsünün mantığı zaman kaybetmekten ibaret değildir. Bu iz, her karenin daha fazla CPU işi yapmanın aslında "ücretsiz" olacağını gösteriyor. boşta kaldığından, ona daha fazla iş yapılması karenin ne kadar süreceğini etkilemez.
Gerçek Örnekler
Şimdi gerçek bir oyundan elde edilen izleme verilerinin nasıl olduğuna bakalım. Açık web teknolojileriyle geliştirilen oyunların güzel yanlarından biri, favori ürünlerinizde neler olup bittiğini görebilmenizdir. Profil oluşturma araçlarını test etmek istiyorsanız Chrome Web Mağazası'ndan favori WebGL başlığınızı seçebilir ve about:tracing ile profil oluşturabilirsiniz. Bu, mükemmel WebGL oyunu Skid Racer'dan alınmış bir izdir.
![Gerçek bir oyunun izinde](https://web.dev/static/articles/abouttracing/image/tracing-real-game-adc53901fdb79.png?authuser=5&hl=tr)
Her kare yaklaşık 20 ms alır. Yani kare hızı yaklaşık 50 FPS'dir. İşin CPU ve GPU arasında dengelendiğini ancak GPU'nun en çok talep gören kaynak olduğunu görebilirsiniz. WebGL oyunlarının gerçek örneklerini profiliyle görmek istiyorsanız, WebGL ile oluşturulmuş bazı Chrome Web Mağazası oyunlarını deneyin. Örneğin:
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. Birbirine paralel olarak kullanılabilecek iki kaynağınız var ve performansı en üst düzeye çıkarmak için çalışmaları bu kaynaklar arasında değiştirebilirsiniz. Chrome'un about:tracing görünümü, kodunuzun gerçekte ne yaptığı konusunda fikir sahibi olmak 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 zamanı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 birkaç etkinliği izlemek için geliştirilmiştir. İzleme etkinliklerinin mevcut durumunu daha iyi anlamak için bu Chromium makalesini okumalısınız.
Web oyunu geliştiricisiyseniz aşağıdaki videoyu izlediğinizden emin olun. Google'ın GDC 2012'de Oyun Geliştiricileri Destekçisi ekibinin Chrome oyunları için performans optimizasyonu hakkında yaptığı bir sunumdur: