Skip to content

Instantly share code, notes, and snippets.

@ukyo
Last active July 3, 2017 10:41
Show Gist options
  • Save ukyo/6d952725bf1e3b7bd727f4a7583d284e to your computer and use it in GitHub Desktop.
Save ukyo/6d952725bf1e3b7bd727f4a7583d284e to your computer and use it in GitHub Desktop.
人のぬくもりがあるwasm
// https://ja.wikipedia.org/wiki/Adler-32
#include <webassembly.h>
#define MOD_ADLER 65521
uint32_t adler32(uint8_t *data, size_t len) {
uint32_t a = 1, b = 0;
while (len > 0) {
size_t tlen = len > 5550 ? 5550 : len;
len -= tlen;
do {
a += *data++;
b += a;
} while (--tlen);
a %= MOD_ADLER;
b %= MOD_ADLER;
}
return (b << 16) | a;
}
(module
(import "env" "memory" (memory 1))
(export "adler32" (func $adler32))
(func $adler32 (param $ptr i32) (param $len i32) (result i32)
(local $a i32)
(local $b i32)
(local $tlen i32)
get_local $len
i32.eqz
if
i32.const 1
return
end
i32.const 1
set_local $a
i32.const 0
set_local $b
loop $l1
get_local $len
i32.const 5550
get_local $len
get_local $len
i32.const 5550
i32.gt_u
select
tee_local $tlen
i32.sub
set_local $len
loop $l2
get_local $b
get_local $a
get_local $ptr
i32.load8_u
i32.add
tee_local $a
i32.add
set_local $b
get_local $ptr
i32.const 1
i32.add
set_local $ptr
get_local $tlen
i32.const 1
i32.sub
tee_local $tlen
br_if $l2
end
get_local $a
i32.const 65521
i32.rem_u
set_local $a
get_local $b
i32.const 65521
i32.rem_u
set_local $b
get_local $len
br_if $l1
end
get_local $b
i32.const 16
i32.shl
get_local $a
i32.or)
)
<script>
const env = {
memory: new WebAssembly.Memory({
initial: 1024,
}),
_abort: () => { },
_grow: () => { },
};
async function initWasm(path, importObject) {
const r = await fetch(path);
const b = await r.arrayBuffer();
const m = await WebAssembly.compile(b);
return await WebAssembly.instantiate(m, importObject);
}
(async () => {
const a = await initWasm("adler32.wasm", { env });
const b = await initWasm("adler32_hand.wasm", { env });
const len = 64 * 1024 * 1024
let s = performance.now();
const x = a.exports.adler32(0, len);
console.log(performance.now() - s);
s = performance.now();
const y = b.exports.adler32(0, len);
console.log(performance.now() - s);
console.log(x, y);
})();
</script>

imayaさんの http://imaya.blog.jp/archives/8858555.html のWebAssemblyバージョン。

バイナリサイズ

c to wasm 手書き
252byte 162byte

c to wasmだと余計なインポートと謎のデータセクションが生えるので不利だが、それを考慮しても手書きのほうが短い。

実行速度

64 * 1024 * 1024 の配列に対して実行してみたが、Chromeではどちらが速いとも言い難いかんじ。Firefoxではちょっと手書きのほうが速い。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment