about:tracing işaretiyle WebGL Oyununuzun profilini oluşturma

Lilli Thompson'dan filmler
Lilli Thompson

Ölçümü yapamıyorsanız iyileştiremezsiniz.

Lord Kelvin

HTML5 oyunlarınızın daha hızlı çalışmasını sağlamak için önce performans sorunlarını tespit etmeniz gerekir, ancak bu zor olabilir. Saniyedeki kare (FPS) verilerinin değerlendirilmesi başlangıçtır, ancak resmin tamamını görmek için Chrome etkinliklerindeki nüansları kavramanız gerekir.

about:tracing aracı, performans iyileştirmeye yönelik acele edilmiş çözümlerden kaçınmanıza yardımcı olan bilgiler sağlar, ancak bunlar temelde iyi niyetli tahminlere dayalı tahminlerdir. Çok fazla zaman ve enerji tasarrufu yapacak, her karede Chrome'un ne yaptığına ilişkin daha net bir fikir edinecek ve bu bilgileri oyununuzu optimize etmek için kullanacaksınız.

Merhaba about:tracing

Chrome'un about:tracing aracı, başlangıçta gözünüzü korkutabilecek kadar ayrıntı düzeyine sahip bir zaman diliminde, Chrome'un tüm etkinliklerine ilişkin bir pencere sağlar. Chrome'daki işlevlerin çoğu, ilk andan itibaren izleme işlevine sahiptir. Dolayısıyla, herhangi bir manuel araç kullanmadan, performansınızı izlemek için about:tracing özelliğini kullanmaya devam edebilirsiniz. (JS'nizin manuel olarak enstrümantasyonuyla ilgili daha sonraki bir bölüme bakın)

İzleme görünümünü görmek için Chrome'un çok amaçlı adres çubuğuna"about:tracing" yazmanız yeterlidir.

Chrome çok amaçlı adres çubuğu
Chrome'un çok amaçlı adres çubuğuna"about:tracing" yazın

İzleme aracını kullanarak kaydetmeye başlayabilir, oyununuzu birkaç saniye çalıştırdıktan sonra iz verilerini görüntüleyebilirsiniz. Aşağıda, verilerin nasıl görünebileceğine dair bir örnek verilmiştir:

Basit izleme sonucu
Basit izleme sonucu

Evet, bu kafa karıştırıcı. Şimdi bu belgeyi nasıl okuyacağınızdan bahsedelim.

Her satır, profili oluşturulan bir işlemi, sol-sağ eksen zamanı belirtir ve her renkli kutu, izlemeli bir işlev çağrısıdır. Çeşitli kaynak türleri için satırlar bulunur. Oyun profili oluşturma konusunda en ilgi çekici alanlar, Grafik İşleme Birimi'nin (GPU) ne yaptığını gösteren CrGpuMain ve CrRendererMain. Her iz, izleme dönemi boyunca (about:tracing sekmesinin kendisi dahil) her açık sekme için CrRendererMain satırları içerir.

İz verilerini okurken ilk göreviniz hangi CrRendererMain satırının oyununuza karşılık geldiğini belirlemektir.

Basit izleme sonucu vurgulandı
Basit izleme sonucu vurgulanmış halde

Bu örnekte iki aday 2216 ve 6516'dır. Maalesef şu anda, çok sayıda düzenli güncelleme yapan çizgiyi bulmak (veya kodunuza iz noktalarıyla manuel olarak donattıysanız, iz verilerinizi içeren satırı bulmak) dışında uygulamanızı seçmek için şık bir yol yoktur. Bu örnekte, 6516'nın güncellemelerin sıklığına göre bir ana döngü çalıştırdığı görülmektedir. İ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.

Kadrajınız bulunuyor

Oyununuzun izleme aracında doğru satırı bulduktan sonraki adım ana döngüyü bulmaktır. Ana döngü, izleme verilerinde tekrarlanan bir kalıp gibi görünür. İzleme verilerinde gezinmek için W, A, S, D tuşlarını kullanabilirsiniz: sola veya sağa (zamanda ileri geri) hareket etmek için A ve D tuşlarını, verileri yakınlaştırmak ve uzaklaştırmak için W ve S tuşlarını kullanabilirsiniz. Oyununuz 60 Hz'de çalışıyorsa ana döngünüzün 16 milisaniyede bir tekrar eden bir kalıp olmasını beklersiniz.

Üç yürütme çerçevesi gibi görünür
Üç yürütme çerçevesi gibi görünüyor

Oyununuzun kalp atış hızını belirledikten sonra, kodunuzun her karede tam olarak ne yaptığını inceleyebilirsiniz. İşlev kutularındaki metni okuyabilene kadar yakınlaştırmak için W, A, S, D tuşlarını kullanın.

Yürütme çerçevesinin derinliklerine
Yürütme çerçevesinin derinliklerine

Bu kutular koleksiyonu, her çağrı renkli bir kutuyla temsil edilen bir dizi işlev çağrısını gösterir. Her bir işlev üzerindeki kutu tarafından çağrılmıştır. Dolayısıyla bu örnekte, MessageLoop::RunTask adlı RenderWidget::OnSwapBuffersComplete (RenderWidget::DoDeizedUpdate vb.) adlı MessageLoop::RunTask öğesini görebilirsiniz. Bu verileri okuyarak her bir yürütme işleminin neyin adı ve ne kadar sürdüğünü tam olarak görebilirsiniz.

Ancak burada biraz yapışkan hale geliyor. about:tracing tarafından gösterilen bilgiler, Chrome kaynak kodundan gelen ham işlev çağrılarıdır. Adını kullanarak her bir işlevin ne yaptığına dair bilgiye dayalı tahminlerde bulunabilirsiniz, ancak bilgiler tam olarak kullanıcı dostu değildir. Kadrajınızın genel akışını görmek faydalıdır ancak gerçekten neler olduğunu 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 araçlar 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. Bu nedenle, uygulamayı yeniden çalıştırırsanız her bir etiket için başlangıç ve bitiş çağrıları arasında geçen süreyi gösteren "güncelle" ve "oluştur" kutuları görürsünüz.

Etiketler manuel olarak eklendi
Etiketler manuel olarak eklenir

Bunu kullanarak kodunuzdaki hotspot'ları izlemek için okunabilir izleme verileri oluşturabilirsiniz.

GPU mu CPU mu?

Donanım hızlandırmalı grafiklerde profil çıkarma sırasında sorabileceğiniz en önemli sorulardan biri şudur: Bu kod GPU'ya bağlı mı yoksa CPU'ya bağlı mı? Her karede GPU'da oluşturma çalışması ve CPU'da da bir mantık yapacaksınız. Oyununuzu yavaşlatan şeyin ne olduğunu anlamak için işin iki kaynak arasında nasıl dengelendiğini görmeniz gerekir.

Önce, izleme görünümünde GPU'nun belirli bir zamanda meşgul olup olmadığını gösteren CrGPUMain adlı satırı bulun.

GPU ve CPU izleri

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östermektedir.

İzleme görünümü, yavaş çalışan bir oyununuz varsa ve hangi kaynağı tükettiğinizden emin değilseniz gerçekten yararlı olur. Hata ayıklama için GPU ve CPU satırlarının nasıl bir ilişki içinde olduğunu görmek çok önemlidir. Önceki örneğin aynısını alın, ancak güncelleme döngüsüne biraz daha çalışma ekleyin.

console.time("update");
doExtraWork();
update(Math.min(50, now - time));
console.timeEnd("update");

console.time("render");
render();
console.timeEnd("render");

Şimdi aşağıdakine benzer bir iz görürsünüz:

GPU ve CPU izleri

Bu iz bize ne anlatıyor? Resimde gösterilen karenin yaklaşık 2270 ms'den 2320 ms'ye çıktığını, yani her karenin yaklaşık 50 ms (20 Hz kare hızı) sürdüğünü görebiliriz. Güncelleme kutusunun yanında oluşturma işlevini temsil eden renkli kutular görebilirsiniz ancak çerçeveye tümüyle güncellemenin hakimiyeti hakimdir.

CPU'da olanların aksine, GPU'nun her karenin büyük bölümünde hâlâ boşta durduğunu 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.

Peki ya gölgelendirici kodunun kendisi yavaş, GPU'nun aşırı çalıştığı durumlarda ne olur? Gereksiz çalışmayı CPU'dan kaldırıp bunun yerine parça gölgelendirici koduna bazı çalışmalar eklersek ne olur? Burada, gereksiz derecede pahalı bir parça gölgelendirici verilmiştir:

#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
Yavaş GPU kodu kullanılırken GPU ve CPU izleri

Yine, bir karenin süresine dikkat edin. Burada tekrarlanan kalıp, yaklaşık 2750 ms'den 2950 ms'ye kadar değişir. Süre 200 ms'dir (yaklaşık 5 Hz kare hızı). CrRendererMain satırı neredeyse tamamen boş, yani CPU çoğu zaman boşta, GPU ise aşırı yüklü. Bu, gölgelendiricilerinizin çok ağır olduğunun kesin bir göstergesidir.

Düşük kare hızına tam olarak neyin neden olduğunu göremediyseniz, 5 Hz güncellemeyi gözlemleyip oyun koduna gidip oyun mantığını optimize etmeye veya kaldırmaya çalışmak isteyebilirsiniz. Bu durumda hiçbir işe yaramaz. Çünkü oyun döngüsündeki mantık boş zamanı yitiren şey değildir. Aslında bu iz, daha fazla CPU işi yapmanın her kare için "boş" olacağı, çünkü CPU boşta kaldığı için "boş" olacaktır. Bu nedenle, daha fazla işlem yapılması karenin süresini etkilemez.

Gerçek Örnekler

Şimdi gerçek bir oyundaki iz verilerinin nasıl göründüğüne bakalım. Açık web teknolojileriyle oluşturulan oyunların güzel yanlarından biri, en sevdiğiniz ürünlerde neler olup bittiğini görebilmenizdir. Profil oluşturma araçlarını test etmek isterseniz 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ış örnek bir izdir.

Gerçek bir oyunu takip etme
Gerçek bir oyunu takip etme

Her kare yaklaşık 20 ms sürer. Bu, kare hızının yaklaşık 50 FPS olduğu anlamına gelir. İşin CPU ile GPU arasında dengelendiğini görebilirsiniz ancak GPU, en çok talep gören kaynaktır. WebGL oyunlarına ilişkin gerçek örneklerin profilini çıkarmanın nasıl bir şey olduğunu görmek istiyorsanız WebGL ile oluşturulmuş Chrome Web Mağazası başlıklarından bazılarını deneyin. Örneğin:

Sonuç

Oyununuzun 60 Hz hızda ç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 var. Performansı en üst düzeye çıkarmak için bunlar arasındaki işi değiştirebilirsiniz. Chrome'un about:tracing görünümü, kodunuzun gerçekte ne yaptığını anlamak için paha biçilmez bir araçtır ve doğru sorunları çözerek geliştirme sürenizi en üst düzeye çıkarmanıza yardımcı olur.

Sonraki adım

GPU'nun yanı sıra Chrome çalışma zamanının diğer kısımlarını da izleyebilirsiniz. Chrome'un erken aşamadaki sürümü olan Chrome Canary IO, IndexedDB ve diğer çeşitli etkinlikleri izlemek üzere donatılmıştır. İzleme olaylarının mevcut durumu hakkında daha ayrıntılı bilgi edinmek için bu Chromium makalesini okumalısınız.

Web oyunu geliştiricisiyseniz aşağıdaki videoyu izlediğinizden emin olun. Bu, GDC 2012'de Google'ın Oyun Geliştirici Destekçisi ekibinin Chrome oyunları için performans optimizasyonuyla ilgili bir sunumudur: