imayaさんの http://imaya.blog.jp/archives/8858555.html のWebAssemblyバージョン。
c to wasm | 手書き |
---|---|
252byte | 162byte |
c to wasmだと余計なインポートと謎のデータセクションが生えるので不利だが、それを考慮しても手書きのほうが短い。
64 * 1024 * 1024 の配列に対して実行してみたが、Chromeではどちらが速いとも言い難いかんじ。Firefoxではちょっと手書きのほうが速い。
// 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ではちょっと手書きのほうが速い。