suchen
HeimBackend-EntwicklungGolangDas Wasm-Komponentenmodell und das idiomatische Codegen

The Wasm Component Model and idiomatic codegen

Arcjet bündelt WebAssembly mit unserem Security-as-Code-SDK. Dies hilft Entwicklern, gängige Sicherheitsfunktionen wie PII-Erkennung und Bot-Erkennung direkt in ihren Code zu implementieren. Ein Großteil der Logik ist in Wasm eingebettet, was uns eine sichere Sandbox mit nahezu nativer Leistung bietet und Teil unserer Philosophie rund um Local-First-Sicherheit ist.

Die Möglichkeit, denselben Code plattformübergreifend auszuführen, ist ebenfalls hilfreich, da wir die Unterstützung von JavaScript auf andere Tech-Stacks ausbauen, aber für die Übersetzung zwischen Sprachen ist eine wichtige Abstraktion erforderlich (unser Wasm wird aus Rust kompiliert).

Das WebAssembly Component Model ist das leistungsstarke Konstrukt, das dies ermöglicht, aber ein Konstrukt kann nur so gut sein wie die Implementierungen und Tools, die es umgeben. Beim Komponentenmodell zeigt sich dies am deutlichsten in der Codegenerierung für Hosts (Umgebungen, die das WebAssembly-Komponentenmodell ausführen) und Gäste (WebAssembly-Module, die in einer beliebigen Sprache geschrieben und zum Komponentenmodell kompiliert wurden; in unserem Fall Rust).

Das Komponentenmodell definiert eine Sprache für die Kommunikation zwischen Hosts und Gästen, die hauptsächlich aus Typen, Funktionen, Importen und Exporten besteht. Es wird versucht, eine breite Sprache zu definieren, aber einige Typen, wie Varianten, Tupel und Ressourcen, existieren möglicherweise nicht in einer bestimmten Programmiersprache für allgemeine Zwecke.

Wenn ein Tool versucht, Code für eine dieser Sprachen zu generieren, müssen die Autoren oft kreativ werden, um Komponentenmodelltypen dieser Allzwecksprache zuzuordnen. Zum Beispiel verwenden wir jco zum Generieren von JS-Bindungen und dies implementiert Varianten mithilfe eines JavaScript-Objekts in der Form { tag: string, value: string }. Es gibt sogar einen Sonderfall für das Ergebnis <_ _> Geben Sie ein, bei dem die Fehlervariante in einen Fehler umgewandelt und ausgelöst wird.

In diesem Beitrag wird untersucht, wie das Wasm-Komponentenmodell sprachübergreifende Integrationen ermöglicht, wie komplex die Codegenerierung für Hosts und Gäste ist und welche Kompromisse wir eingehen, um idiomatischen Code in Sprachen wie Go zu erreichen.

Hostcode-Generierung für Go

Bei Arcjet mussten wir ein Tool entwickeln, um Code für Hosts zu generieren, der in der Programmiersprache Go geschrieben wurde. Obwohl unser SDK versucht, alles lokal zu analysieren, ist das nicht immer möglich und deshalb haben wir eine in Go geschriebene API, die lokale Entscheidungen mit zusätzlichen Metadaten ergänzt.

Go hat von Natur aus ein sehr minimales Syntax- und Typsystem. Bis vor kurzem gab es noch nicht einmal Generika, und es gibt immer noch erhebliche Einschränkungen. Dies macht die Codegenerierung vom Component Model to Go in vielerlei Hinsicht komplex.

Zum Beispiel könnten wir ein Ergebnis generieren<_ _> als:

type Result[V any] struct {
    value V
    err error
}

Dies schränkt jedoch den Typ ein, der an der Fehlerposition bereitgestellt werden kann. Wir müssten es also wie folgt codegenerieren:

type Result[V any] struct {
    value V
    err error
}

Dies funktioniert, wird aber mit anderen idiomatischen Go-Elementen umständlich zu verwenden, da diese häufig die Konvention val, err := doSomething() verwenden, um die gleiche Semantik wie der oben definierte Ergebnistyp anzugeben.

Außerdem ist die Erstellung dieses Ergebnisses umständlich: Result[int, string]{value: 1, err: ""}. Anstatt den Ergebnistyp bereitzustellen, möchten wir wahrscheinlich idiomatische Muster abgleichen, damit Go-Benutzer sich natürlich fühlen, wenn sie unsere generierten Bindungen nutzen.

Idiomatische vs. direkte Zuordnung

Code kann so generiert werden, dass er sich natürlicher für die Sprache anfühlt, oder es kann eine direktere Zuordnung zu den Komponentenmodelltypen erfolgen. Keine der Optionen passt zu 100 % der Anwendungsfälle, daher liegt es an den Tool-Autoren, zu entscheiden, welche am sinnvollsten ist.

Für die Arcjet-Werkzeuge haben wir den idiomatischen Go-Ansatz für die Option<_> gewählt. und result<_ _> Typen, die jeweils auf val, ok := doSomething() und val, err := doSomething() abgebildet werden. Für Varianten erstellen wir eine Schnittstelle, die jede Variante implementieren muss, wie zum Beispiel:

type Result[V any, E any] struct {
    value V
    err E
}

Dies schafft eine gute Balance zwischen Typsicherheit und unnötigem Umwickeln. Natürlich gibt es Situationen, in denen eine Umhüllung erforderlich ist, aber diese können als Randfälle behandelt werden.

Entwickler haben möglicherweise Probleme mit nicht idiomatischen Mustern, was zu ausführlichem und weniger wartbarem Code führt. Durch die Verwendung etablierter Konventionen fühlt sich der Code vertrauter an, die Implementierung erfordert jedoch etwas mehr Aufwand.

Wir haben uns für den idiomatischen Weg entschieden, um Reibungsverluste zu minimieren und es unserem Team einfacher zu machen, damit wir wissen, was uns erwartet, wenn wir uns in der Codebasis bewegen.

Aufrufe zu Konventionen

Eine der wichtigsten Entscheidungen, die Tool-Autoren treffen müssen, ist die Aufrufkonvention der Bindungen. Dazu gehört die Entscheidung, wie/wann Importe kompiliert werden, ob das Wasm-Modul während der Einrichtung oder Instanziierung kompiliert wird, und die Bereinigung.

In der Arcjet-Codebasis haben wir das Fabrik-/Instanzmuster ausgewählt, um die Leistung zu optimieren. Das Kompilieren eines WebAssembly-Moduls ist teuer, daher führen wir es einmal im NewBotFactory()-Konstruktor durch. Nachfolgende Instantiate()-Aufrufe sind dann schnell und kostengünstig und ermöglichen einen hohen Durchsatz bei Produktions-Workloads.

type BotConfig interface {
    isBotConfig()
}

func (AllowedBotConfig) isBotConfig() {}

func (DeniedBotConfig) isBotConfig() {}

Verbraucher erstellen diese BotFactory einmal, indem sie NewBotFactory(ctx) aufrufen, und verwenden sie, um über die Instantiate-Methode mehrere Instanzen zu erstellen.

func NewBotFactory(
    ctx context.Context,
) (*BotFactory, error) {
    runtime := wazero.NewRuntime(ctx)

    // ... Imports are compiled here if there are any

    // Compiling the module takes a LONG time, so we want to do it once and hold
    // onto it with the Runtime
    module, err := runtime.CompileModule(ctx, wasmFileBot)
    if err != nil {
            return nil, err
    }

    return &BotFactory{runtime, module}, nil
}

Die Instanziierung erfolgt sehr schnell, wenn das Modul bereits kompiliert wurde, wie wir es mit runtime.CompileModule() beim Erstellen der Factory tun.

Die BotInstance verfügt über Funktionen, die aus der Komponentenmodelldefinition exportiert wurden.

func (f *BotFactory) Instantiate(ctx context.Context) (*BotInstance, error) {
    if module, err := f.runtime.InstantiateModule(ctx, f.module, wazero.NewModuleConfig()); err != nil {
            return nil, err
    } else {
            return &BotInstance{module}, nil
    }
}

Im Allgemeinen möchten wir eine BotInstance nach der Verwendung bereinigen, um sicherzustellen, dass kein Speicher verloren geht. Hierfür stellen wir die Close-Funktion zur Verfügung.

func (i *BotInstance) Detect(
    ctx context.Context,
    request string,
    options BotConfig,
) (BotResult, error) {
   // ... Lots of generated code for binding to Wazero
}

Wenn Sie die gesamte BotFactory bereinigen möchten, kann diese auch geschlossen werden:

type Result[V any] struct {
    value V
    err error
}

Wir können alle diese APIs zusammenfügen, um Funktionen in diesem WebAssembly-Modul aufzurufen:

type Result[V any, E any] struct {
    value V
    err E
}

Dieses Muster der Fabrik- und Instanzkonstruktion erfordert mehr Code zur Verwendung, wurde jedoch ausgewählt, um in den Hot-Paths des Arcjet-Dienstes so viel Leistung wie möglich zu erzielen.

Durch die Vorabbelastung der Kompilierungskosten stellen wir sicher, dass in den Hot Paths des Arcjet-Dienstes – wo die Latenz am wichtigsten ist – die Anforderungsbearbeitung so effizient wie möglich ist. Dieser Kompromiss erhöht zwar die Komplexität des Initialisierungscodes, zahlt sich jedoch durch einen wesentlich geringeren Overhead pro Anfrage aus – siehe unsere Diskussion der Kompromisse.

Kompromisse

Jedes Mal, wenn wir zwei oder mehr Sprachen integrieren müssen, ist dies voller Kompromisse, die eingegangen werden müssen – sei es mit nativem FFI oder dem Komponentenmodell.

In diesem Beitrag wurden einige der Herausforderungen besprochen, mit denen wir bei Arcjet konfrontiert waren, und die Gründe für unsere Entscheidungen. Wenn wir alle auf demselben Satz an Grundelementen wie dem Komponentenmodell und WIT aufbauen, können wir alle denselben Satz hochwertiger Grundelemente wie wit-bindgen oder wit-component nutzen und erstellen Sie Werkzeuge, die für jeden Anwendungsfall geeignet sind. Deshalb hilft die Arbeit an Standards allen.

Das WebAssembly-Komponentenmodell bietet eine leistungsstarke Abstraktion für die sprachübergreifende Integration, aber die Übersetzung seiner Typen in Sprachen wie Go bringt subtile Designherausforderungen mit sich. Durch die Auswahl idiomatischer Muster und die selektive Optimierung der Leistung – beispielsweise durch die Verwendung eines Fabrik-/Instanzmusters – können wir ein natürliches Entwicklererlebnis bieten und gleichzeitig die Effizienz aufrechterhalten.

Während sich die Tools rund um das Komponentenmodell weiterentwickeln, können wir uns auf verfeinerte Codegen-Ansätze freuen, die diese Integrationen weiter vereinfachen.

Das obige ist der detaillierte Inhalt vonDas Wasm-Komponentenmodell und das idiomatische Codegen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Golang und Python: Verständnis der UnterschiedeGolang und Python: Verständnis der UnterschiedeApr 18, 2025 am 12:21 AM

Die Hauptunterschiede zwischen Golang und Python sind Parallelitätsmodelle, Typsysteme, Leistung und Ausführungsgeschwindigkeit. 1. Golang verwendet das CSP -Modell, das für hohe gleichzeitige Aufgaben geeignet ist. Python verlässt sich auf Multi-Threading und Gil, was für I/O-intensive Aufgaben geeignet ist. 2. Golang ist ein statischer Typ und Python ist ein dynamischer Typ. 3.. Golang kompilierte Sprachausführungsgeschwindigkeit ist schnell und Python interpretierte die Sprachentwicklung schnell.

Golang gegen C: Bewertung des GeschwindigkeitsunterschiedsGolang gegen C: Bewertung des GeschwindigkeitsunterschiedsApr 18, 2025 am 12:20 AM

Golang ist in der Regel langsamer als C, aber Golang hat mehr Vorteile für die gleichzeitige Programmier- und Entwicklungseffizienz: 1) Golangs Müllsammlung und Parallelitätsmodell macht es in hohen Parallelitätsszenarien gut ab. 2) C erhält eine höhere Leistung durch das manuelle Speichermanagement und die Hardwareoptimierung, weist jedoch eine höhere Komplexität der Entwicklung auf.

Golang: Eine Schlüsselsprache für Cloud Computing und DevOpsGolang: Eine Schlüsselsprache für Cloud Computing und DevOpsApr 18, 2025 am 12:18 AM

Golang wird häufig in Cloud -Computing und DevOps verwendet, und seine Vorteile liegen in Einfachheit, Effizienz und gleichzeitigen Programmierfunktionen. 1) Beim Cloud Computing behandelt Golang effizient gleichzeitige Anforderungen über Goroutine- und Kanalmechanismen. 2) In DevOps machen Golangs schnelle Zusammenstellung und plattformübergreifende Funktionen die erste Wahl für Automatisierungswerkzeuge.

Golang und C: Ausführungseffizienz verstehenGolang und C: Ausführungseffizienz verstehenApr 18, 2025 am 12:16 AM

Golang und C haben jeweils ihre eigenen Vorteile bei der Leistungseffizienz. 1) Golang verbessert die Effizienz durch Goroutine- und Müllsammlung, kann jedoch eine Pause einführen. 2) C realisiert eine hohe Leistung durch das manuelle Speicherverwaltung und -optimierung, aber Entwickler müssen sich mit Speicherlecks und anderen Problemen befassen. Bei der Auswahl müssen Sie Projektanforderungen und Teamtechnologie -Stack in Betracht ziehen.

Golang vs. Python: Parallelität und MultithreadingGolang vs. Python: Parallelität und MultithreadingApr 17, 2025 am 12:20 AM

Golang eignet sich besser für hohe Parallelitätsaufgaben, während Python mehr Vorteile bei der Flexibilität hat. 1. Golang behandelt die Parallelität effizient über Goroutine und Kanal. 2. Python stützt sich auf Threading und Asyncio, das von GIL betroffen ist, jedoch mehrere Parallelitätsmethoden liefert. Die Wahl sollte auf bestimmten Bedürfnissen beruhen.

Golang und C: Die Kompromisse bei der LeistungGolang und C: Die Kompromisse bei der LeistungApr 17, 2025 am 12:18 AM

Die Leistungsunterschiede zwischen Golang und C spiegeln sich hauptsächlich in der Speicherverwaltung, der Kompilierungsoptimierung und der Laufzeiteffizienz wider. 1) Golangs Müllsammlung Mechanismus ist praktisch, kann jedoch die Leistung beeinflussen.

Golang vs. Python: Anwendungen und AnwendungsfälleGolang vs. Python: Anwendungen und AnwendungsfälleApr 17, 2025 am 12:17 AM

Wählen SieGolangforHighperformanceConcurcurrency, idealforbackendServicesandNetworkProgramming; selectPythonforrapidDevelopment, DataScience und MachinelearningDuEToSverseStilityAntenSiveselibrary.

Golang gegen Python: Schlüsselunterschiede und ÄhnlichkeitenGolang gegen Python: Schlüsselunterschiede und ÄhnlichkeitenApr 17, 2025 am 12:15 AM

Golang und Python haben jeweils ihre eigenen Vorteile: Golang ist für hohe Leistung und gleichzeitige Programmierung geeignet, während Python für Datenwissenschaft und Webentwicklung geeignet ist. Golang ist bekannt für sein Parallelitätsmodell und seine effiziente Leistung, während Python für sein Ökosystem für die kurze Syntax und sein reiches Bibliothek bekannt ist.

See all articles

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Crossplay haben?
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

MinGW – Minimalistisches GNU für Windows

MinGW – Minimalistisches GNU für Windows

Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

WebStorm-Mac-Version

WebStorm-Mac-Version

Nützliche JavaScript-Entwicklungstools

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor