Chrome Dev Summit 2020'de web'deki Chrome'un WebAssembly uygulamaları için hata ayıklama desteğini ilk kez tanıttık. O zamandan beri ekip, geliştirici deneyimini büyük ve hatta çok büyük uygulamalara ölçeklendirmek için büyük miktarda enerji harcadı. Bu yayında, farklı araçlara eklediğimiz (veya yaptığımız) düğmeleri ve bunları nasıl kullanacağınızı göstereceğiz!
Ölçeklenebilir hata ayıklama
2020 gönderimizde kaldığımız yerden devam edelim. İşte o zaman incelediğimiz örnek:
#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 hâlâ oldukça küçük bir örnektir ve büyük bir uygulamada karşılaşacağınız gerçek sorunların hiçbirini büyük olasılıkla görmezsiniz. Yine de size yeni özelliklerin neler olduğunu gösterebiliriz. Kurulumu hızlı ve kolaydır. Üstelik kendiniz de deneyebilirsiniz.
Son yayında, bu örneğin nasıl derleneceği ve hata ayıklanacağı anlatılmıştır. Bunu tekrar yapalım, ancak //performance// bölümüne de göz atalım:
$ emcc -sUSE_SDL=2 -g -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH
Bu komut, 3 MB'lık bir wasm ikili programı oluşturur. Tahmin edebileceğiniz gibi, bunların büyük kısmı hata ayıklama bilgileridir. Bunu llvm-objdump
aracını [1] kullanarak doğrulayabilirsiniz. Örneğin:
$ llvm-objdump -h mandelbrot.wasm
mandelbrot.wasm: file format wasm
Sections:
Idx Name Size VMA Type
0 TYPE 0000026f 00000000
1 IMPORT 00001f03 00000000
2 FUNCTION 0000043e 00000000
3 TABLE 00000007 00000000
4 MEMORY 00000007 00000000
5 GLOBAL 00000021 00000000
6 EXPORT 0000014a 00000000
7 ELEM 00000457 00000000
8 CODE 0009308a 00000000 TEXT
9 DATA 0000e4cc 00000000 DATA
10 name 00007e58 00000000
11 .debug_info 000bb1c9 00000000
12 .debug_loc 0009b407 00000000
13 .debug_ranges 0000ad90 00000000
14 .debug_abbrev 000136e8 00000000
15 .debug_line 000bb3ab 00000000
16 .debug_str 000209bd 00000000
Bu çıkış, oluşturulan wasm dosyasındaki tüm bölümleri gösterir. Bunların çoğu standart WebAssembly bölümleridir ancak adı .debug_
ile başlayan birkaç özel bölüm de mevcuttur. İkili programın hata ayıklama bilgilerimizi barındırdığı yer burasıdır. Tüm boyutları topladığımızda, hata ayıklama bilgilerinin 3 MB'lık dosyamızın yaklaşık 2,3 MB'ını oluşturduğunu görürüz. emcc
komutunu da time
işlemini gerçekleştirirsek makinemizde çalışmasının yaklaşık 1, 5 saniye sürdüğünü görürüz. Bu sayılar küçük bir referans noktası olabilir, ancak o kadar küçüktür ki kimse bu rakamlara çarpmayacaktır. Ancak gerçek uygulamalarda, hata ayıklama ikili programı GB cinsinden bir boyuta kolayca ulaşabilir ve birkaç dakika içinde oluşturabilir.
Binaryen'i atlama
Emscripten ile bir wasm uygulaması oluştururken, uygulamanın son derleme adımlarından biri Binaryen optimize ediciyi çalıştırmaktır. Binaryen, WebAssembly gibi ikili programları hem optimize eden hem de yasal hâle getiren bir derleyici araç setidir. Binaryen'in derlemenin bir parçası olarak çalıştırılması oldukça pahalıdır, ancak bunun yalnızca belirli koşullarda yapılması gerekir. Hata ayıklama derlemelerinde Binaryen kartlarına gerek kalmazsa derleme süresini önemli ölçüde kısaltabiliriz. En yaygın olarak kullanılan İkili Geçiş geçişi, 64 bit tam sayı değerleri içeren işlev imzalarını yasallaştırmak içindir. -sWASM_BIGINT
kullanarak WebAssembly BigInt entegrasyonunu etkinleştirerek bunu önleyebiliriz.
$ emcc -sUSE_SDL=2 -g -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK
İyi bir önlem olarak -sERROR_ON_WASM_CHANGES_AFTER_LINK
işaretini attık. Binaryen'in çalıştığı ve ikili dosyayı beklenmedik bir şekilde yeniden yazdığı durumların tespit edilmesine yardımcı olur. Bu şekilde, hızlı yoldan ilerleyeceğimizden emin olabiliriz.
Örneğimiz oldukça küçük olsa da Binaryen'i atlamanın etkisini görebiliriz. time
adlı kaynağa göre bu komut 1 saniyenin biraz altında çalıştığından yarım saniye daha hızlıdır!
Gelişmiş ince ayarlar
Giriş dosyası taraması atlanıyor
Normalde bir Emscripten projesi bağlanırken emcc
, tüm giriş nesnesi dosyalarını ve kitaplıklarını tarar. Bunu, programınızdaki JavaScript kitaplık işlevleri ile yerel simgeler arasında kesin bağımlılıklar uygulamak için yapar. Daha büyük projelerde, giriş dosyalarının llvm-nm
kullanılarak bu şekilde ek tarama yapılması bağlantı süresini önemli ölçüde uzatabilir.
Bunun yerine, emcc
öğesine JavaScript işlevlerinin tüm olası yerel bağımlılıklarını dahil etmesini bildiren -sREVERSE_DEPS=all
ile çalıştırılabilir. Bunun küçük bir kod boyutu ek yüküne neden olur ancak bağlantı sürelerini kısaltabilir ve hata ayıklama derlemelerinde faydalı olabilir.
Örneğimiz kadar küçük bir proje için bu durum hiçbir fark yaratmaz ancak projenizde yüzlerce, hatta binlerce nesne dosyası varsa bağlantı süreleri anlamlı bir şekilde kısaltılabilir.
“Ad” bölümünü kaldırma
Büyük projelerde, özellikle de çok fazla C++ şablonu kullananlar için WebAssembly “adı” bölümü çok büyük olabilir. Örneğimizde bu, toplam dosya boyutunun küçük bir kısmıdır (yukarıdaki llvm-objdump
çıkışına bakın), ancak bazı durumlarda çok önemli olabilir. Uygulamanızın “ad” bölümü çok büyükse ve cüce hata ayıklama bilgileri hata ayıklama ihtiyaçlarınız için yeterliyse “ad” bölümünün kaldırılması avantajlı olabilir:
$ emstrip --no-strip-all --remove-section=name mandelbrot.wasm
Bu işlem, DWARF hata ayıklama bölümlerini korurken WebAssembly "name" bölümünü kaldırır.
Fisyonda hata ayıklama
Çok sayıda hata ayıklama verisi içeren ikili programlar, yalnızca derleme süresini değil, hata ayıklama süresini de etkiler. Hata ayıklayıcının verileri yüklemesi ve "X yerel değişkeninin türü nedir?" gibi sorgulara hızlı bir şekilde yanıt verebilmesi için, verilere yönelik bir dizin oluşturması gerekir.
Hata ayıklama fisyonu, bir ikili programın hata ayıklama bilgilerini iki bölüme ayırmamızı sağlar: biri ikili programda kalan, diğeri ise DWARF nesnesi (.dwo
) adlı ayrı bir dosyada bulunan parça. -gsplit-dwarf
işareti Emscripten'a geçirilerek etkinleştirilebilir:
$ emcc -sUSE_SDL=2 -g -gsplit-dwarf -gdwarf-5 -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK
Aşağıda, farklı komutları ve hata ayıklama verileri olmadan, hata ayıklama verileriyle ve son olarak hem hata ayıklama verileri hem de hata ayıklama fisyonuyla derlenerek hangi dosyaların oluşturulduğu gösterilmektedir.
DWARF verileri bölünürken hata ayıklama verilerinin bir kısmı ikili programla birlikte tutulurken büyük bölümü mandelbrot.dwo
dosyasına yerleştirilir (yukarıda gösterildiği gibi).
mandelbrot
için yalnızca bir kaynak dosyamız var, ancak genellikle projeler bundan büyüktür ve birden fazla dosya içerir. Hata ayıklama fisyonu, her biri için bir .dwo
dosyası oluşturur. Hata ayıklayıcının mevcut beta sürümünün (0.1.6.1615) bu bölme hata ayıklama bilgilerini yükleyebilmesi için hepsini aşağıdaki gibi DWARF paketi (.dwp
) adı verilen bir pakette toplamamız gerekir:
$ emdwp -e mandelbrot.wasm -o mandelbrot.dwp
DWARF paketini tek tek nesnelerden oluşturmak, yalnızca bir ekstra dosya sunmanızın gerekeceği avantajıdır! Şu anda, gelecekteki bir sürümde tüm nesneleri tek tek yüklemek için çalışıyoruz.
DWARF 5'in içeriği nedir?
Yukarıdaki emcc
komutuna başka bir bayrak yerleştirdiğimizi fark etmiş olabilirsiniz: -gdwarf-5
. DWARF simgelerinin şu anda varsayılan olmayan sürüm 5'ini etkinleştirmek, hata ayıklama işlemini daha hızlı başlatmamıza yardımcı olacak başka bir ipucudur. Bu algoritma ile belirli bilgiler, varsayılan sürüm 4'ün dışarıda bıraktığı ana ikili programda depolanır. Özellikle, kaynak dosyaların tamamını yalnızca ana ikili programdan belirleyebiliriz. Bu, hata ayıklayıcının, tam simge verilerini yüklemeden ve ayrıştırmadan, kaynak ağacının tamamını göstermek ve ayrılma noktalarını ayarlamak gibi temel işlemleri yapmasına olanak tanır. Bu, bölme simgeleriyle hata ayıklamayı çok daha hızlı hale getirir. Böylece, her zaman -gsplit-dwarf
ve -gdwarf-5
komut satırı işaretlerini birlikte kullanırız!
DWARF5 hata ayıklama biçimiyle başka bir faydalı özelliğe de erişim elde ederiz. Hata ayıklama verilerinde, -gpubnames
işareti iletildiğinde oluşturulacak bir ad dizini sunar:
$ emcc -sUSE_SDL=2 -g -gdwarf-5 -gsplit-dwarf -gpubnames -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK
Hata ayıklama oturumu sırasında sembol aramaları genellikle bir varlığı ada göre arayarak (ör. değişken veya tür ararken) gerçekleşir. Ad dizini, doğrudan söz konusu adı tanımlayan derleme birimine işaret ederek bu aramayı hızlandırır. Ad dizini olmadan, aradığımız adlandırılmış varlığı tanımlayan doğru derleme birimini bulmak için hata ayıklama verilerinin tamamında kapsamlı bir arama yapılması gerekir.
Meraklılar için: Hata ayıklama verilerine göz atma
DWARF verilerine göz atmak için llvm-dwarfdump
kullanabilirsiniz. Bir deneme yapalım:
llvm-dwarfdump mandelbrot.wasm
Bu, hata ayıklama bilgilerine sahip olduğumuz "Birimleri derle" (kabaca kaynak dosyalar) ile ilgili bir genel bakış sağlar. Bu örnekte yalnızca mandelbrot.cc
için hata ayıklama bilgileri mevcuttur. Verilen genel bilgiler bize bir iskelet birimimiz olduğunu bildirecektir. Bu, dosyada eksik veriler olduğu ve kalan hata ayıklama bilgilerini içeren ayrı bir .dwo
dosyası olduğu anlamına gelir:
Bu dosyadaki diğer tablolara da bakabilirsiniz. Örneğin, wasm bayt kodunun C++ satırlarıyla eşlenmesini gösteren satır tablosu (llvm-dwarfdump -debug-line
kullanmayı deneyin).
Ayrı .dwo
dosyasında bulunan hata ayıklama bilgilerine de göz atabiliriz:
llvm-dwarfdump mandelbrot.dwo
Özet: Hata ayıklama fisyonu kullanmanın avantajı nedir?
Büyük uygulamalarla çalışan bir hata ayıklama bilgilerini bölmenin birçok avantajı vardır:
Daha hızlı bağlama: Bağlayıcının artık hata ayıklama bilgilerinin tamamını ayrıştırmasına gerek yoktur. Bağlayıcıların genellikle ikili programdaki DWARF verilerinin tamamını ayrıştırması gerekir. Bağlayıcılar, hata ayıklama bilgilerinin büyük bölümlerini ayrı dosyalar halinde çıkararak daha küçük ikili programlarla ilgilenir. Bu da daha kısa bağlantı sürelerine neden olur (özellikle büyük uygulamalar için geçerlidir).
Daha hızlı hata ayıklama: Hata ayıklayıcı, bazı simge aramaları için
.dwo
/.dwp
dosyalarındaki ek simgeleri ayrıştırmayı atlayabilir. Bazı aramalarda (ör. wasm-to-C++ dosyalarının satır eşlemesiyle ilgili istekler) ek hata ayıklama verilerini incelememiz gerekmez. Bu bize zaman kazandırır ve ek hata ayıklama verilerini yükleyip ayrıştırmamıza gerek kalmaz.
1: Sisteminizde llvm-objdump
uygulamasının yeni bir sürümü yoksa ve emsdk
kullanıyorsanız bu sürümü emsdk/upstream/bin
dizininde bulabilirsiniz.
Önizleme kanallarını indirme
Varsayılan geliştirme tarayıcınız olarak Chrome Canary, Yeni geliştirilenler veya Beta'yı kullanmayı düşünün. Bu önizleme kanallarıyla Geliştirici Araçları'nın en yeni özelliklerine erişebilir, son teknoloji ürünü web platformu API'lerini test edebilir ve sitenizdeki sorunları kullanıcılarınızdan önce tespit edebilirsiniz!
Chrome Geliştirici Araçları ekibiyle iletişim kurma
Yayındaki yeni özellikler ve değişiklikler ya da Geliştirici Araçları ile ilgili diğer konular hakkında konuşmak için aşağıdaki seçenekleri kullanın.
- crbug.com adresinden öneri veya geri bildirim gönderin.
- Geliştirici Araçları'nda, Diğer seçenekler > Yardım > Geliştirici Araçları sorunu bildir'i kullanarak Geliştirici Araçları sorunlarını bildirin.
- @ChromeDevTools adresine tweet gönderin.
- Geliştirici Araçları'ndaki YouTube videoları veya Geliştirici Araçları İpuçları YouTube videolarındaki yenilikler hakkındaki görüşlerinizi bizimle paylaşın.