Learning WASM 4 ~ 8 の成果をライブラリ化して公開した。
JS側では今回作成したQuickJSの拡張モジュールでる`ipc`モジュールを使用し、プロシージャを登録して、最終的に`listen`メソッドを実行する
import * as ipc from 'ipc';
ipc.register('echo', function (payload) {
return payload;
});
ipc.listen();
.NET側では、QjsIpcEngineのインスタンスを作成し、JSファイルと実行フォルダを指定してQuickJSを実行する。
実行した後は、`InvokeAsync`メソッドでJS側に登録したプロシージャを実行できる。
using QjsIpc;
await using var engine = new QjsIpcEngine();
engine.Start(new QjsIpcOptions
{
ScriptFileName = "main.js",
AllowedDirectoryPath = Environment.CurrentDirectory,
});
var message = await engine.InvokeAsync<string>("echo", "Hello, World!");
Console.WriteLine(message);
.NET側にプロシージャを用意し、JS側から呼び出すこともできる。
.NET側にプロシージャホストとなるクラスを作成し、そのインスタンスをMethodHost
オプションに設定する。
生やすメソッドは、値でもTaskでもValueTaskでも大丈夫。
public class Host
{
public int HostAdd(int a, int b) => a + b;
public Task<string> HostStringTask() => Task.FromResult("host value");
public async Task<string> HostStringAsync() {
await Task.Delay(100);
return "host value";
}
public async ValueTask<string> HostStringValueAsync() {
await Task.Delay(100);
return "host value";
}
}
public class Program
{
public static async Task Main(string[] args)
{
await using var engine = new QjsIpcEngine();
engine.Start(new QjsIpcOptions
{
ScriptFileName = "main.js",
AllowedDirectoryPath = Environment.CurrentDirectory,
MethodHost = new Host()
});
await engine.InvokeAsync('createMessage', "iwate");
}
}
JS側では`ipc.invoke`メソッドで呼び出せる。戻り値は`Promise`。
import * as ipc from 'ipc';
ipc.register('createMessage', async function (name) {
const value = ipc.invoke('HostAdd', 100, 200);
return Hi, ${name}. The result of HostAdd(100, 200) is ${value};
});
ipc.listen();
ベンチマークもとってみたが、想像通り速くはない。けど使えないほどではない。
自分の実装の中で遅い部分の検討はついてて、.NET<->JS間を1バイトずつやり取りしてるのでまあ遅い。
wasmのmemory使ってページ(64kb)ごとにやり取りすればもっと早くなるかな。今後に課題。
// Summary
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.200-preview.21617.4
[Host] : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT [AttachedDebugger]
DefaultJob : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT
| Method | Mean | Error | StdDev |
|----------------- |-----------:|----------:|----------:|
| Echo | 303.7 us | 28.22 us | 81.42 us |
| HostValue | 456.2 us | 41.25 us | 120.97 us |
| Ejs | 1,414.2 us | 91.87 us | 269.43 us |
| EjsWithHostValue | 1,499.9 us | 121.33 us | 340.22 us |