npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@bnaya/malloc-temporary-fork

v4.0.11-transferable

Published

ArrayBuffer based malloc() impl for hybrid JS/WASM use cases, based on thi.ng/tinyalloc

Downloads

4

Readme

@thi.ng/malloc

npm (scoped) npm downloads Twitter Follow

This project is part of the @thi.ng/umbrella monorepo.

About

TypeScript port of thi.ng/tinyalloc, for raw or typed array memory pooling and/or hybrid JS/WASM use cases etc. Supports free block compaction and configurable splitting. Unlike the original, this implementation also supports realloc() and does not constrain the overall number of blocks in use and the only imposed limit is that of the underlying array buffer.

Each MemPool instance operates on a single large ArrayBuffer used as backing memory chunk, e.g. the same buffer used by a WASM module.

Even for non-WASM use cases, using this package can drastically speed up allocation of typed arrays and reduce GC pressure. See benchmarks below.

Installation

yarn add @thi.ng/malloc

Dependencies

Usage examples

import { Type } from "@thi.ng/api";
import { MemPool } from "@thi.ng/malloc";

// create memory w/ optional start allocation address
// (start address can't be zero, reserved for malloc/calloc failure)
const pool = new MemPool({ size: 0x1000, start: 8 });

// all memory blocks will be aligned to 8-byte boundaries
// size is given in bytes
// returns pointer / index in array buffer
ptr = pool.malloc(16);
// 8

// request memory and return as typed view
// in this case we use number of elements, NOT bytes
vec = pool.mallocAs(Type.F64, 4);
// Float64Array [ 0, 0, 0, 0 ]

// report block stats (sizes & addresses in bytes)
pool.stats();
// { free: { count: 0, size: 0 },
//   used: { count: 2, size: 48 },
//   top: 56,
//   available: 4040,
//   total: 4096 }

// reallocate/resize block for pointer/address
// (might move block contents to new mem region)
ptr = pool.realloc(ptr, 32);

// same but for arrays created with `mallocAs()`
vec = pool.reallocArray(vec, 5);

// release address or view back into pool / heap
pool.free(ptr);
// true
pool.free(vec);
// true

// pointers / views can only be freed once
pool.free(vec);
// false

// memory blocks are re-merged whenever possible
// likewise, available free blocks might be split
// if smaller size requested...
pool.stats();
// { free: { count: 1, size: 48 },
//   used: { count: 0, size: 0 },
//   top: 56,
//   available: 4040,
//   total: 4096 }

API

MemPool

The MemPool constructor takes an ArrayBuffer (or size only) and an optional MemPoolOpts object for specifying start and end addresses (byte offsets) delineating the allocatable / managed region and other options.

// example with default options shown
new MemPool(0x1000, {
    start:    0x8,
    end:      0x1000,
    compact:  true,
    split:    true,
    minSplit: 16
});

The default start address is 8 and end the length of the buffer. This start address is also the minimum supported address for memory blocks. Address 0x0 is reserved as return value for allocation errors.

The compact option enables recursive compaction / joining of neighboring free blocks. Enabled by default to minimize fragmentation.

The split option is used to enable (default) splitting of a larger suitable free block when allocating a smaller size. minSplit specifies the minimum excess between requested size and actual block size, i.e. by default a block will be split during allocation if there're at least 16 bytes left over. The given value should always be a multiple of 8.

malloc(size: number)

Attempts to allocate a new block of memory of given byte size and returns start address if successful, or zero (0) if unsuccessful. Memory blocks always start at multiples of 8.

mallocAs(type: Type, num: number)

Similar to malloc(), but returns a typed array view of desired type and instead of byte size, expects number of elements. Returns null, if allocation failed.

Types are referred to via the Type enum in the base @thi.ng/api package, e.g. Type.F64:

U8, U8C, I8, U16, I16, U32, I32, F32, F64

calloc(size: number)

Like malloc() but zeroes allocated block before returning. Unless the allocated block is immediately filled with user data, this method is preferred over malloc().

callocAs(type: Type, num: number)

Like mallocAs() but zeroes allocated block before returning.

realloc(addr: number, size: number)

Attempts to adjust the size of the block at the given allocated address to new size or if not possible, attempt to allocate a new block and copies contents of current block (if successful, automatically frees old address). Returns new address if successful or else 0.

reallocArray(buf: TypedArray, num: number)

Similar to realloc(), but takes a typed array created with mallocAs() / callocAs() and returns new arrays of same type or null if re-allocation wasn't possible.

free(addr: number | TypedArray)

Releases given address or array view back into the pool. Returns true if successful. Only previously allocated addresses or views created by this instance can be freed and its the user's responsibility to not use the freed address or view after this call.

freeAll()

Frees all allocated blocks, essentially resets the pool. This is useful when using a MemPool for temporary object allocation within a function and then calling this method before returning. This is also much cheaper than individually freeing the blocks.

release()

This completely destroys all internal pool references & state and should only be used when the pool is no longer needed. The pool is unusable afterwards. If there're no other external references to the pool's underlying ArrayBuffer, then it will also be garbage collected soon after.

stats()

Returns pool statistics (see above example).

Benchmarks

node bench/index.js
1x f64x4 malloc x 8,712,284 ops/sec ±0.39% (92 runs sampled) mean: 0.00011ms
1x f64x4 vanilla x 1,714,557 ops/sec ±2.18% (82 runs sampled) mean: 0.00058ms

6x f64 malloc x 704,920 ops/sec ±1.20% (91 runs sampled) mean: 0.00142ms
6x f64 vanilla x 251,799 ops/sec ±1.87% (84 runs sampled) mean: 0.00397ms

Authors

  • Karsten Schmidt

License

© 2016 - 2018 Karsten Schmidt // Apache Software License 2.0