Skip to content

Commit

Permalink
fix: memory leak (#29)
Browse files Browse the repository at this point in the history
Memory leak was caused by
rustwasm/wee_alloc#106. This PR fixes the leak
by removes lightweight allocator

I have also added a test, which is now disabled, that hashes 17GB in a
loop to verify expected memory use. Test is disabled because it takes a
long time to run.
  • Loading branch information
Gozala committed Dec 7, 2023
1 parent a5b1301 commit c1fad61
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 129 deletions.
61 changes: 7 additions & 54 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions cargo.toml
Expand Up @@ -8,7 +8,7 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]

[features]
default = ["console_error_panic_hook", "wee_alloc"]
default = ["console_error_panic_hook"]

[dependencies]
wasm-bindgen = "0.2.84"
Expand All @@ -20,12 +20,6 @@ unsigned-varint = "0.7.2"
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }

# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.5", optional = true }
web-sys = { version = "0.3.61", features = [
"console",
"Window",
Expand Down
3 changes: 2 additions & 1 deletion gen/wasm.d.ts
Expand Up @@ -48,12 +48,13 @@ export interface InitOutput {
readonly __wbg_piecehasher_free: (a: number) => void;
readonly piecehasher_count: (a: number) => number;
readonly piecehasher_reset: (a: number) => void;
readonly piecehasher_write: (a: number, b: number, c: number) => void;
readonly piecehasher_write: (a: number, b: number, c: number, d: number) => void;
readonly piecehasher_digestInto: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number;
readonly piecehasher_digestByteLength: (a: number) => number;
readonly piecehasher_multihashByteLength: (a: number) => number;
readonly create: () => number;
readonly piecehasher_create: () => number;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_malloc: (a: number, b: number) => number;
}

Expand Down
62 changes: 43 additions & 19 deletions gen/wasm.js
@@ -1,20 +1,6 @@
// @ts-nocheck
let wasm;

let cachedUint8Memory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}

function getArrayU8FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}

const heap = new Array(128).fill(undefined);

heap.push(undefined, null, true, false);
Expand All @@ -35,6 +21,20 @@ function takeObject(idx) {
return ret;
}

let cachedUint8Memory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}

function getArrayU8FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}

const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );

if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
Expand All @@ -53,6 +53,15 @@ function passArray8ToWasm0(arg, malloc) {
return ptr;
}

let cachedInt32Memory0 = null;

function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}

function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
Expand Down Expand Up @@ -120,9 +129,19 @@ export class PieceHasher {
* @param {Uint8Array} bytes
*/
write(bytes) {
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.piecehasher_write(this.__wbg_ptr, ptr0, len0);
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.piecehasher_write(retptr, this.__wbg_ptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
if (r1) {
throw takeObject(r0);
}
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
/**
* @param {Uint8Array} target
Expand Down Expand Up @@ -186,11 +205,15 @@ async function __wbg_load(module, imports) {
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbindgen_copy_to_typed_array = function(arg0, arg1, arg2) {
new Uint8Array(getObject(arg2).buffer, getObject(arg2).byteOffset, getObject(arg2).byteLength).set(getArrayU8FromWasm0(arg0, arg1));
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
imports.wbg.__wbg_new_d258248ed531ff54 = function(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
Expand All @@ -206,6 +229,7 @@ function __wbg_init_memory(imports, maybe_memory) {
function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
__wbg_init.__wbindgen_wasm_module = module;
cachedInt32Memory0 = null;
cachedUint8Memory0 = null;


Expand Down
2 changes: 1 addition & 1 deletion gen/wasm_bg.js

Large diffs are not rendered by default.

Binary file modified gen/wasm_bg.wasm
Binary file not shown.
3 changes: 2 additions & 1 deletion gen/wasm_bg.wasm.d.ts
Expand Up @@ -4,10 +4,11 @@ export const memory: WebAssembly.Memory;
export function __wbg_piecehasher_free(a: number): void;
export function piecehasher_count(a: number): number;
export function piecehasher_reset(a: number): void;
export function piecehasher_write(a: number, b: number, c: number): void;
export function piecehasher_write(a: number, b: number, c: number, d: number): void;
export function piecehasher_digestInto(a: number, b: number, c: number, d: number, e: number, f: number, g: number): number;
export function piecehasher_digestByteLength(a: number): number;
export function piecehasher_multihashByteLength(a: number): number;
export function create(): number;
export function piecehasher_create(): number;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function __wbindgen_malloc(a: number, b: number): number;
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -55,7 +55,8 @@
},
"c8": {
"exclude": [
"gen/**"
"gen/**",
"test/**"
]
},
"devDependencies": {
Expand Down

0 comments on commit c1fad61

Please sign in to comment.