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

@alshdavid/worker-shared-memory

v0.0.8

Published

A native module that allows workers to share memory

Downloads

19

Readme

Node.js Shared Memory Across Workers

This npm package exposes a centralized storage for state shared between workers.

Installation

npm install @alshdavid/worker-shared-memory

Usage

// main.js
import { StringRef, MapRef } from '@alshdavid/worker-shared-memory'
import { Worker } from 'node:worker_threads'

// Spawn worker
const worker = new Worker('./worker.js')

// Create Map in store
const map = new MapRef()
map.set('foo', StringRef.from("Hello World"))

// Give the worker the id of the Map
// I might add "named" values in future so you don't need to transfer IDs
worker.postMessage(map.id)
// worker.js
import { MapRef } from '@alshdavid/worker-shared-memory'
import { parentPort } from 'node:worker_threads'

// Get the ID of the Map
parentPort.addEventListener('message', ({ data: map_id }) => {
    // Connect to the same map
    const map = new MapRef(map_id)

    console.log(map.get('foo').obtainValue()) // "Hello World"
})

Types

import { StringRef, NumberRef, MapRef, VectorRef } from '@alshdavid/worker-shared-memory'

const str = new StringRef() // Empty string (utf8 string)
const num = new NumberRef() // Empty number (64 bit float)
const map = new MapRef()    // Key/Value store that holds refs
const vec = new VectorRef() // Dynamic array that holds refs

Structs

You can define and instantiate structs

// Define struct
const Foo = new StructFactory({
    key_1: "string",
    key_2: "number",
})

const foo = Foo.new({
    key_1: "foo",
    key_2: 42,
})

console.log(foo.getKey('key_1')) // 'foo'
foo.setKey('key_1', 'something else')

You can access structs through a JavaScript proxy object for more ergonomic interactions. be mindful of accessing values as they are not references, the underlying value may change after it is obtained.

const Foo = new StructDefinition({
    key_1: "string",
    key_2: "number",
})

const foo = Foo.new_proxy({
    key_1: "foo",
    key_2: 42,
})

console.log(foo.key_1) // 'foo'
foo.key_1 = 'bar' 
console.log(foo.key_1) // 'bar'

Safety and Memory usage

All values are stored in a shared heap managed by the native module. Interacting with values occurs behind synchronization controls like mutexes and atomics.

The shared heap is not subject to the maximum heap size assigned to Node.js that you can modify via —-max-old-space-size - however to ensure minimal memory usage within the Node.js process + threads, values are passed by reference identifiers.

import { StringRef } from '@alshdavid/worker-shared-memory'

const str = StringRef.from('foo')

console.log(str)               // { id: 342 }
console.log(str.obtainValue()) // 'foo'

Only after a value is obtained is it copied into the Node.js heap and will, at that point, contribute to memory usage within the process/thread memory pool.

The limitation is how many references you can hold in the process - which appears to be several billion under Node's default memory limit.

Manual Memory Management

Unfortunately, usage of this library requires the manual cleanup of values stored in the shared value store and does expose the consumer to use after free errors.

Caution is advised, particularly with Vectors and Maps as dropping them does not drop their held resources. Structs drop their assigned values.

import { StringRef } from '@alshdavid/worker-shared-memory'

const str = StringRef.from('foo')

console.log(str.obtainValue()) // 'foo'

str.drop() // will deallocate the value

console.log(str.obtainValue()) // Thrown Error ('use after free')