Geldiğimiz nokta
Chrome, bir yıl önce Chrome DevTools'da yerel WebAssembly hata ayıklama için ilk desteği duyurmuştu.
Temel adım desteğini gösterdik ve kaynak haritalar yerine DWARF bilgilerinin kullanımının gelecekte bize sunacağı fırsatlardan bahsettik:
- Değişken adlarını çözümleme
- Şık yazdırma türleri
- Kaynak dillerdeki ifadeleri değerlendirme
- ...ve çok daha fazlası!
Bugün, vadedilen özelliklerin hayata geçtiğini ve Emscripten ve Chrome Geliştirici Araçları ekiplerinin bu yıl, özellikle de C ve C++ uygulamalarında kaydettiği ilerlemeyi göstermekten heyecan duyuyoruz.
Başlamadan önce, bunun yeni deneyimin beta sürümünün hâlâ olduğunu, tüm araçların en son sürümünü kendi sorumluluğunuzda kullanmanız gerektiğini ve herhangi bir sorunla karşılaşırsanız lütfen https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 adresinden bildirin.
Geçen seferkiyle aynı basit C örneğiyle başlayalım:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
Derlemek için en son Emscripten'i kullanırız ve hata ayıklama bilgilerini dahil etmek üzere orijinal gönderide olduğu gibi bir -g
işareti iletiriz:
emcc -g temp.c -o temp.html
Artık oluşturulan sayfayı bir yerel ana makine HTTP sunucusundan (ör. serve ile) yayınlayabilir ve en son Chrome Canary sürümünde açabiliriz.
Bu kez, Chrome Geliştirici Araçları ile entegre olan ve WebAssembly dosyasında kodlanmış tüm hata ayıklama bilgilerini anlamlandırmasına yardımcı olan bir yardımcı uzantıya da ihtiyacımız olacak. Lütfen şu bağlantıya giderek yükleyin: goo.gle/wasm-debugging-extension
DevTools Denemeler bölümünde WebAssembly hata ayıklama özelliğini de etkinleştirmeniz gerekir. Chrome Geliştirici Araçları'nı açın, DevTools bölmesinin sağ üst köşesindeki dişli (⚙) simgesini tıklayın, Deneysel paneline gidin ve WebAssembly Hata Ayıklama: DWARF desteğini etkinleştir'i işaretleyin.
Ayarlar'ı kapattığınızda DevTools, ayarları uygulamak için kendisini yeniden yüklemeyi önerir. Biz de bunu yapalım. Tek seferlik kurulum bu kadar.
Şimdi Kaynaklar paneline geri dönebilir, İstisnalarda duraklat'ı (⏸ simgesi) etkinleştirebilir, ardından Tespit edilen istisnalarda duraklat'ı işaretleyip sayfayı yeniden yükleyebiliriz. Geliştirici Araçları'nın bir istisnada duraklatıldığını göreceksiniz:
Varsayılan olarak Emscripten tarafından oluşturulan birleştirici kodda durur, ancak sağda, hatanın yığın izlemeyi temsil eden Çağrı Grubu görünümünü görebilir ve abort
komutunu çağıran orijinal C satırına gidebilirsiniz:
Artık Kapsam görünümüne bakarak C/C++ kodundaki değişkenlerin orijinal adlarını ve değerlerini görebilirsiniz. Böylece $localN
gibi bozuk adların ne anlama geldiğini ve yazdığınız kaynak kodla nasıl ilişkili olduğunu öğrenmek zorunda kalmazsınız.
Bu durum yalnızca tam sayılar gibi ilkel değerler için değil, yapı, sınıf, dizi vb. gibi karmaşık türler için de geçerlidir.
Zengin tür desteği
Bu noktaları açıklamak için daha karmaşık bir örneğe bakalım. Bu kez, aşağıdaki C++ kodunu kullanarak bir Mandelbrot fraktal çizeceğiz:
#include <SDL2/SDL.h>
#include <complex>
int main() {
// Init SDL.
int width = 600, height = 600;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window;
SDL_Renderer* renderer;
SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
&renderer);
// Generate a palette with random colors.
enum { MAX_ITER_COUNT = 256 };
SDL_Color palette[MAX_ITER_COUNT];
srand(time(0));
for (int i = 0; i < MAX_ITER_COUNT; ++i) {
palette[i] = {
.r = (uint8_t)rand(),
.g = (uint8_t)rand(),
.b = (uint8_t)rand(),
.a = 255,
};
}
// Calculate and draw the Mandelbrot set.
std::complex<double> center(0.5, 0.5);
double scale = 4.0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::complex<double> point((double)x / width, (double)y / height);
std::complex<double> c = (point - center) * scale;
std::complex<double> z(0, 0);
int i = 0;
for (; i < MAX_ITER_COUNT - 1; i++) {
z = z * z + c;
if (abs(z) > 2.0)
break;
}
SDL_Color color = palette[i];
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawPoint(renderer, x, y);
}
}
// Render everything we've drawn to the canvas.
SDL_RenderPresent(renderer);
// SDL_Quit();
}
Bu uygulamanın hâlâ oldukça küçük olduğunu (50 satır kod içeren tek bir dosya) görebilirsiniz. Ancak bu sefer grafikler için SDL kitaplığı ve C++ standart kitaplığındaki karmaşık sayılar gibi bazı harici API'leri de kullanıyorum.
Hata ayıklama bilgilerini içermesi için yukarıdakiyle aynı -g
işaretiyle derleyeceğim. Ayrıca Emscripten'den SDL2 kitaplığını sağlamasını ve rastgele boyutlu belleğe izin vermesini isteyeceğim:
emcc -g mandelbrot.cc -o mandelbrot.html \ -s USE_SDL=2 \ -s ALLOW_MEMORY_GROWTH=1
Oluşturulan sayfayı tarayıcıda ziyaret ettiğimde, rastgele renklerle güzel kesirli şekli görebiliyorum:
Geliştirici Araçları'nı tekrar açtığımda orijinal C++ dosyasını görebiliyorum. Ancak bu sefer kodda hata yok (oh be!). Bunun yerine kodumuzun başına bir kesme noktası koyalım.
Sayfayı tekrar yüklediğimizde hata ayıklayıcı, C++ kaynağımızın tam içinde duraklar:
Tüm değişkenlerimizi sağ tarafta görebiliriz ancak şu anda yalnızca width
ve height
başlatılmıştır. Bu nedenle, incelenecek çok fazla şey yoktur.
Ana Mandelbrot döngümüzün içine başka bir ayrılma noktası ayarlayalım ve biraz daha ileri atlamak için yürütme işlemine devam edelim.
Bu noktada palette
aracımız rastgele renklerle dolduruldu. Hem diziyi hem de bağımsız SDL_Color
yapılarını genişletip her şeyin iyi göründüğünü doğrulamak için bileşenlerini inceleyebiliriz (örneğin, "alfa" kanalı her zaman tam opaklığa ayarlanır). Benzer şekilde, center
değişkeninde depolanan karmaşık sayının reel ve sanal bölümlerini genişletip kontrol edebiliriz.
Kapsam görünümü aracılığıyla erişmesi zor olan, derin iç içe yerleştirilmiş bir mülke erişmek istiyorsanız Console değerlendirmesini de kullanabilirsiniz. Ancak daha karmaşık C++ ifadelerinin henüz desteklenmediğini unutmayın.
Yürütmeye birkaç kez devam edelim. Kapsam görünümüne tekrar bakarak, değişken adını izleme listesine ekleyerek, konsolda değerlendirerek veya fareyle kaynak kodda değişkenin üzerine gelerek iç x
öğesinin nasıl değiştiğini görebiliriz:
Buradan C++ ifadelerine adım atabilir veya adım atlayabilir ve diğer değişkenlerin nasıl değiştiğini gözlemleyebiliriz:
Hata ayıklama bilgileri mevcut olduğunda bu yöntemler mükemmel şekilde çalışır. Peki, hata ayıklama seçenekleriyle derlenmemiş bir kodda hata ayıklama yapmak istersek ne olur?
Ham WebAssembly hata ayıklama
Örneğin, Emscripten'den bizim için önceden oluşturulmuş bir SDL kitaplığı sunmasını istedik. Bu kitaplığı kendi kaynağından derlemek yerine şu anda hata ayıklayıcının ilişkili kaynakları bulmasının bir yolu yok.
SDL_RenderDrawColor
'e girmek için tekrar başlayalım:
Ham WebAssembly hata ayıklama deneyimine geri döndük.
Bu biraz korkutucu olabilir ve çoğu Web geliştiricisinin hiçbir zaman uğraşması gerekmeyecektir. Ancak zaman zaman, hata ayıklama bilgileri olmadan oluşturulmuş bir kitaplıkta hata ayıklamak isteyebilirsiniz. Bu, kontrolünüzün olmadığı üçüncü bir taraf kitaplığı veya yalnızca üretim aşamasında ortaya çıkan hatalardan biriyle karşılaştığınız için olabilir.
Bu durumlarda yardımcı olmak için temel hata ayıklama deneyiminde de bazı iyileştirmeler yaptık.
Öncelikle, daha önce ham WebAssembly hata ayıklama özelliğini kullandıysanız artık tüm kod ayrıştırmasının tek bir dosyada gösterildiğini fark edebilirsiniz. Artık wasm-53834e3e/
wasm-53834e3e-7
Kaynaklar girişinin hangi işleve karşılık geldiğini tahmin etmeniz gerekmez.
Yeni ad oluşturma şeması
Demonte görünümündeki adları da iyileştirdik. Daha önce yalnızca sayısal dizinler veya işlevler söz konusu olduğunda hiç ad gösterilmiyordu.
Artık WebAssembly ad bölümündeki ipuçlarını, içe/dışa aktarma yollarını kullanarak ve diğer tüm yöntemler başarısız olursa $func123
gibi öğenin türüne ve dizine göre adları diğer disassemblör araçlarına benzer şekilde oluşturuyoruz. Yukarıdaki ekran görüntüsünde, bu durumun biraz daha okunaklı yığın izleme ve kod ayıklama bilgilerine nasıl yardımcı olduğunu görebilirsiniz.
Tür bilgisi olmadığında, ilkellerin dışındaki değerleri incelemek zor olabilir. Örneğin, işaretçiler normal tam sayılar olarak gösterilir ve bellekte arkalarında nelerin depolandığını bilmek mümkün olmaz.
Bellek denetimi
Daha önce, tek tek baytları aramak için yalnızca Kapsam görünümünde env.memory
ile temsil edilen WebAssembly bellek nesnesini genişletebiliyordunuz. Bu, bazı basit senaryolarda işe yaradı ancak genişletme açısından özellikle uygun değildi ve verilerin bayt değerleri dışındaki biçimlerde yeniden yorumlanmasına izin vermiyordu. Bu konuda size yardımcı olacak yeni bir özellik de ekledik: doğrusal bellek denetleyicisi.
env.memory
simgesini sağ tıkladığınızda Hafızayı incele adlı yeni bir seçenek görürsünüz:
Tıklandığında, WebAssembly belleğini onaltılık ve ASCII görünümlerinde inceleyebileceğiniz, belirli adreslere gidebileceğiniz ve verileri farklı biçimlerde yorumlayabileceğiniz bir Bellek Denetleyicisi açılır:
Gelişmiş senaryolar ve uyarılar
WebAssembly kodunda profil oluşturma
Geliştirici Araçları'nı açtığınızda WebAssembly kodu, hata ayıklamayı etkinleştirmek için optimize edilmemiş bir sürüme "indirilir". Bu sürüm çok daha yavaştır. Bu nedenle, DevTools açıkken console.time
, performance.now
ve diğer kod hız ölçüm yöntemlerine güvenemezsiniz. Elde ettiğiniz sayılar gerçek dünya performansını hiç yansıtmaz.
Bunun yerine, kodu tam hızda çalıştıran ve farklı işlevlerde harcanan sürenin ayrıntılı bir dökümünü sunan Geliştirici Araçları Performans panelini kullanmanız gerekir:
Alternatif olarak, uygulamanızı Geliştirici Araçları kapalıyken çalıştırabilir ve işiniz bittiğinde Konsolu incelemek için bu araçları açabilirsiniz.
Profil oluşturma senaryolarını gelecekte iyileştireceğiz ancak şimdilik bu konuda dikkatli olmanız gerekiyor. WebAssembly katmanlandırma senaryoları hakkında daha fazla bilgi edinmek isterseniz WebAssembly derleme ardışık düzeni ile ilgili dokümanlarımıza göz atın.
Farklı makinelerde (Docker / ana makine dahil) derleme ve hata ayıklama
Docker, sanal makine veya uzak derleme sunucusunda derleme yaparken, derleme sırasında kullanılan kaynak dosyalarına giden yolların, Chrome Geliştirici Araçları'nın çalıştığı kendi dosya sisteminizdeki yollarla eşleşmediği durumlarla karşılaşabilirsiniz. Bu durumda, dosyalar Kaynaklar panelinde gösterilir ancak yüklenemez.
Bu sorunu düzeltmek için C/C++ uzantı seçeneklerine bir yol eşleme işlevi uyguladık. İsteğe bağlı yolları yeniden eşlemek ve DevTools'un kaynakları bulmasına yardımcı olmak için bu seçeneği kullanabilirsiniz.
Örneğin, ana makinenizdeki proje C:\src\my_project
yolunun altındaysa ancak bu yolun /mnt/c/src/my_project
olarak temsil edildiği bir Docker kapsayıcısında derlendiyse bu yolları ön ek olarak belirterek hata ayıklama sırasında yeniden eşleyebilirsiniz:
Eşleşen ilk ön ek "kazanır". Diğer C++ hata ayıklayıcılarını biliyorsanız bu seçenek, GDB'deki set substitute-path
komutuna veya LLDB'deki target.source-map
ayarına benzer.
Optimize edilmiş derlemelerde hata ayıklama
Diğer tüm dillerde olduğu gibi, optimizasyonlar devre dışı bırakılırsa hata ayıklama en iyi şekilde çalışır. Optimizasyonlar, işlevleri birbirine satır içi olarak yerleştirebilir, kodu yeniden sıralayabilir veya kod parçalarını tamamen kaldırabilir. Tüm bunların hata ayıklayıcıyı ve dolayısıyla kullanıcı olarak sizi şaşırtma olasılığı vardır.
Daha sınırlı bir hata ayıklama deneyimi sizi rahatsız etmiyorsa ve yine de optimize edilmiş bir derlemede hata ayıklama yapmak istiyorsanız işlev iç içe yerleştirme dışındaki optimizasyonların çoğu beklendiği gibi çalışır. Kalan sorunları gelecekte ele almayı planlıyoruz ancak şimdilik -O
düzeyinde optimizasyonlarla derleme yaparken devre dışı bırakmak için lütfen -fno-inline
kullanın. Örneğin:
emcc -g temp.c -o temp.html \ -O3 -fno-inline
Hata ayıklama bilgilerini ayırma
Hata ayıklama bilgileri, kodunuz, tanımlanmış türler, değişkenler, işlevler, kapsamlar ve konumlar (hata ayıklayıcı için yararlı olabilecek her şey) hakkında birçok ayrıntıyı korur. Sonuç olarak, genellikle kodun kendisinden daha büyük olabilir.
WebAssembly modülünün yükleme ve derleme işlemini hızlandırmak için bu hata ayıklama bilgilerini ayrı bir WebAssembly dosyasına ayırabilirsiniz. Emscripten'de bunu yapmak için istenen dosya adıyla birlikte bir -gseparate-dwarf=…
işareti iletin:
emcc -g temp.c -o temp.html \ -gseparate-dwarf=temp.debug.wasm
Bu durumda, ana uygulama yalnızca bir dosya adı temp.debug.wasm
depolar ve yardımcı uzantı, DevTools'u açtığınızda dosyayı bulup yükleyebilir.
Yukarıda açıklanan optimizasyonlarla birlikte kullanıldığında bu özellik, uygulamanızın neredeyse optimize edilmiş üretim derlemelerini göndermek ve daha sonra yerel taraftaki bir dosyayla bu derlemelerde hata ayıklama yapmak için bile kullanılabilir. Bu durumda, uzantının yan dosyayı bulmasına yardımcı olmak için saklanan URL'yi de geçersiz kılmamız gerekir. Örneğin:
emcc -g temp.c -o temp.html \ -O3 -fno-inline \ -gseparate-dwarf=temp.debug.wasm \ -s SEPARATE_DWARF_URL=file://[local path to temp.debug.wasm]
Devam etmek için...
Vay canına, bir sürü yeni özellik sunduk.
Tüm bu yeni entegrasyonlarla Chrome Geliştirici Araçları, yalnızca JavaScript için değil, C ve C++ uygulamaları için de geçerli, güçlü ve kullanışlı bir hata ayıklayıcı haline gelir. Böylece, çeşitli teknolojilerde geliştirilen uygulamaları paylaşılan, platformlar arası bir web'e taşımak hiç olmadığı kadar kolay hale gelir.
Ancak yolculuğumuz henüz sona ermedi. Bundan sonra üzerinde çalışacağımız bazı konular:
- Hata ayıklama deneyimindeki pürüzleri giderme.
- Özel tür biçimlendiricileri için destek eklendi.
- WebAssembly uygulamaları için profil oluşturma özelliğinde iyileştirmeler üzerinde çalışıyoruz.
- Kullanılmayan kodun bulunmasını kolaylaştırmak için kod kapsamı desteği eklendi.
- Konsolda değerlendirme için ifadelere yönelik destek iyileştirildi.
- Daha fazla dil için destek ekliyoruz.
- …ve daha fazlası!
Bu sırada, mevcut beta sürümünü kendi kodunuzda deneyerek ve karşılaştığınız sorunları https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 adresinden bildirerek bize yardımcı olabilirsiniz.
Önizleme kanallarını indirme
Chrome Canary, Yeni geliştirilenler veya Beta'yı varsayılan geliştirme tarayıcınız olarak kullanabilirsiniz. Bu önizleme kanalları, en son DevTools özelliklerine erişmenizi sağlar, en yeni web platformu API'lerini test etmenize olanak tanır ve sitenizdeki sorunları kullanıcılarınızdan önce bulmanıza yardımcı olur.
Chrome Geliştirici Araçları Ekibi ile iletişime geçme
Yeni özellikleri, güncellemeleri veya Geliştirici Araçları ile ilgili diğer konuları görüşmek için aşağıdaki seçenekleri kullanın.
- crbug.com adresinden bize geri bildirim ve özellik isteği gönderin.
- Geliştirici Araçları'ndaki Diğer seçenekler > Yardım > Geliştirici Araçları sorunu bildir bölümüne giderek Geliştirici Araçları sorunlarını bildirin.
- @ChromeDevTools hesabına tweet gönderin.
- Geliştirici Araçları'ndaki yenilikler veya Geliştirici Araçları'yla ilgili ipuçları konulu YouTube videolarına yorum bırakın.