Zum Hauptinhalt springen




Una arquitectura fuera del hilo principal puede mejorar significativamente la confiabilidad y la experiencia del Nutzername de su aplicación.

En los últimos 20 años, la Netz ha evolucionado drásticamente desde documentos estáticos con algunos estilos e imágenes hasta aplicaciones complejas y dinámicas. Sin embargo, una cosa se ha mantenido prácticamente sin cambios: solo tenemos un hilo por pestaña del Browser (con algunas excepciones) para hacer el trabajo de renderizar nuestros sitios y ejecutar nuestro JavaScript.

Infolgedessen ist der Hauptfaden unglaublich überarbeitet. Und mit zunehmender Komplexität von Webanwendungen wird der Hauptthread zu einem erheblichen Leistungsengpass. Um die Sache noch schlimmer zu machen, dauert es für einen bestimmten Benutzer so lange, bis der Code im Hauptthread ausgeführt ist fast völlig unvorhersehbar
weil die Fähigkeiten des Geräts einen großen Einfluss auf die Leistung haben. Diese Unvorhersehbarkeit wird nur zunehmen, wenn Benutzer von einer immer vielfältigeren Gruppe von Geräten auf das Internet zugreifen, von Telefonen mit eingeschränkten Funktionen bis hin zu leistungsstarken Flaggschiff-Maschinen mit hoher Bildwiederholfrequenz.

Wenn wir möchten, dass anspruchsvolle Webanwendungen die Leistungsrichtlinien wie z RAIL-Modell- Was auf empirischen Daten zur menschlichen Wahrnehmung und Psychologie basiert - wir brauchen Wege, um unseren Code auszuführen außerhalb des Hauptfadens (OMT).

Wenn Sie mehr über den Fall einer OMT-Architektur erfahren möchten, sehen Sie sich meinen CDS 2019-Vortrag unten an.

Threads mit Web-Workern

Native Plattformen unterstützen im Allgemeinen die parallele Arbeit, indem Sie einem Thread eine Funktion zuweisen können, die parallel zum Rest Ihres Programms ausgeführt wird. Sie können von beiden Threads aus auf dieselben Variablen zugreifen, und der Zugriff auf diese Freigaben kann mit Mutex und Semaphoren synchronisiert werden, um Race-Bedingungen zu vermeiden.

En JavaScript, podemos obtener una funcionalidad similar de los trabajadores web, que existen desde 2007 y son compatibles con los principales Browser desde 2012. Los trabajadores web se ejecutan en paralelo con el hilo principal, pero a diferencia del hilo nativo, no pueden compartir variables.

Verwechseln Sie Web-Worker nicht mit Servicemitarbeitern oder Worklets. Während die Namen ähnlich sind, unterscheiden sich die Funktionalität und Verwendung.

Übergeben Sie zum Erstellen eines Web-Workers eine Datei an den Konstruktor des Workers, der diese Datei in einem separaten Thread ausführt:

const Arbeiter = new Arbeiter("./worker.js");

Kommunizieren Sie mit dem Web Worker, indem Sie Nachrichten über das senden
POST-Meldung API. Übergeben Sie den Nachrichtenwert als Parameter in der POST-Meldung Rufen Sie an und fügen Sie dem Worker einen Listener für Nachrichtenereignisse hinzu:

main.js

const Arbeiter = new Arbeiter("./worker.js");
Arbeiter.POST-Meldung([40, 2]);

worker.js

addEventListener("message", Veranstaltung => {
const [zu, b] = Veranstaltung.Daten;
});

Verwenden Sie dasselbe, um eine Nachricht an den Hauptthread zu senden POST-Meldung API en el trabajador web y configure un detector de eventos en el hilo principal:

main.js

const Arbeiter = new Arbeiter("./worker.js");
Arbeiter.POST-Meldung([40, 2]);
Arbeiter.addEventListener("message", Veranstaltung => {
console.Log(Veranstaltung.Daten);
});

worker.js

addEventListener("message", Veranstaltung => {
const [zu, b] = Veranstaltung.Daten;

POST-Meldung(zu+b);
});

Es ist wahr, dass dieser Ansatz etwas begrenzt ist. In der Vergangenheit wurden Web-Worker hauptsächlich verwendet, um ein einzelnes Hochleistungsstück vom Hauptfaden abzuziehen. Der Versuch, mehrere Vorgänge mit einem einzigen Web-Worker abzuwickeln, wird schnell unhandlich. Sie müssen nicht nur die Parameter, sondern auch den Vorgang in der Nachricht codieren und die Abrechnung durchführen, um die Antworten mit den Anforderungen abzugleichen. Diese Komplexität ist wahrscheinlich der Grund, warum Web-Worker nicht weiter verbreitet sind.

Wenn wir jedoch einige der Kommunikationsschwierigkeiten zwischen dem Hauptthread und den Web-Workern beseitigen könnten, könnte dieses Modell für viele Anwendungsfälle ideal sein. Und zum Glück gibt es eine Bibliothek, die genau das tut!

Comlink: Web-Worker weniger arbeiten lassen

Comlink es una biblioteca cuyo Ziel es permitirle utilizar trabajadores web sin tener que pensar en los detalles de POST-Meldung. Comlink le permite compartir variables entre los trabajadores web y el hilo principal casi como lenguajes de Programmierung que soportan de forma nativa el hilo.

Sie konfigurieren Comlink, indem Sie es in einen Web Worker importieren und eine Reihe von Funktionen definieren, die für den Hauptthread verfügbar gemacht werden sollen. Anschließend importieren Sie Comlink in den Hauptthread, wickeln den Worker ein und erhalten Zugriff auf die bereitgestellten Funktionen:

worker.js

importieren {expose} desde "comlink";

const api = {
someMethod() { }
}
expose(api);

main.js

importieren {wrap} desde "comlink";

const Arbeiter = new Arbeiter("./worker.js");
const api = wrap(Arbeiter);

das api Die Variable im Hauptthread verhält sich genauso wie die im Webworker, außer dass jede Funktion ein Versprechen eines Werts anstelle des Werts selbst zurückgibt.

Welchen Code soll ich an einen Webworker übertragen?

Web-Worker haben keinen Zugriff auf das DOM und viele APIs wie WebUSB,
WebRTCoder
Web AudioSie können also keine Teile Ihrer Anwendung, die von einem solchen Zugriff abhängen, einem Mitarbeiter zuweisen. Dennoch erzeugt jeder kleine Code, der an einen Mitarbeiter übergeben wird, mehr Kopffreiheit im Hauptthread für die Dinge, die Es hat estar allí, como actualizar la Benutzeroberfläche.

Das Einschränken des Zugriffs auf die Benutzeroberfläche auf den Hauptthread ist in anderen Sprachen typisch. Tatsächlich nennen sowohl iOS als auch Android den Haupt-Thread das UI-Thread.

Ein Problem für Webentwickler besteht darin, dass die meisten Webanwendungen auf einem Benutzeroberflächen-Framework wie Vue oder React basieren, um alles in der Anwendung zu orchestrieren. Alles ist Bestandteil des Frameworks und daher inhärent an das DOM gebunden. Dies scheint die Migration auf eine OMT-Architektur schwierig zu machen.

Wenn wir jedoch zu einem Modell wechseln, bei dem Bedenken hinsichtlich der Benutzeroberfläche von anderen Belangen wie der Statusverwaltung getrennt sind, können Web-Worker selbst bei Framework-basierten Anwendungen sehr nützlich sein. Genau das ist der Ansatz von PROXX.

PROXX: eine OMT-Fallstudie

El equipo de Google Chrome desarrolló PROXX como un clon de Buscaminas que cumple
Progressive Web-App requisitos, incluido trabajar sin conexión y tener una Benutzererfahrung atractiva. Desafortunadamente, las primeras versiones del juego funcionaron mal en dispositivos restringidos como los teléfonos con funciones, lo que llevó al equipo a darse cuenta de que el hilo principal era un cuello de botella.

Das Team entschied sich für die Verwendung von Web-Workern, um den visuellen Status des Spiels von seiner Logik zu trennen:

  • Der Haupt-Thread behandelt das Rendern von Animationen und Übergängen.
  • Ein Web-Worker kümmert sich um die Logik des Spiels, die rein rechnerisch ist.

Dieser Ansatz ähnelt Redux
StrömungsmusterViele Flux-Anwendungen können problemlos auf eine OMT-Architektur migriert werden. Schau es dir an dieser Blog-Beitrag
Lesen Sie mehr darüber, wie Sie OMT auf eine Redux-Anwendung anwenden.

OMT hatte interessante Auswirkungen auf die Leistung des PROXX-Funktionstelefons. In der Nicht-OMT-Version friert die Benutzeroberfläche sechs Sekunden lang ein, nachdem der Benutzer mit ihr interagiert hat. Es gibt keine Kommentare und der Benutzer muss die vollen sechs Sekunden warten, bevor er etwas anderes tun kann.

Die Antwortzeit der Benutzeroberfläche in der nicht OMT PROXX-Version.

In der OMT-Version dauert das Spiel jedoch zwölf Sekunden, um ein Update der Benutzeroberfläche abzuschließen. Dies scheint zwar ein Leistungsverlust zu sein, führt jedoch zu mehr Benutzerfeedback. Die Verlangsamung tritt auf, weil die Anwendung mehr Frames sendet als die Nicht-OMT-Version, die keine Frames sendet. Daher weiß der Benutzer, dass etwas passiert, und kann weiter spielen, wenn die Benutzeroberfläche aktualisiert wird, wodurch sich das Spiel erheblich besser anfühlt.

Die Antwortzeit der Benutzeroberfläche in der OMT PROXX-Version.

Dies ist ein bewusster Kompromiss: Wir bieten Benutzern eingeschränkter Geräte eine Erfahrung, die Gefühl besser, ohne Benutzer von High-End-Geräten zu bestrafen.

Implikationen einer OMT-Architektur

Como muestra el ejemplo de PROXX, OMT hace que su aplicación se ejecute de manera confiable en una gama más amplia de dispositivos, pero no hace que su aplicación Sein más rápida:

  • Sie verschieben einfach die Arbeit aus dem Hauptfaden, ohne die Arbeit zu reduzieren.
  • Der zusätzliche Kommunikationsaufwand zwischen dem Web-Worker und dem Haupt-Thread kann die Dinge manchmal etwas verlangsamen.

Berücksichtigung der Kompromisse

Da der Hauptthread Benutzerinteraktionen wie das Scrollen während der Ausführung von JavaScript frei verarbeiten kann, werden weniger Frames gelöscht, obwohl die Gesamtwartezeit möglicherweise etwas länger ist. Es ist vorzuziehen, den Benutzer ein wenig warten zu lassen, anstatt einen Frame zu löschen, da die Fehlerquote bei verworfenen Frames geringer ist: Das Löschen eines Frames erfolgt in Millisekunden Hunderte Millisekunden, bevor ein Benutzer das Zeitlimit wahrnimmt.

Aufgrund der Unvorhersehbarkeit der Leistung zwischen Geräten ist das Ziel der OMT-Architektur wirklich wichtig Risikominderung- Machen Sie Ihre Anwendung robuster gegen sehr variable Laufzeitbedingungen - nicht über die Leistungsvorteile der Parallelisierung. Die verbesserte Wiederherstellbarkeit und UX-Verbesserungen sind einen kleinen Kompromiss bei der Geschwindigkeit wert.

Entwickler sind manchmal besorgt über die Kosten für das Kopieren komplexer Objekte in den Haupt-Thread und die Web-Worker. Weitere Details sind in der Diskussion, aber im Allgemeinen sollten Sie Ihr Leistungsbudget nicht sprengen, wenn die JSON-Zeichenfolgendarstellung Ihres Objekts weniger als 10 KB beträgt. Wenn Sie größere Objekte kopieren müssen, ziehen Sie die Verwendung in Betracht
ArrayBuffer
oder WebAssembly. Weitere Informationen zu diesem Problem finden Sie unter
esta publicación de Blog auf POST-Meldung Performance.

Ein Hinweis zu Werkzeugen

Web-Worker sind noch kein Mainstream, weshalb die meisten Modul-Tools wie z WebPack
y Aufrollen"Unterstütze sie nicht von Anfang an." ((Packen oder packen Obwohl ja!) Glücklicherweise gibt es Plugins, mit denen Web-Worker erstellt werden können. Job mit WebPack und Rollup:

zusammenfassend

Um sicherzustellen, dass unsere Anwendungen insbesondere in einem zunehmend globalen Markt so zuverlässig und zugänglich wie möglich sind, müssen wir eingeschränkte Geräte unterstützen. Auf diese Weise greifen die meisten Benutzer weltweit auf das Web zu. OMT bietet eine vielversprechende Möglichkeit, die Leistung auf solchen Geräten zu steigern, ohne die Benutzer von High-End-Geräten zu beeinträchtigen.

Darüber hinaus hat OMT sekundäre Vorteile:

Web-Mitarbeiter müssen nicht beängstigend sein. Tools wie Comlink entlasten die Mitarbeiter und machen sie zu einer praktikablen Option für eine Vielzahl von Webanwendungen.