Skip to content

Commit

Permalink
snappyUncompressor to generate snappyUncompress
Browse files Browse the repository at this point in the history
  • Loading branch information
platypii committed Feb 27, 2024
1 parent 856a659 commit 5607605
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const compressed = new Uint8Array([
0x0a, 0x24, 0x68, 0x79, 0x70, 0x65, 0x72, 0x70, 0x61, 0x72, 0x61, 0x6d
])
const output = new Uint8Array(10)
await snappyUncompress(compressed, output)
snappyUncompress(compressed, output)
```

## Development
Expand Down
5 changes: 3 additions & 2 deletions benchmark.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import { compress } from 'snappyjs'
import { snappyUncompress as uncompressWasm } from './hysnappy.js'
import { snappyUncompressor } from './hysnappy.js'

const fileSize = 200_000_000

Expand All @@ -16,7 +16,8 @@ console.log(`compressed ${fileSize.toLocaleString()} bytes to ${compressed.lengt

const output = new Uint8Array(fileSize)

timeWithStdDev('uncompress wasm', () => uncompressWasm(compressed, output))
const snappyUncompress = snappyUncompressor()
timeWithStdDev('uncompress wasm', () => snappyUncompress(compressed, output))

// time('uncompress snappyjs', () => uncompress(compressed, output))

Expand Down
5 changes: 5 additions & 0 deletions hysnappy.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
* @param {Uint8Array} output
*/
export async function snappyUncompress(input: Uint8Array, output: Uint8Array): Promise<void>

/**
* Load wasm and return uncompressor function.
*/
export function snappyUncompressor(): (input: Uint8Array, output: Uint8Array) => void
85 changes: 45 additions & 40 deletions hysnappy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,59 @@
* @param {Uint8Array} output
*/
export function snappyUncompress(input, output) {
// Load the WASM module
snappyUncompressor()(input, output)
}

/**
* Load wasm and return uncompressor function.
*
* @returns {(input: Uint8Array, output: Uint8Array) => void}
*/
export function snappyUncompressor() {
// Instantiate wasm module
const wasm = instantiateWasm()
// const { memory, uncompress } = snappyModule.instance.exports
/** @type {WebAssembly.Memory} */
// @ts-ignore
// eslint-disable-next-line prefer-destructuring
const memory = wasm.exports.memory
/** @type {Function} */
// @ts-ignore
// eslint-disable-next-line prefer-destructuring
const uncompress = wasm.exports.uncompress

// Input data is passed into wasm memory at inputStart
// Output data is expected to be written to wasm memory at outputStart
// clang uses some wasm memory, so we need to skip past that
const inputStart = 68000 // 68 kb
const outputStart = inputStart + input.byteLength
return (input, output) => {
/** @type {any} */
const { memory, uncompress } = wasm.exports

// WebAssembly memory
const totalSize = inputStart + input.byteLength + output.byteLength
if (memory.buffer.byteLength < totalSize) {
// Calculate the number of pages needed, rounding up
const pageSize = 64 * 1024 // 64KiB per page
const currentPages = memory.buffer.byteLength / pageSize
const requiredPages = Math.ceil(totalSize / pageSize)
const pagesToGrow = requiredPages - currentPages
memory.grow(pagesToGrow)
}
// Input data is passed into wasm memory at inputStart
// Output data is expected to be written to wasm memory at outputStart
// clang uses some wasm memory, so we need to skip past that
const inputStart = 68000 // 68 kb
const outputStart = inputStart + input.byteLength

// Copy the compressed data to WASM memory
const byteArray = new Uint8Array(memory.buffer)
byteArray.set(input, inputStart)
// WebAssembly memory
const totalSize = inputStart + input.byteLength + output.byteLength
if (memory.buffer.byteLength < totalSize) {
// Calculate the number of pages needed, rounding up
const pageSize = 64 * 1024 // 64KiB per page
const currentPages = memory.buffer.byteLength / pageSize
const requiredPages = Math.ceil(totalSize / pageSize)
const pagesToGrow = requiredPages - currentPages
memory.grow(pagesToGrow)
}

// Call wasm uncompress function
const result = uncompress(inputStart, input.byteLength, outputStart)
// Copy the compressed data to WASM memory
const byteArray = new Uint8Array(memory.buffer)
byteArray.set(input, inputStart)

// Check for errors
if (result === -1) throw new Error('invalid snappy length header')
if (result === -2) throw new Error('missing eof marker')
if (result === -3) throw new Error('premature end of input')
if (result) throw new Error(`failed to uncompress data ${result}`)
// Call wasm uncompress function
const result = uncompress(inputStart, input.byteLength, outputStart)

// Get uncompressed data from WASM memory
const uncompressed = byteArray.slice(outputStart, outputStart + output.byteLength)
// Check for errors
if (result === -1) throw new Error('invalid snappy length header')
if (result === -2) throw new Error('missing eof marker')
if (result === -3) throw new Error('premature end of input')
if (result) throw new Error(`failed to uncompress data ${result}`)

// Copy the uncompressed data to the output buffer
// TODO: Return WASM memory buffer instead of copying?
output.set(uncompressed)
// Get uncompressed data from WASM memory
const uncompressed = byteArray.slice(outputStart, outputStart + output.byteLength)

// Copy the uncompressed data to the output buffer
// TODO: Return WASM memory buffer instead of copying?
output.set(uncompressed)
}
}

/**
Expand Down

0 comments on commit 5607605

Please sign in to comment.