Skip to content

Instantly share code, notes, and snippets.

@cgiosy
Last active June 29, 2022 23:16
Show Gist options
  • Save cgiosy/f85c934d5c989cc000ddbf2abdf79ac9 to your computer and use it in GitHub Desktop.
Save cgiosy/f85c934d5c989cc000ddbf2abdf79ac9 to your computer and use it in GitHub Desktop.
XXHash32 JS Implementation
const getUint32 = (arr: Uint8Array, i: number) => (
arr[i] | arr[i + 1 | 0] << 8 | arr[i + 2 | 0] << 16 | arr[i + 3 | 0] << 24
);
const rotl32 = (x: number, r: number) => (x << r) | (x >>> 32 - r);
const xxh32 = (buf: Uint8Array, seed = 0) => {
seed |= 0;
const len = buf.length | 0;
let i = 0;
let h = (seed + len | 0) + 0x165667B1 | 0;
if (len < 16) {
for (; (i + 3 | 0) < len; i = i + 4 | 0)
h = Math.imul(rotl32(h + Math.imul(getUint32(buf, i), 0xC2B2AE3D) | 0, 17), 0x27D4EB2F);
} else {
let v0 = seed + 0x24234428 | 0;
let v1 = seed + 0x85EBCA77 | 0;
let v2 = seed;
let v3 = seed - 0x9E3779B1 | 0;
if (len < 256) {
for (; (i + 15 | 0) < len; i = i + 16 | 0) {
v0 = Math.imul(rotl32(v0 + Math.imul(getUint32(buf, i + 0 | 0), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v1 = Math.imul(rotl32(v1 + Math.imul(getUint32(buf, i + 4 | 0), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v2 = Math.imul(rotl32(v2 + Math.imul(getUint32(buf, i + 8 | 0), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v3 = Math.imul(rotl32(v3 + Math.imul(getUint32(buf, i + 12 | 0), 0x85EBCA77) | 0, 13), 0x9E3779B1);
}
h = (((rotl32(v0, 1) + rotl32(v1, 7) | 0) + rotl32(v2, 12) | 0) + rotl32(v3, 18) | 0) + len | 0;
for (; (i + 3 | 0) < len; i = i + 4 | 0)
h = Math.imul(rotl32(h + Math.imul(getUint32(buf, i), 0xC2B2AE3D) | 0, 17), 0x27D4EB2F);
} else {
const view = new DataView(buf.buffer);
for (; (i + 15 | 0) < len; i = i + 16 | 0) {
v0 = Math.imul(rotl32(v0 + Math.imul(view.getUint32(i + 0 | 0, true), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v1 = Math.imul(rotl32(v1 + Math.imul(view.getUint32(i + 4 | 0, true), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v2 = Math.imul(rotl32(v2 + Math.imul(view.getUint32(i + 8 | 0, true), 0x85EBCA77) | 0, 13), 0x9E3779B1);
v3 = Math.imul(rotl32(v3 + Math.imul(view.getUint32(i + 12 | 0, true), 0x85EBCA77) | 0, 13), 0x9E3779B1);
}
h = (((rotl32(v0, 1) + rotl32(v1, 7) | 0) + rotl32(v2, 12) | 0) + rotl32(v3, 18) | 0) + len | 0;
for (; (i + 3 | 0) < len; i = i + 4 | 0)
h = Math.imul(rotl32(h + Math.imul(view.getUint32(i, true), 0xC2B2AE3D) | 0, 17), 0x27D4EB2F);
}
}
for (; i < len; i = i + 1 | 0)
h = Math.imul(rotl32(h + Math.imul(buf[i], 0x165667B1) | 0, 11), 0x9E3779B1);
h = Math.imul(h ^ h >>> 15, 0x85EBCA77);
h = Math.imul(h ^ h >>> 13, 0xC2B2AE3D);
return (h ^ h >>> 16) >>> 0;
};
export default xxh32;
@cgiosy
Copy link
Author

cgiosy commented Apr 23, 2022

Usage: xxh32(new TextEncoder().encode("test"))
Size: Minified < 1.6kb, Gzip < 0.5kb

@cgiosy
Copy link
Author

cgiosy commented Apr 23, 2022

Benchmark

# Throughput - 16 bytes
xxh32.js: 233.05165950866152 MB/s
hash-wasm.xxhash32: 65.2451403877805 MB/s
hash-wasm.xxhash64: 33.463045859622625 MB/s
hash-wasm.xxhash128: 26.104324164081667 MB/s
hash-wasm.xxhash3: 33.16877614561841 MB/s
hash-wasm.crc32: 60.72135141026678 MB/s
hash-wasm.blake3: 20.083299196822654 MB/s
hash-wasm.sha1: 21.31338591657368 MB/s
hash-wasm.sha256: 17.204622334383593 MB/s
hash-wasm.sha512: 10.519422118677038 MB/s
hash-wasm.sha3: 10.87381065579847 MB/s
hash-wasm.md5: 26.94183066115019 MB/s

# Throughput - 256 bytes
xxh32.js: 1459.0742013673616 MB/s
hash-wasm.xxhash32: 912.3366422516513 MB/s
hash-wasm.xxhash64: 555.7804742286385 MB/s
hash-wasm.xxhash128: 435.8167534892718 MB/s
hash-wasm.xxhash3: 522.0287774049153 MB/s
hash-wasm.crc32: 677.6684432194427 MB/s
hash-wasm.blake3: 278.8266499607441 MB/s
hash-wasm.sha1: 241.16285718396705 MB/s
hash-wasm.sha256: 160.20225160477395 MB/s
hash-wasm.sha512: 136.34390737987852 MB/s
hash-wasm.sha3: 123.41993041591684 MB/s
hash-wasm.md5: 255.2523216864908 MB/s

# Throughput - 4096 bytes
xxh32.js: 5825.412345695758 MB/s
hash-wasm.xxhash32: 4824.87418061821 MB/s
hash-wasm.xxhash64: 5295.7885934688375 MB/s
hash-wasm.xxhash128: 4183.324814999695 MB/s
hash-wasm.xxhash3: 4639.759417730065 MB/s
hash-wasm.crc32: 1775.2268904489122 MB/s
hash-wasm.blake3: 750.7761200245818 MB/s
hash-wasm.sha1: 678.8332389393644 MB/s
hash-wasm.sha256: 326.52230774914324 MB/s
hash-wasm.sha512: 479.2395482756276 MB/s
hash-wasm.sha3: 297.6650603055725 MB/s
hash-wasm.md5: 486.35204339833297 MB/s

# Throughput - 65536 bytes
xxh32.js: 7117.317183501204 MB/s
hash-wasm.xxhash32: 6217.269224283 MB/s
hash-wasm.xxhash64: 10626.99709827573 MB/s
hash-wasm.xxhash128: 8502.518078010455 MB/s
hash-wasm.xxhash3: 8641.513626457921 MB/s
hash-wasm.crc32: 1963.6240093152837 MB/s
hash-wasm.blake3: 811.5914462901178 MB/s
hash-wasm.sha1: 760.5687346096273 MB/s
hash-wasm.sha256: 345.45550246387756 MB/s
hash-wasm.sha512: 546.3248935564654 MB/s
hash-wasm.sha3: 318.26581203555975 MB/s
hash-wasm.md5: 513.8385025591177 MB/s

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