Skip to content

Commit

Permalink
Merge pull request #10 from joshLong145/add/async-support
Browse files Browse the repository at this point in the history
Add/async support
  • Loading branch information
joshLong145 authored Mar 12, 2024
2 parents 721995c + fc2e409 commit 01f5d60
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 97 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Span: A Web Worker Bridging Module

[![deno module](https://shield.deno.dev/x/span)](https://deno.land/x/span)
[![Unit Test CI](https://github.com/joshLong145/Span/actions/workflows/test.yml/badge.svg)](https://github.com/joshLong145/Span/actions/workflows/test.yml)

Expand Down Expand Up @@ -44,20 +45,20 @@ class Example extends WorkerDefinition {
super();
}

public addOne(
addOne = (
buffer: SharedArrayBuffer,
args: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
console.log("param name value: ", args.name);
const arr = new Int8Array(buffer);
arr[0] += 1;
return buffer;
}

public fib(
fib = (
buffer: SharedArrayBuffer,
module: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
let i;
const arr = new Uint8Array(buffer);
arr[0] = 0;
Expand Down Expand Up @@ -104,20 +105,20 @@ class Example extends WorkerDefinition {
super();
}

public addOne(
addOne = (
buffer: SharedArrayBuffer,
args: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
console.log("param name value: ", args.name);
const arr = new Int8Array(buffer);
arr[0] += 1;
return buffer;
}

public fib(
fib = (
buffer: SharedArrayBuffer,
module: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
let i;
const arr = new Uint8Array(buffer);
arr[0] = 0;
Expand Down Expand Up @@ -178,7 +179,7 @@ class Example extends WasmWorkerDefinition {
super(modulePath);
}

public test(buffer: SharedArrayBuffer, module: any) {
addOne = (buffer: SharedArrayBuffer, module: any) => {
let arr = new Int8Array(buffer);
arr[0] += 1
//@ts-ignore
Expand All @@ -204,7 +205,7 @@ const wrapper: WasmInstanceWrapper<Example> = new WasmInstanceWrapper<Example>(e

wrapper.start();
//@ts-ignore
await example.execute("test").then((buf: SharedArrayBuffer) => {
await example.execute("addOne").then((buf: SharedArrayBuffer) => {
console.log("buffer returned ", new Int32Array(buf))
});

Expand Down
26 changes: 14 additions & 12 deletions benchmark/wasm_instance_start_bench.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
//@ts-nocheck
import {
assertEquals,
assertExists,
} from "https://deno.land/std@0.210.0/assert/mod.ts";

import {
WasmInstanceWrapper,
WasmWorkerDefinition,
Expand All @@ -13,16 +10,19 @@ class TestExample extends WasmWorkerDefinition {
super(modulePath);
}

public test2(buffer: SharedArrayBuffer, module: Record<string, any>) {
let arr = new Int8Array(buffer);
test2 = (
buffer: SharedArrayBuffer,
_module: Record<string, any>,
): SharedArrayBuffer => {
const arr = new Int8Array(buffer);
arr[0] += 1;

self.primeGenerator();
return arr.buffer;
}
};
}

Deno.bench("Wasm Worker Start Go Module loading", async (b) => {
Deno.bench("Wasm Worker Start Go Module loading", async (_b) => {
const example: WasmWorkerDefinition = new TestExample(
"./examples/wasm/tiny-go/primes-2.wasm",
);
Expand All @@ -33,7 +33,7 @@ Deno.bench("Wasm Worker Start Go Module loading", async (b) => {
example,
{
outputPath: "output",
namespace: "asd",
namespace: "testing",
addons: [
"./lib/wasm_exec_tiny.js",
],
Expand All @@ -42,18 +42,19 @@ Deno.bench("Wasm Worker Start Go Module loading", async (b) => {
},
moduleLoader: (path: string) => {
const fd = Deno.openSync(path);
let mod = Deno.readAllSync(fd);
const mod = Deno.readFileSync(fd);
fd.close();
return mod;
},
},
);

await wrapper.start().then(() => {
example.terminateWorker();
});
});

Deno.bench("Wasm Worker Start Rust Module loading", async (b) => {
Deno.bench("Wasm Worker Start Rust Module loading", async (_b) => {
const example: WasmWorkerDefinition = new TestExample(
"./examples/wasm/rust/wasm_test_bg.wasm",
);
Expand All @@ -73,12 +74,13 @@ Deno.bench("Wasm Worker Start Rust Module loading", async (b) => {
},
moduleLoader: (path: string) => {
const fd = Deno.openSync(path);
let mod = Deno.readAllSync(fd);
const mod = Deno.readAllSync(fd);
fd.close();
return mod;
},
},
);

await wrapper.start().then(() => {
example.terminateWorker();
});
Expand Down
60 changes: 49 additions & 11 deletions examples/js/example.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,66 @@
import { InstanceConfiguration } from "../../src/types.ts";
import { InstanceWrapper, WorkerDefinition } from "./../../src/mod.ts";

class Example extends WorkerDefinition {
public constructor() {
super();
}

public addOne(
addOne = (
buffer: SharedArrayBuffer,
args: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
console.log("param name value: ", args.name);
const arr = new Int8Array(buffer);
const arr = new Uint32Array(buffer);
arr[0] += 1;

return buffer;
}
};

public fib(
fib = (
buffer: SharedArrayBuffer,
args: Record<string, any>,
): SharedArrayBuffer {
): SharedArrayBuffer => {
let i;
const arr = new Uint8Array(buffer);
const arr = new Uint32Array(buffer);
arr[0] = 0;
arr[1] = 1;

for (i = 2; i <= args.count; i++) {
arr[i] = arr[i - 2] + arr[i - 1];
console.log(arr[i]);
}
return buffer;
};

getKeyPair = async (
buffer: SharedArrayBuffer,
_args: Record<string, any>,
): Promise<SharedArrayBuffer> => {
const keyPair = await crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256",
},
true,
["encrypt", "decrypt"],
);

console.log("generated key", keyPair);
return buffer;
}
};

getGpuAdapter = async (
buffer: SharedArrayBuffer,
_args: Record<string, any>,
): Promise<SharedArrayBuffer> => {
const adapter = await navigator.gpu.requestAdapter();
console.log("gpu adapter", adapter);

return buffer;
};
}

const example: Example = new Example();
Expand All @@ -42,6 +72,10 @@ const wrapper: InstanceWrapper<Example> = new InstanceWrapper<Example>(

wrapper.start();

(example as any).worker.onerror = (event: any) => {
console.log("an error occured ", event);
};

await example.execute("addOne", { name: "foo" }).then(
(buf: SharedArrayBuffer) => {
console.log("add one result: ", new Int32Array(buf));
Expand All @@ -53,11 +87,15 @@ await example.execute("addOne", { name: "foo" }).then(
},
);

await example.execute("fib", { count: 10 }).then(
await example.execute("getKeyPair");

await example.execute("fib", { count: 46 }).then(
(buffer: SharedArrayBuffer) => {
console.log("fib result ", new Uint8Array(buffer));
console.log("last fib number", new Uint8Array(buffer)[10]);
console.log("fib result ", new Uint32Array(buffer));
console.log("last fib number", new Uint32Array(buffer)[46]);
},
);
await example.execute("getGpuAdapter");
await example.execute("getGpuAdapter");

example.terminateWorker();
4 changes: 2 additions & 2 deletions examples/wasm/rust/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ class Example extends WasmWorkerDefinition {
super(modulePath);
}

public test2(buffer: SharedArrayBuffer, args: Record<string, any>) {
test2 = (buffer: SharedArrayBuffer, args: Record<string, any>) => {
let arr = new Int8Array(buffer);
arr[0] += 1;
//@ts-ignore
self.greet();
return arr.buffer;
}
};
}

const example: Example = new Example(
Expand Down
11 changes: 7 additions & 4 deletions src/InstanceWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export class WorkerDefinition {
/**
* worker instance, can be stopped by calling terminateWorker
*/
public worker: Worker | undefined = undefined;
// deno-lint-ignore no-explicit-any
public worker: any | undefined = undefined;

constructor() {}

Expand Down Expand Up @@ -117,12 +118,14 @@ export class InstanceWrapper<T extends WorkerDefinition> {
}

private _generate(): void {
const keys = Reflect.ownKeys(
const protoKeys = Reflect.ownKeys(
Object.getPrototypeOf(this._instance),
) as [keyof T];
const baseKeys = Object.keys(this._instance) as [keyof T];

const wrps: WorkerWrapper[] = [];
for (const key of keys) {
key !== "constructor" &&
for (const key of protoKeys.concat(baseKeys)) {
key !== "constructor" && key !== "execMap" && key !== "worker" &&
wrps.push(new WorkerWrapper(this._instance[key] as WorkerMethod));
}

Expand Down
19 changes: 12 additions & 7 deletions src/WasmInstanceWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export class WasmWorkerDefinition {
/**
* Worker instance, can be stopped by calling terminateWorker
*/
public worker: Worker | undefined = undefined;
// deno-lint-ignore no-explicit-any
public worker: any | undefined = undefined;

/**
* Path to the WASM module being loaded into the worker.
Expand Down Expand Up @@ -81,14 +82,18 @@ export class WasmInstanceWrapper<T extends WasmWorkerDefinition> {
}

private _generate(): void {
const keys = Reflect.ownKeys(Object.getPrototypeOf(this._instance)) as [
keyof T,
];
const protoKeys = Reflect.ownKeys(
Object.getPrototypeOf(this._instance),
) as [keyof T];
const baseKeys = Object.keys(this._instance) as [keyof T];

const wrps: WorkerWrapper[] = [];
for (const key of keys) {
key !== "constructor" &&
for (const key of protoKeys.concat(baseKeys)) {
key !== "constructor" && key !== "execMap" && key !== "worker" &&
key !== "ModulePath" && key !== "workerString" &&
wrps.push(new WorkerWrapper(this._instance[key] as WorkerMethod));
}

this._wm = new WorkerManager(wrps);
this._wb = new WorkerBridge({
workers: wrps,
Expand Down Expand Up @@ -199,7 +204,7 @@ export class WasmInstanceWrapper<T extends WasmWorkerDefinition> {
}
const enc = new TextEncoder();
this._generate();
let worker = `
const worker = `
${this.workerString}\n
${this?._wm?.CreateWorkerMap()}\n
${this?._wm?.CreateOnMessageHandler()}`;
Expand Down
12 changes: 9 additions & 3 deletions src/WorkerBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export class WorkerBridge<T> {

for (const worker of this._workers) {
root += `
// this buffer size should be a config option,
_bufferMap["${worker.WorkerName}"] = typeof SharedArrayBuffer != "undefined" ? new SharedArrayBuffer(1024) : new Uint8Array();\n
// this buffer size should be a config option,
_bufferMap["${worker.WorkerName}"] = typeof SharedArrayBuffer != "undefined" ? new SharedArrayBuffer(1024) : new Uint8Array();\n
`;
}

Expand Down Expand Up @@ -70,7 +70,7 @@ export class WorkerBridge<T> {
prmsRes = res;
});

self.worker = new Worker(objUrl, { deno: true, type: "module" });
self.worker = this._genWebWorker(objUrl);
self.worker.onmessage = (e: MessageEvent<any>) => {
if (e.data.ready) {
prmsRes();
Expand Down Expand Up @@ -195,6 +195,12 @@ self['worker'] = worker;
return root;
}

private _genWebWorker(objUrl: URL): any {
const worker = new Worker(objUrl, { deno: true, type: "module" });

return worker;
}

public createBridge(worker: string): string {
const bufferAlloc = this._bufferMap();
const bootstrap = this._workerBootstrap(worker);
Expand Down
Loading

0 comments on commit 01f5d60

Please sign in to comment.