Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allocation debug tooling + select tests #605

Open
H-Plus-Time opened this issue Sep 18, 2024 · 2 comments
Open

Allocation debug tooling + select tests #605

H-Plus-Time opened this issue Sep 18, 2024 · 2 comments

Comments

@H-Plus-Time
Copy link
Contributor

It turns out this is a relatively simple thing to do (for simple 'did it leak?' checks, this is sufficient: https://gist.github.com/H-Plus-Time/93fa5767fa32d8f8a6740dea3d4b974f), with slightly more valgrind-esque usage possible via https://github.com/rustwasm/wasm-tracing-allocator.

Obviously one not to go overboard on (e.g. testing the allocator itself is just a bad idea), the kind of tests that would be useful would be things like:

test('free to zero', () => {
  const initialAllocation = currentAllocation();
  const t = readParquet(fileBlob);
  // obviously more memory will be in use at this point - debatable whether setting an upper 
  // bound on allocated memory would catch anything the borrow checker wouldn't.
  t.free()
  // actually worth checking that allocation goes all the way back to initial (which it does)
  assert currentAllocation() == initialAllocation;
})

test('automatic free on GC', () => {
  const func = () => {
    const t = readParquet(fileBlob);
    // intentionally forget to free 
  }
  const initialAllocation = currentAllocation();
  func();
  global.gc();
  // yield back to the event loop for a short period (setImmediate is usually enough, but 
  // we don't want flaky tests)
  await setTimeout(1_00);
  // the finalization registry will have triggered free on garbage collection of the Table
  // instance
  assert currentAllocation() == initialAllocation;
});

test('automatic free on RS stream consumption', async () => {
  const initialAllocation = currentAllocation();
  const stream = await transformParquetStream(await readParquetStream(url));
  // reader, metadata, first row group of the source file, first output record batch of the
  // writer allocated - somewhat difficult to determine what that *should* be without
  // manual inspection.
  const roundtripBuf = await new Response(stream).arrayBuffer();
  assert currentAllocation() == initialAllocation; // this actually caught a (tiny, 64b) leak
});
@H-Plus-Time
Copy link
Contributor Author

This, if/when it's merged will enable some pretty interesting patterns: rustwasm/wasm-bindgen#4117 (provided you're going through bun, deno, TS, esbuild (probably babel too) or anything else that has support for syntax lowering, it enables the equivalent of with).

The proposal makes for wild reading, and is eminently polyfillable.

@kylebarron
Copy link
Owner

That's really cool, and something I've been curious about for a while: kylebarron/arrow-js-ffi#43

Looking forward to seeing that merged and seeing more examples of it in use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants