Skip to content

Commit

Permalink
frontend: use single wasm instance
Browse files Browse the repository at this point in the history
  • Loading branch information
TerrorJack committed Nov 15, 2024
1 parent 43f2f40 commit a8ca59e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
- name: test
run: |
$CROSS_EMULATOR dist/pandoc.wasm pandoc/README.md -o pandoc/README.rst
wasmtime run --dir $PWD::/ -- dist/pandoc.wasm pandoc/README.md -o pandoc/README.rst
head --lines=20 pandoc/README.rst
- name: upload-pages-artifact
Expand Down
9 changes: 3 additions & 6 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,13 @@
<input type="text" id="arguments" value="-f markdown -t rst" />
</div>
<script type="module">
import { run_pandoc } from "./index.js";
import { pandoc } from "./index.js";

async function updateOutput() {
const inputText = document.getElementById("input").value;
const argumentsText = document
.getElementById("arguments")
.value.trim()
.split(" ");
const argumentsText = document.getElementById("arguments").value;
try {
const output = await run_pandoc(argumentsText, inputText);
const output = pandoc(argumentsText, inputText);
document.getElementById("output").value = output;
} catch (err) {
document.getElementById("output").value = `Error: ${err.message}`;
Expand Down
99 changes: 51 additions & 48 deletions frontend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,63 @@ import {
OpenFile,
File,
ConsoleStdout,
PreopenDirectory,
} from "https://cdn.jsdelivr.net/npm/@bjorn3/[email protected]/dist/index.js";

const mod = await WebAssembly.compileStreaming(fetch("./pandoc.wasm"));

const instance_promise_pool_size = 8;
const args = ["pandoc.wasm", "+RTS", "-H64m", "-RTS"];
const env = [];
const in_file = new File(new Uint8Array(), { readonly: true });
const out_file = new File(new Uint8Array(), { readonly: false });
const fds = [
new OpenFile(new File(new Uint8Array(), { readonly: true })),
ConsoleStdout.lineBuffered((msg) => console.log(`[WASI stdout] ${msg}`)),
ConsoleStdout.lineBuffered((msg) => console.warn(`[WASI stderr] ${msg}`)),
new PreopenDirectory("/", [
["in", in_file],
["out", out_file],
]),
];
const options = { debug: false };
const wasi = new WASI(args, env, fds, options);
const { instance } = await WebAssembly.instantiateStreaming(
fetch("./pandoc.wasm"),
{
wasi_snapshot_preview1: wasi.wasiImport,
}
);

const instance_promise_pool = [];
wasi.initialize(instance);
instance.exports.__wasm_call_ctors();

function instance_promise_pool_fill() {
if (instance_promise_pool.length < instance_promise_pool_size) {
for (
let i = instance_promise_pool.length;
i < instance_promise_pool_size;
++i
) {
const args = [];
const env = [];
const stdin_file = new File(new Uint8Array(), { readonly: true });
const stdout_file = new File(new Uint8Array(), { readonly: false });
const fds = [
new OpenFile(stdin_file),
new OpenFile(stdout_file),
ConsoleStdout.lineBuffered((msg) =>
console.warn(`[WASI stderr] ${msg}`)
),
];
const options = { debug: false };
const wasi = new WASI(args, env, fds, options);
instance_promise_pool.push(
WebAssembly.instantiate(mod, {
wasi_snapshot_preview1: wasi.wasiImport,
}).then((instance) => ({ instance, wasi, stdin_file, stdout_file }))
);
}
}
function memory_data_view() {
return new DataView(instance.exports.memory.buffer);
}

instance_promise_pool_fill();
const argc_ptr = instance.exports.malloc(4);
memory_data_view().setUint32(argc_ptr, args.length, true);
const argv = instance.exports.malloc(4 * (args.length + 1));
for (let i = 0; i < args.length; ++i) {
const arg = instance.exports.malloc(args[i].length + 1);
new TextEncoder().encodeInto(
args[i],
new Uint8Array(instance.exports.memory.buffer, arg, args[i].length)
);
memory_data_view().setUint8(arg + args[i].length, 0);
memory_data_view().setUint32(argv + 4 * i, arg, true);
}
memory_data_view().setUint32(argv + 4 * args.length, 0, true);
const argv_ptr = instance.exports.malloc(4);
memory_data_view().setUint32(argv_ptr, argv, true);

const instances = (async function* () {
while (true) {
yield await instance_promise_pool.shift();
instance_promise_pool_fill();
}
})();
instance.exports.hs_init_with_rtsopts(argc_ptr, argv_ptr);

export async function run_pandoc(args, stdin_str) {
const { instance, wasi, stdin_file, stdout_file } = (await instances.next())
.value;
wasi.args = ["pandoc.wasm", ...args];
stdin_file.data = new TextEncoder().encode(stdin_str);
const ec = wasi.start(instance);
if (ec !== 0) {
throw new Error(`Non-zero exit code ${ec}`);
}
return new TextDecoder("utf-8", { fatal: true }).decode(stdout_file.data);
export function pandoc(args_str, in_str) {
const args_ptr = instance.exports.malloc(args_str.length);
new TextEncoder().encodeInto(
args_str,
new Uint8Array(instance.exports.memory.buffer, args_ptr, args_str.length)
);
in_file.data = new TextEncoder().encode(in_str);
instance.exports.wasm_main(args_ptr, args_str.length);
return new TextDecoder("utf-8", { fatal: true }).decode(out_file.data);
}

0 comments on commit a8ca59e

Please sign in to comment.