Der Weg bisher
Vor einem Jahr wurde in Chrome die erste Unterstützung angekündigt für natives WebAssembly-Debugging in den Chrome-Entwicklertools.
Wir haben grundlegende Unterstützung bei den Schritten gezeigt und über Chancen gesprochen Verwendung von DWARF-Informationen anstelle von Quellzuordnungen zukünftig für uns geöffnet:
- Variablennamen auflösen
- Quelltextformatierungen
- Ausdrücke in den Ausgangssprachen auswerten
- ...und vieles mehr!
Heute möchten wir zeigen, wie die versprochenen Funktionen und die Fortschritte der Emscripten- und Chrome DevTools-Teams insbesondere für C- und C++-Apps.
Bevor wir beginnen, möchte ich noch einmal darauf hinweisen, dass dies eine Betaversion ist. der neuen Version müssen Sie die aktuelle Version aller Tools verwenden. auf dein eigenes Risiko. Sollten Probleme auftreten, melde sie bitte https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.
Beginnen wir mit demselben einfachen C-Beispiel wie beim letzten Mal:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
Zur Kompilierung verwenden wir die neueste Emscripten-Version.
und übergeben Sie wie im ursprünglichen Beitrag ein -g
-Flag, um
Informationen:
emcc -g temp.c -o temp.html
Jetzt können wir die generierte Seite von einem localhost-HTTP-Server (für Beispiel, mit serve) und öffnen Sie sie in der aktuellen Version von Chrome Canary.
Dieses Mal benötigen wir auch eine Hilfserweiterung, die in die Chrome DevTools eingebunden ist und dabei hilft, alle in der WebAssembly-Datei codierten Informationen zur Fehlerbehebung zu verstehen. Installieren Sie sie hier: Link: goo.gle/wasm-debugging-extension
Sie sollten auch das WebAssembly-Debugging in den Entwicklertools aktivieren Experimentelle Funktionen: Öffnen Sie die Chrome-Entwicklertools, klicken Sie in der Symbolleiste auf das Zahnradsymbol (⚙) Gehen Sie rechts oben im Bereich „Entwicklertools“ zum Bereich Tests. und wählen Sie WebAssembly Debugging: Enable DWARF support (WebAssembly-Debugging: DWARF-Unterstützung aktivieren) aus.
Wenn du die Einstellungen schließt, schlägt die Entwicklertools vor, sich selbst zu aktualisieren um Einstellungen anzuwenden. Damit ist die einmalige Einrichtung abgeschlossen.
Jetzt können wir zum Bereich Quellen zurückkehren und die Option Pausieren am Ausnahmen (⏸-Symbol) und aktivieren Sie dann Bei erkannten Ausnahmen pausieren und aktualisieren Sie die Seite. Die Entwicklertools sollten bei einer Ausnahme pausiert sein:
Standardmäßig stoppt er bei einem von Emscripten generierten Glue Code, aber auf der
sehen Sie einen Aufrufstack, der den Stacktrace von
Fehler aus und können zur ursprünglichen C-Zeile navigieren,
abort
:
Wenn Sie jetzt in der Ansicht Scope (Umfang) nachsehen, sehen Sie die ursprünglichen Namen und Werte der Variablen im C/C++-Code. Sie müssen also nicht mehr herausfinden, was unleserliche Namen wie $localN
bedeuten und in welcher Beziehung sie zum von Ihnen geschriebenen Quellcode stehen.
Dies gilt nicht nur für primitive Werte wie Ganzzahlen, sondern auch für Typen wie Strukturen, Klassen, Arrays usw. anwenden.
Rich-Type-Unterstützung
Sehen wir uns dazu ein etwas komplizierteres Beispiel an. Dieses zeichnen wir ein Mandelbrot-Faktal mit der folgenden C++ Code:
#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();
}
Wie Sie sehen, ist diese Anwendung immer noch recht klein, mit 50 Zeilen Code. Dieses Mal verwende ich aber auch externe APIs wie die SDL-Bibliothek für Grafiken sowie komplexe Zahlen aus der C++-Standardbibliothek.
Ich werde sie mit demselben -g
-Flag wie oben kompilieren,
und bitte Emscripten, die SDL2-Datei
und Arbeitsspeicher mit beliebiger Größe zulassen:
emcc -g mandelbrot.cc -o mandelbrot.html \ -s USE_SDL=2 \ -s ALLOW_MEMORY_GROWTH=1
Wenn ich die generierte Seite im Browser aufrufe, fraktale Form mit einigen zufälligen Farben:
Wenn ich die Entwicklertools wieder öffne, sehe ich die ursprüngliche C++-Datei. Dieses Allerdings haben wir keinen Fehler im Code (Puh!), also legen wir einen Haltepunkt am Anfang des Codes.
Wenn wir die Seite erneut laden, pausiert der Debugger direkt im C++-Quelle:
Auf der rechten Seite sind bereits alle Variablen zu sehen, aber nur width
und height
initialisiert sind, sodass nicht viel
prüfen.
Legen wir einen weiteren Haltepunkt in unserer Hauptschleife für den Mandelbrot-Algorithmus fest und fahren wir fort, um ein wenig vorzuspringen.
Wir haben palette
mit zufälligen Farben gefüllt,
Wir können sowohl das Array selbst
als auch die einzelnen Elemente erweitern,
SDL_Color
aufgebaut und ihre Komponenten überprüft, um sicherzustellen,
alles in Ordnung ist (z. B. ist der Kanal "Alpha" immer
volle Deckkraft). Auf ähnliche Weise können wir die realen und
imaginären Teile der komplexen Zahl, die in der Variablen center
gespeichert sind.
Wenn Sie auf eine tief verschachtelte Property zugreifen möchten, die über die Ansicht Umfang nur schwer zu finden ist, können Sie auch die Console verwenden. Beachten Sie jedoch, dass komplexere C++-Ausdrücke keine unterstützt.
Führen wir die Ausführung noch ein paar Mal fort, um zu sehen, wie sich auch die innere x
ändert. Dazu können wir entweder noch einmal in der Ansicht Scope nachsehen, den Variablennamen der Beobachtungsliste hinzufügen, ihn in der Konsole auswerten oder den Mauszeiger im Quellcode auf die Variable bewegen:
Von hier aus können wir Step-in- oder Step-over-Anweisungen andere Variablen ändern sich ebenfalls:
Okay, das klappt gut, wenn Debug-Informationen verfügbar sind. was ist, wenn wir Fehler in einem Code beheben möchten, der nicht mit dem Debugging-Tool erstellt wurde, Optionen?
Raw-WebAssembly-Debugging
Beispielsweise haben wir Emscripten gebeten, eine vordefinierte SDL-Bibliothek für
Anstatt sie aus der Quelle selbst zusammenzustellen,
derzeit kann der Debugger die zugehörigen Quellen nicht finden.
Lassen Sie uns noch einmal einsteigen, um in den SDL_RenderDrawColor
einzusteigen:
Jetzt haben wir wieder das Debugging mit WebAssembly.
Es sieht jetzt etwas beängstigend aus und ist für die meisten Webentwickler nicht relevant. mit denen Sie sich befassen müssen, aber gelegentlich möchten Sie Fehler ohne Informationen zur Fehlerbehebung erstellt wurde – Drittanbieter-Bibliothek, die Sie nicht steuern können, oder weil Sie auf einen dieser Fehler stößt, der nur in der Produktion auftritt.
Um Ihnen in diesen Fällen zu helfen, haben wir auch einige Verbesserungen am grundlegenden Debugging vorgenommen.
Wenn Sie schon einmal das Debugging von Roh-WebAssembly verwendet haben, werden Sie feststellen, dass die gesamte Deassemblage jetzt in einer einzigen Datei angezeigt wird. Sie müssen also nicht mehr raten, welcher Funktion ein Eintrag wasm-53834e3e/
wasm-53834e3e-7
unter Quellen möglicherweise entspricht.
Neues Schema zur Namensgenerierung
Außerdem haben wir die Namen in der Demontageansicht verbessert. Bisher wurden diese nur numerische Indizes oder, im Fall von Funktionen, überhaupt keinen Namen.
Jetzt generieren wir Namen ähnlich wie bei
anderen Werkzeugen zum Auseinandernehmen,
mithilfe von Hinweisen aus dem Abschnitt mit WebAssembly-Namen
Import/Export von Pfaden und, falls alles andere fehlschlägt,
basierend auf dem Typ und dem Index des Elements
wie z. B. $func123
. Sie können
Wie im Screenshot oben gezeigt,
Stacktraces und deren
Demontage besser lesbar sind.
Wenn keine Typinformationen verfügbar sind, ist der Zugriff möglicherweise schwierig. alle Werte außer den Primitiven, z. B. werden Zeiger angezeigt, als reguläre Ganzzahlen, ohne zu wissen, was in den Daten zu speichern.
Arbeitsspeicherprüfung
Bisher konnten Sie nur das Speicherobjekt WebAssembly maximieren, das in der Ansicht Bereich durch env.memory
dargestellt wird, um nachzuschlagen.
einzelne Byte. Dies funktionierte zwar in einigen simplen Szenarien,
ist besonders praktisch zu erweitern und ließen Daten nicht neu interpretieren
in anderen Formaten als Byte-Werten. Wir haben eine neue Funktion hinzugefügt,
mit diesem linearen Arbeitsspeicher-Prüftool.
Wenn Sie mit der rechten Maustaste auf das env.memory
klicken, sollte jetzt eine neue
mit der Option Arbeitsspeicher prüfen:
Daraufhin wird der Memory Inspector Sie können den WebAssembly-Arbeitsspeicher in Hexadezimal- und ASCII-Ansichten zu bestimmten Adressen navigieren und die Daten in verschiedene Formate verwenden:
Erweiterte Szenarien und Vorbehalte
Profilerstellung für WebAssembly-Code
Wenn Sie die Entwicklertools öffnen, wird WebAssembly-Code „abgestuft“ in ein
nicht optimierten Version, um das Debugging zu ermöglichen. Diese Version ist viel langsamer,
Das bedeutet, dass Sie sich nicht auf console.time
, performance.now
und andere Methoden zur Messung
der Codegeschwindigkeit, während die Entwicklertools
da die angezeigten Zahlen nicht die tatsächliche Leistung
überhaupt nicht.
Verwenden Sie stattdessen in den Entwicklertools das Steuerfeld „Leistung“. Dadurch wird der Code mit voller Geschwindigkeit ausgeführt und Sie erhalten eine Eine detaillierte Aufschlüsselung der Zeit, die für verschiedene Funktionen aufgewendet wurde:
Alternativ können Sie Ihre Anwendung mit geschlossenen Entwicklertools ausführen und Wenn Sie fertig sind, öffnen Sie sie, um die Console zu überprüfen.
Wir werden die Profilerstellung in Zukunft verbessern. zu beachten. Wenn Sie mehr über WebAssembly erfahren möchten Tiering-Szenarien finden Sie in unserer Dokumentation zur WebAssembly-Kompilierungspipeline.
Build und Debugging auf verschiedenen Computern (einschließlich Docker / Host)
Beim Erstellen in einem Docker, einer virtuellen Maschine oder einem Remote-Build-Server werden Sie wahrscheinlich auf Situationen stoßen, in denen die Pfade zu den die während des Builds verwendet wurden, nicht mit den Pfaden in Ihrem eigenen Dateisystem übereinstimmen, die Chrome-Entwicklertools ausgeführt werden. In diesem Fall werden Dateien im Bereich Quellen angezeigt, aber nicht geladen.
Um dieses Problem zu beheben, haben wir in den C/C++-Erweiterungsoptionen eine Pfadzuordnungsfunktion implementiert. Sie können damit beliebige Pfade neu zuordnen und damit die Entwicklertools Quellen leichter finden können.
Wenn sich das Projekt auf Ihrem Hostcomputer beispielsweise unter dem Pfad C:\src\my_project
befindet, aber in einem Docker-Container erstellt wurde, in dem dieser Pfad als /mnt/c/src/my_project
dargestellt wurde, können Sie ihn beim Debuggen neu zuordnen, indem Sie diese Pfade als Präfixe angeben:
Das erste übereinstimmende Präfix „gewinnt“. Wenn Sie mit anderen C++-
Debugger erstellt haben, ähnelt diese Option dem Befehl set substitute-path
in GDB oder eine target.source-map
-Einstellung in LLDB.
Fehler in optimierten Builds beheben
Wie bei anderen Sprachen funktioniert das Debuggen am besten, wenn Optimierungen deaktiviert sind. Durch Optimierungen können Funktionen inline angeordnet oder neu angeordnet werden. oder Teile des Codes ganz entfernen. den Debugger und folglich Sie als Nutzer zu verwirren.
Wenn Sie mit eingeschränkten Debug-Funktionen zufrieden sind und trotzdem einen optimierten Build debuggen möchten, funktionieren die meisten Optimierungen wie erwartet, mit Ausnahme der Funktions-Inline-Optimierung. Wir haben vor, die verbleibenden
in Zukunft zu beheben. Verwenden Sie für den Moment -fno-inline
,
bei der Kompilierung mit Optimierungen auf -O
-Ebene deaktivieren, z.B.:
emcc -g temp.c -o temp.html \ -O3 -fno-inline
Debug-Informationen trennen
In den Informationen zur Fehlerbehebung werden viele Details zu Ihrem Code gespeichert, Variablen, Funktionen, Umfänge und Standorte – alles, was auch für den Debugger nützlich sein. Daher kann sie häufig größer sein als die Code selbst.
Um das Laden und Kompilieren des WebAssembly-Moduls zu beschleunigen,
diese Debug-Informationen in eine separate WebAssembly-
-Datei. Dazu übergeben Sie in Emscripten ein -gseparate-dwarf=…
-Flag mit
einen gewünschten Dateinamen:
emcc -g temp.c -o temp.html \ -gseparate-dwarf=temp.debug.wasm
In diesem Fall speichert die Hauptanwendung nur einen Dateinamen.
temp.debug.wasm
und die Hilfserweiterung kann nach
wenn Sie die Entwicklertools öffnen.
In Kombination mit den oben beschriebenen Optimierungen kann diese Funktion können sogar fast optimierte Produktions-Builds und führen Sie später das Debugging mit einer lokalen Nebendatei durch. In diesem Fall Außerdem müssen wir die gespeicherte URL überschreiben, die Nebendatei suchen, zum Beispiel:
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]
Wird fortgesetzt...
Puh, das waren eine Menge neuer Funktionen!
Mit all diesen neuen Integrationen werden die Chrome-Entwicklertools ein brauchbares, leistungsstarker Debugger, nicht nur für JavaScript, sondern auch für C- und C++-Apps. Es war noch nie so einfach, Apps zu nutzen, die in einer Vielzahl von und sie in ein gemeinsames, plattformübergreifendes Web zu bringen.
Wir sind jedoch noch nicht am Ende. Einige der Dinge, von hier an arbeiten:
- Die Fehlerbehebung wurde optimiert.
- Benutzerdefinierte Typformatierer werden jetzt unterstützt.
- Wir arbeiten an Verbesserungen der Profilerstellung für WebAssembly-Anwendungen.
- Codeabdeckung wird unterstützt, um die Suche zu erleichtern nicht verwendetem Code.
- Verbesserte Unterstützung für Ausdrücke bei der Konsolenauswertung.
- Unterstützung für weitere Sprachen
- und weitere!
In der Zwischenzeit können Sie die aktuelle Betaversion mit Ihrem eigenen Code testen und alle gefundenen Probleme unter https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 melden.
Vorschaukanäle herunterladen
Sie können Canary, Dev oder Beta als Standardbrowser für die Entwicklung verwenden. Über diese Vorschaukanäle erhältst du Zugriff auf die neuesten Entwicklertools, kannst hochmoderne Webplattform-APIs testen und Probleme auf deiner Website erkennen, bevor deine Nutzer es tun.
Chrome-Entwicklertools-Team kontaktieren
Mit den folgenden Optionen kannst du die neuen Funktionen und Änderungen des Beitrags oder andere Aspekte der Entwicklertools besprechen.
- Senden Sie uns über crbug.com einen Vorschlag oder Feedback.
- Problem mit den Entwicklertools über Weitere Optionen melden > Hilfe > Hier kannst du Probleme mit den Entwicklertools in den Entwicklertools melden.
- Twittern Sie unter @ChromeDevTools.
- Hinterlasse Kommentare in den YouTube-Videos mit den Neuerungen in den Entwicklertools oder in YouTube-Videos mit Tipps zu den Entwicklertools.