javascriptのハッシュライブラリを比較する

# javascriptのハッシュライブラリを比較する

## 概要

javascript向けのハッシュライブラリの性能が気になり調査した。

調べたライブラリは以下

* `js-xxhash`  [https://github.com/pierrec/js-xxhash](https://github.com/pierrec/js-xxhash "Javascript implementation of xxHash") xxHash pure js実装
* `xxhash-wasm`  [https://github.com/jungomi/xxhash-wasm](https://github.com/jungomi/xxhash-wasm "A WebAssembly implementation of xxHash") xxHash WebAssembly実装
* `cybozulabs/sha1`  [http://labs.cybozu.co.jp/blog/mitsunari/2007/07/sha1_1.html](http://labs.cybozu.co.jp/blog/mitsunari/2007/07/sha1_1.html "JavaScriptでSHA-1を計算するライブラリ")
* `cybozulabs/md5`  [http://labs.cybozu.co.jp/blog/mitsunari/2007/07/md5js_1.html](http://labs.cybozu.co.jp/blog/mitsunari/2007/07/md5js_1.html "JavaScriptでMD5を計算するライブラリ")
* `crypto-js`  [https://github.com/brix/crypto-js](https://github.com/brix/crypto-js "JavaScript library of crypto standards.")
* `sjcl`  [https://github.com/bitwiseshiftleft/sjcl](https://github.com/bitwiseshiftleft/sjcl "Stanford Javascript Crypto Library")
* `emn178/js-sha1`  [https://github.com/emn178/js-sha1](https://github.com/emn178/js-sha1 "A simple SHA1 hash function for JavaScript supports UTF-8 encoding.")
* `emn178/js-sha256`  [https://github.com/emn178/js-sha256](https://github.com/emn178/js-sha256 "A simple SHA-256 / SHA-224 hash function for JavaScript supports UTF-8 encoding.")
* `emn178/js-md5`  [https://github.com/emn178/js-md5](https://github.com/emn178/js-md5 "A simple MD5 hash function for JavaScript supports UTF-8 encoding.")
* `rusha`  [https://github.com/srijs/rusha](https://github.com/srijs/rusha "High-performance pure-javascript SHA1 implementation suitable for large binary data, reaching up to half the native speed.") asm.js利用したSHA-1
* `forge`  [https://github.com/digitalbazaar/forge](https://github.com/digitalbazaar/forge "A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps")
* `bitcoin-ts`  [https://github.com/bitjson/bitcoin-ts](https://github.com/bitjson/bitcoin-ts "WebAssembly versions of secp256k1, ripemd160, sha256, sha512, and sha1") SHA-1,SHA-256等の WebAssembly実装

## 調査方法

ハッシュアルゴリズムは

* xxHash
* SHA-1
* SHA-256
* MD5

のみを対象とする。

入力データとしては

* 文字列(String)
* ファイルデータ(ArrayBuffer,未対応ならバイナリ文字列)

調査対象ブラウザは、Windows7 の Firefox63, Google Chrome70, IE11。
ただし、IE11はWebAssemblyが未サポートなので `xxhash-wasm`, `bitcoin-ts` は動作しない

## 各ライブラリの特徴と準備

ライブラリによっては、入力が文字列限定であったり、ファイルの読み込み(ArrayBuffer)に対応しておらず独自形式でないといけなかったりする。
ライブラリ毎に入力形式を工夫し、場合によっては一部改変した。

* `xxhash-wasm`: 対応している入力が文字列のみであったので、ArrayBufferにも対応出来るよう改造した
* `cybozulabs/sha1`: 対応しているのはバイナリ文字列のみ(charCodeAt(i)の返値がuint8を想定)なのでArrayBuffer対応した改造版を作成し `cybozulabs/sha1(AB)` とした
* `crypto-js/sha1`,`sha256`,`md5`: 入力が文字列かCryptoJS独自のWordArrayオブジェクトなので、ArrayBufferをWordArrayへ変換する処理を追加した。また、省メモリ化のためAraryBufferを何回かに分けてWordArrayに変換する方式を追加し `crypto-js/sha1(AB)` として別に計測した。
* `forge/sha1`: 入力が文字列のみなので、ArrayBufferをバイナリ文字列に変換する処理を追加した
* `bitcoin-ts/sha1`,`sha256`: 配布されているjsファイルがそのままでは動作しなかったためwebpackでbundle.jsを作成している

特に `xxhash-wasm` のArrayBuffer対応は効果が大きかったので最後に参考として載せておく

## 調査結果まとめ

実験結果の詳細は長くなるので末尾に列挙した。
かなりざっくりまとめると、

* `xxhash-wasm` がダントツで早い(Firefoxで他の10倍以上、Chromeは1.9倍以上)
* WebAssembly や asm.js を利用してないライブラリの中では `js-xxhash` が早く、次点で `emn178/sha1`, `emn178/sha256` が良いか

アルゴリズム別には

* xxHashに限ると、予想どおり `xxhash-wasm` ＞ `js-xxhash` となる
* SHA-1に限ると、入力が文字列なら `emn178/sha1`, `rusha` が早く、ファイルなら WebAssembly実装の `bitcoin-ts` が早く、次いで `emn178/sha1`, `rusha` が良いか
* SHA-256は、入力が文字列なら `emn178/sha256` が早い。ファイルなら `bitncoin-ts/sha256` が早くなる
* MD5は、文字列なら `emn178/md5` か `forge/md5`、ファイルなら `emn178/md5` が早い

ブラウザ別に見ると

* Firefox は WebAssembly や asm.js の効果が大きいように感じる
* Chrome も Firefox ほどではないが WebAssembly, asm.js が効果的
* ただ、Chrome の場合は asm.js 対応してない('use asm'表記がない) コードでも最適化がかかって早くなる場合があるようだ
* IE11 は全体的にかなり遅く、素直にアルゴリズムの違いだけが効いているように見える(xxHashが早く,MD5,SHA-1,SHA-256と続く)


## 実験結果詳細1 - 文字列データの場合

入力する文字列データは、短いもの(約20KB)と長いもの(約400KB)の2種類を用意した。
ブラウザ別に実験し以下の結果になった。

### Firefox small text

| Hash方法          | 計算結果(hex)                                                    | 平均処理時間(msec)  | 効率(MB/s) |
|-------------------|------------------------------------------------------------------|---------------------|------------|
| xxhash-wasm       | f05b7932                                                         |  0                  | -          |
| xxhash-wasm(64b)  | f8b7fe989ec9325                                                  |  0.1                | 193.30     |
| emn178/sha1       | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  1.4                |  13.80     |
| emn178/sha256     | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 |  1.8                |  10.73     |
| forge/md5         | 4c1b17b77cf1722c5d0b356d11e8abcb                                 |  1.8                |  10.73     |
| forge/sha256      | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 |  2                  |   9.66     |
| forge/sha1        | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  2.1                |   9.20     |
| crypto-js/sha1    | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  2.3                |   8.40     |
| crypto-js/sha256  | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 |  2.3                |   8.40     |
| bitcoin-ts/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 |  2.7                |   7.15     |
| crypto-js/md5     | 4c1b17b77cf1722c5d0b356d11e8abcb                                 |  2.8                |   6.90     |
| bitcoin-ts/sha1   | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  2.8                |   6.90     |
| js-xxhash         | f05b7932                                                         |  2.9                |   6.66     |
| sjcl/sha256       | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 |  3.3                |   5.85     |
| sjcl/sha1         | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  3.9                |   4.95     |
| js-xxhash(64b)    | f8b7fe9809ec9325                                                 |  4.1                |   4.71     |
| cybozulabs/sha1   | 94ad35fcd68600626afa83d2778c867cb2dac8a6                         |  5.1                |   3.79     |
| rusha             | 7d1206ee3a4995913de8857a962e48e970e2333e                         |  6.4                |   3.02     |
| emn178/md5        | 4c1b17b77cf1722c5d0b356d11e8abcb                                 |  7.1                |   2.72     |
| cybozulabs/md5    | 4c1b17b77cf1722c5d0b356d11e8abcb                                 | 10.1                |   1.91     |

### Firefox large text

| Hash方法        | 計算結果(hex)                                                    | 平均処理時間(msec) | 効率(MB/s) |
|-----------------|------------------------------------------------------------------|--------------------|------------|
|xxhash-wasm(64b) | dfc791976d97d7d1                                                 | 1.33               | 313.43     |
|xxhash-wasm      | 7afefb09                                                         | 1.66               | 250.74     |
|emn178/sha1      | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 12                 |  34.82     |
|rusha            | 543e7997382a1c77fdd12d9801c49dab66c74ed5                         | 17                 |  24.58     |
|emn178/sha256    | 0cd37dd229068c9d9a848b8cc8d2cc6cbb41db6008a2a4da0c2c4d60a62804be | 17.33              |  24.11     |
|js-xxhash        | 7afefb09                                                         | 19.33              |  21.61     |
|forge/md5        | da467abe0c39983a2c232142ec6768bd                                 | 21.66              |  19.28     |
|forge/sha1       | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 25.66              |  16.28     |
|forge/sha256     | 0cd37dd229068c9d9a848b8cc8d2cc6cbb41db6008a2a4da0c2c4d60a62804be | 28                 |  14.92     |
|crypto-js/sha1   | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 29.33              |  14.24     |
|crypto-js/md5    | da467abe0c39983a2c232142ec6768bd                                 | 29.33              |  14.24     |
|crypto-js/sha256 | 0cd37dd229068c9d9a848b8cc8d2cc6cbb41db6008a2a4da0c2c4d60a62804be | 30.66              |  13.62     |
|emn178/md5       | da467abe0c39983a2c232142ec6768bd                                 | 32.33              |  12.92     |
|js-xxhash(64b)   | dfc791976d97d7d1                                                 | 42.66              |   9.79     |
|bitcoin-ts/sha1  | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 48.66              |   8.58     |
|bitcoin-ts/sha256| 0cd37dd229068c9d9a848b8cc8d2cc6cbb41db6008a2a4da0c2c4d60a62804be | 48.66              |   8.58     |
|sjcl/sha1        | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 53.66              |   7.78     |
|cybozulabs/sha1  | 4d92b1fb281d8438c2156aa7a92bdb7a89857137                         | 78.33              |   5.33     |
|sjcl/sha256      | 0cd37dd229068c9d9a848b8cc8d2cc6cbb41db6008a2a4da0c2c4d60a62804be | 84.66              |   4.93     |
|cybozulabs/md5   | da467abe0c39983a2c232142ec6768bd                                 | 123.33             |   3.38     |

### Google Chrome small text

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm(64b) | f8b7fe989ec9325 | 0.20 | 96.65 |
| xxhash-wasm | f05b7932 | 0.25 | 74.34 |
| bitcoin-ts/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 0.89 | 21.47 |
| bitcoin-ts/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 1.01 | 18.95 |
| rusha | 7d1206ee3a4995913de8857a962e48e970e2333e | 1.60 | 12.00 |
| crypto-js/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 1.85 | 10.39 |
| sjcl/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 2.04 | 9.47 |
| emn178/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 2.39 | 8.08 |
| sjcl/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 2.53 | 7.61 |
| emn178/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 2.57 | 7.49 |
| js-xxhash | f05b7932 | 2.68 | 7.18 |
| forge/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 2.79 | 6.90 |
| forge/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 2.86 | 6.73 |
| crypto-js/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 3.25 | 5.94 |
| emn178/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 3.49 | 5.52 |
| crypto-js/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 3.74 | 5.16 |
| forge/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 3.90 | 4.95 |
| cybozulabs/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 4.52 | 4.27 |
| cybozulabs/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 5.28 | 3.66 |
| js-xxhash(64b) | f8b7fe9809ec9325 | 5.62 | 3.43 |


### Google Chrome large text

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm | eca4534b | 4.30 | 96.96 |
| xxhash-wasm(64b) | a914651cee9e302a | 4.33 | 96.29 |
| rusha | 55eebdc91a5cddfd3cbeca9046519d06fbf9fccd | 7.76 | 53.85 |
| emn178/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 9.53 | 43.80 |
| emn178/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 14.70 | 28.42 |
| emn178/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 16.25 | 25.70 |
| forge/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 21.57 | 19.36 |
| forge/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 21.91 | 19.07 |
| js-xxhash | eca4534b | 22.20 | 18.81 |
| forge/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 23.68 | 17.64 |
| crypto-js/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 28.57 | 14.62 |
| bitcoin-ts/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 28.64 | 14.58 |
| bitcoin-ts/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 29.07 | 14.37 |
| cybozulabs/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 30.04 | 13.91 |
| crypto-js/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 30.09 | 13.88 |
| sjcl/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 30.93 | 13.51 |
| sjcl/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 31.06 | 13.45 |
| cybozulabs/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 31.07 | 13.45 |
| crypto-js/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 33.90 | 12.32 |
| js-xxhash(64b) | a914651cee9e302a | 68.68 | 6.08 |

### IE11 small text

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|-------------------:|-----------:|
| js-xxhash | f05b7932 | 3.72 | 5.19 |
| emn178/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 4.05 | 4.76 |
| emn178/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 4.65 | 4.14 |
| cybozulabs/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 5.33 | 3.62 |
| emn178/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 5.41 | 3.57 |
| forge/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 5.45 | 3.54 |
| rusha | 7d1206ee3a4995913de8857a962e48e970e2333e | 5.69 | 3.39 |
| forge/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 6.45 | 2.99 |
| crypto-js/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 6.59 | 2.93 |
| crypto-js/md5 | 4c1b17b77cf1722c5d0b356d11e8abcb | 6.73 | 2.87 |
| js-xxhash(64b) | f8b7fe9809ec9325 | 7.78 | 2.48 |
| cybozulabs/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 7.99 | 2.41 |
| sjcl/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 8.58 | 2.25 |
| forge/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 9.03 | 2.14 |
| sjcl/sha256 | 6288860b7dbf8f30809ab39fc0739dad583356f42096b9fa204a4091920bd5c3 | 9.82 | 1.96 |
| crypto-js/sha1 | 94ad35fcd68600626afa83d2778c867cb2dac8a6 | 14.76 | 1.30 |

### IE11 large text

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| js-xxhash | eca4534b | 38.85 | 10.75 |
| emn178/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 39.79 | 10.50 |
| emn178/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 55.51 | 7.52 |
| emn178/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 80.77 | 5.17 |
| cybozulabs/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 82.55 | 5.06 |
| rusha | 55eebdc91a5cddfd3cbeca9046519d06fbf9fccd | 84.26 | 4.95 |
| cybozulabs/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 102.55 | 4.07 |
| crypto-js/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 103.46 | 4.03 |
| forge/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 105.80 | 3.94 |
| crypto-js/md5 | 1ad061d3f2e1ae832d694d726959fe7c | 110.58 | 3.77 |
| forge/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 112.60 | 3.71 |
| crypto-js/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 133.32 | 3.13 |
| forge/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 149.48 | 2.79 |
| js-xxhash(64b) | a914651cee9e302a | 151.64 | 2.75 |
| sjcl/sha256 | bb65dcfe9f9d63ff4d4e322257c3e281a3a0227435b242cc082145ebcc6c859d | 174.77 | 2.39 |
| sjcl/sha1 | 0a18490021f260c8eea9ddb0d9a91f176ca655f9 | 193.45 | 2.16 |


## 実験結果詳細2 - ファイルデータの場合

ファイルデータも2種類、約1MBのものと約50MBのものを用意した。
これもブラウザ毎に検証した。

### Firefox small file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm | 46414a05 | 1 | 1072.46 |
| xxhash-wasm(64b) | ff0b0c9fd8e4844 | 1 | 1072.46 |
| bitcoin-ts/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 12 | 89.37 |
| bitcoin-ts/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 16 | 67.02 |
| emn178/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 32 | 33.51 |
| rusha | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 35 | 30.64 |
| js-xxhash | 46414a05 | 40 | 26.81 |
| crypto-js/md5(AB) | b12c69e74ea938b432916c7d4b9523a3 | 41 | 26.15 |
| crypto-js/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 42 | 25.53 |
| crypto-js/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 43 | 24.94 |
| crypto-js/md5 | b12c69e74ea938b432916c7d4b9523a3 | 47 | 22.81 |
| crypto-js/sha256(AB) | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 48 | 22.34 |
| emn178/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 48 | 22.34 |
| crypto-js/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 49 | 21.88 |
| cybozulabs/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 70 | 15.32 |
| emn178/md5 | b12c69e74ea938b432916c7d4b9523a3 | 90 | 11.91 |
| sjcl/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 107 | 10.02 |
| js-xxhash(64b) | ff0b0c9fd8e4844 | 123 | 8.71 |
| forge/md5 | b12c69e74ea938b432916c7d4b9523a3 | 138 | 7.77 |
| forge/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 148 | 7.24 |
| forge/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 154 | 6.96 |
| cybozulabs/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 187 | 5.73 |
| cybozulabs/md5 | b12c69e74ea938b432916c7d4b9523a3 | 320 | 3.35 |
| sjcl/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 1028 | 1.04 |

### Firefox large file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm(64b) | 4407011eb470e572 | 28 | 1677.72 |
| xxhash-wasm | c7f44ffa | 29 | 1619.87 |
| emn178/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 445 | 105.56 |
| bitcoin-ts/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 511 | 91.93 |
| js-xxhash | c7f44ffa | 601 | 78.16 |
| bitcoin-ts/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 630 | 74.56 |
| rusha | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 935 | 50.24 |
| emn178/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 1110 | 42.32 |
| emn178/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 1634 | 28.74 |
| crypto-js/md5(AB) | 61d52ad7a06a226c0c65121fc92b3f8a | 1669 | 28.14 |
| crypto-js/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 1786 | 26.30 |
| crypto-js/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 1913 | 24.55 |
| crypto-js/sha256(AB) | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 1969 | 23.85 |
| crypto-js/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 2077 | 22.61 |
| crypto-js/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 2315 | 20.29 |
| cybozulabs/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 2472 | 19.00 |
| js-xxhash(64b) | 4407011eb470e572 | 4354 | 10.78 |
| sjcl/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 4468 | 10.51 |
| forge/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 5879 | 7.99 |
| cybozulabs/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 5927 | 7.92 |
| forge/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 5990 | 7.84 |
| forge/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 6532 | 7.19 |
| cybozulabs/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 7458 | 6.29 |
| sjcl/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 43857 | 1.07 |

### Google Chrome small file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm(64b) | ff0b0c9fd8e4844 | 0.59 | 1787.44 |
| xxhash-wasm | 46414a05 | 1.10 | 974.97 |
| bitcoin-ts/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 20.99 | 51.06 |
| bitcoin-ts/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 22.30 | 48.09 |
| rusha | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 22.89 | 46.83 |
| js-xxhash | 46414a05 | 34.89 | 30.72 |
| emn178/md5 | b12c69e74ea938b432916c7d4b9523a3 | 35.29 | 30.38 |
| emn178/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 41.80 | 25.65 |
| emn178/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 44.69 | 23.99 |
| crypto-js/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 54.70 | 19.60 |
| sjcl/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 56.59 | 18.94 |
| sjcl/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 60.69 | 17.66 |
| cybozulabs/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 61.60 | 17.41 |
| crypto-js/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 64.99 | 16.49 |
| crypto-js/sha256(AB) | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 71.90 | 14.91 |
| crypto-js/md5(AB) | b12c69e74ea938b432916c7d4b9523a3 | 83.99 | 12.76 |
| crypto-js/md5 | b12c69e74ea938b432916c7d4b9523a3 | 84.29 | 12.72 |
| crypto-js/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 91.40 | 11.73 |
| js-xxhash(64b) | ff0b0c9fd8e4844 | 180.10 | 5.95 |
| forge/md5 | b12c69e74ea938b432916c7d4b9523a3 | 302.60 | 3.54 |
| forge/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 309.40 | 3.46 |
| forge/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 313.29 | 3.42 |
| cybozulabs/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 336.20 | 3.18 |
| cybozulabs/md5 | b12c69e74ea938b432916c7d4b9523a3 | 339.19 | 3.16 |

### Google Chrome large file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| xxhash-wasm | c7f44ffa | 41.99 | 1118.48 |
| xxhash-wasm(64b) | 4407011eb470e572 | 93.79 | 500.81 |
| cybozulabs/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 343.80 | 136.63 |
| emn178/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 376.59 | 124.73 |
| js-xxhash | c7f44ffa | 397.69 | 118.12 |
| rusha | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 636.20 | 73.83 |
| bitcoin-ts/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 938.99 | 50.02 |
| bitcoin-ts/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 1071.89 | 43.82 |
| emn178/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 1073.30 | 43.76 |
| emn178/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 1552.29 | 30.26 |
| crypto-js/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 1872.59 | 25.08 |
| sjcl/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 1935.79 | 24.26 |
| crypto-js/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 2013.69 | 23.32 |
| crypto-js/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 2036.70 | 23.06 |
| crypto-js/sha256(AB) | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 2144.49 | 21.90 |
| crypto-js/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 2217.30 | 21.18 |
| crypto-js/md5(AB) | 61d52ad7a06a226c0c65121fc92b3f8a | 2225.70 | 21.10 |
| sjcl/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 4466.49 | 10.51 |
| js-xxhash(64b) | 4407011eb470e572 | 4864.89 | 9.65 |
| cybozulabs/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 12226.80 | 3.84 |
| forge/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 12279.40 | 3.82 |
| cybozulabs/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 12406.39 | 3.78 |
| forge/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 12446.89 | 3.77 |
| forge/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 12615.49 | 3.72 |

### IE11 small file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| js-xxhash | 46414a05 | 361.79 | 2.96 |
| emn178/md5 | b12c69e74ea938b432916c7d4b9523a3 | 850.19 | 1.26 |
| cybozulabs/md5 | b12c69e74ea938b432916c7d4b9523a3 | 877.59 | 1.22 |
| js-xxhash(64b) | ff0b0c9fd8e4844 | 1088.59 | 0.98 |
| forge/md5 | b12c69e74ea938b432916c7d4b9523a3 | 1120.30 | 0.95 |
| crypto-js/md5(AB) | b12c69e74ea938b432916c7d4b9523a3 | 1137.00 | 0.94 |
| crypto-js/md5 | b12c69e74ea938b432916c7d4b9523a3 | 1159.29 | 0.92 |
| cybozulabs/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1392.29 | 0.77 |
| cybozulabs/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1537.50 | 0.69 |
| emn178/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1599.99 | 0.67 |
| crypto-js/sha1(AB) | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1624.90 | 0.66 |
| crypto-js/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1657.09 | 0.64 |
| forge/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 1683.39 | 0.63 |
| sjcl/sha1 | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 2108.50 | 0.50 |
| rusha | 4a7fae7142387b7c72d92271d491ee8e7ac62177 | 2473.19 | 0.43 |
| sjcl/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 2561.60 | 0.41 |
| emn178/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 2752.19 | 0.38 |
| crypto-js/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 2799.20 | 0.38 |
| crypto-js/sha256(AB) | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 2815.80 | 0.38 |
| forge/sha256 | 3693c5eae807139a7d25744aa46fda52e342081426213c8172c0aa428eefabaa | 2879.90 | 0.37 |

### IE11 large file

| Hash方法 | 計算結果(hex) | 平均処理時間(msec) | 効率(MB/s) |
|----------|---------------|--------------------|------------|
| js-xxhash | c7f44ffa | 14574.69 | 3.22 |
| emn178/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 36746.40 | 1.27 |
| cybozulabs/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 38677.59 | 1.21 |
| forge/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 40836.70 | 1.15 |
| crypto-js/md5(AB) | 61d52ad7a06a226c0c65121fc92b3f8a | 43548.40 | 1.07 |
| js-xxhash(64b) | 4407011eb470e572 | 45746.10 | 1.02 |
| crypto-js/md5 | 61d52ad7a06a226c0c65121fc92b3f8a | 48135.69 | 0.97 |
| cybozulabs/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 61327.30 | 0.76 |
| rusha | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 64682.59 | 0.72 |
| crypto-js/sha1(AB) | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 66047.49 | 0.71 |
| cybozulabs/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 66253.00 | 0.70 |
| forge/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 66877.60 | 0.70 |
| crypto-js/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 67165.09 | 0.69 |
| emn178/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 69002.79 | 0.68 |
| sjcl/sha1 | 4c8a902c2f6c387ae1a9841e4cfb1094abf2010b | 95946.60 | 0.48 |
| crypto-js/sha256(AB) | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 116144.70 | 0.40 |
| sjcl/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 116869.60 | 0.40 |
| emn178/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 119427.89 | 0.39 |
| forge/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 122898.69 | 0.38 |
| crypto-js/sha256 | 317e4f1eaf6185cd7d27e8c60b745f52b463f611fc2a23a148d3b61337be2f6e | 124765.89 | 0.37 |

## 改造箇所

### xxhash-wasm (xxhash-wasm-0.3.1)

xxhash-wasm/src/index.js 27行目,35行目付近

入力の `str` を `encoder.encode(str)` でエンコードしてしまっているので
String型じゃないときはスルーするようにしている。

```diff
--- xxhash-wasm-0.3.1/src/index.js.original
+++ xxhash-wasm-0.3.1/src/index.js
@@ -27 +27 @@ async function xxhash() {
-      const strBuffer = encoder.encode(str);
+      const strBuffer = typeof str === 'string' ? encoder.encode(str) : str;
@@ -35 +35 @@ async function xxhash() {
-      const strBuffer = encoder.encode(str);
+      const strBuffer = typeof str === 'string' ? encoder.encode(str) : str;
```

こうしておけば

```js
xxhash().then(function(hasher) {
  console.log(hasher.h32(new Uint8Array([97, 98, 99])));
});
```

のようにして Uint8Array オブジェクトを引数として渡せるようになる。