SharedCore
High-performance, thread-safe data structures for JavaScript and TypeScript, powered by SharedArrayBuffer. Zero-copy, zero-hassle, shared memory at your core.
Install / Use
/learn @pverscha/SharedCoreREADME
Key features
High-performance, thread-safe data structures for JavaScript and TypeScript, powered by SharedArrayBuffer. Zero-copy, zero-hassle, shared memory at your core.
- Zero-cost data sharing: Avoid serialization and transfer overhead between Web Workers or threads.
- Thread-safe by design: Synchronization is handled internally — no locks, races, or guesswork.
- Familiar API: Drop-in replacements for JavaScript's native Map and Array, with full TypeScript support.
- Built for performance: Optimized for speed-critical, concurrent workloads.
- Automatic memory management: Resizes automatically when necessary.
Introduction
This package is intended to speed up the communication time between different JavaScript threads by exposing data structures that internally use a SharedArrayBuffer to store all required information.
SharedArrayBuffers can be used by multiple threads without an extra cost (they do not need to be transferred, nor does it require any serialization / deserialization), but can only contain binary data.
This library overcomes this issue by providing users with rich datastructures that follow the default JavaScript API (where possible) and that can be (more or less) transparently used. TypeScript typings are included with this library.
Unlike traditional JavaScript Maps or Arrays that need to be serialized and copied between workers, the datastructures provided by this library reside in shared memory, making them instantly accessible to all workers without any transfer cost. This makes them particularly efficient for scenarios where large amounts of data need to be shared across multiple threads in your application.
A common use case for ShareableMap is when processing large datasets in a separate worker thread while maintaining UI responsiveness. For example, when your application needs to fetch and process substantial amounts of data, this operation can be offloaded to a worker thread to keep the main thread (UI) responsive. With traditional Maps, transferring the processed data back to the main thread for UI updates would require costly serialization and deserialization. ShareableMap eliminates this overhead by providing instant access to the processed data from any thread, making it an ideal choice for data-intensive applications that require frequent updates between workers and the UI thread.
Performance
Coming soon
Installation
This package is available on npm and can be installed using
npm install shared-memory-datastructures
Examples
Creating a new ShareableMap
Creating a new ShareableMap is as simple as creating a normal Map in JavaScript:
import {ShareableMap} from "shared-memory-datastructures";
const sharedMap = new ShareableMap<string, number>();
sharedMap.set("x", 17);
console.log(`Set value is: ${sharedMap.get("x")}`);
Sharing a ShareableMap between workers
The ShareableMap can be used by multiple workers at the same time.
Because it's not possible in JavaScript to send functions (or objects containing functions) from one worker to another, you need to manually send a ShareableMap's internal state to another worker, and revive it over there.
Main thread (or worker A):
import {ShareableMap} from "shared-memory-datastructures";
const sharedMap = new ShareableMap<string, number>();
sharedMap.set("x", 45);
sharedMap.set("y", 68);
// Retrieve the binary memory representation of the ShareableMap
const transferableState = sharedMap.toTransferableState();
const workerB = new WorkerA();
// Send a reference to this block of shared memory to another worker.
workerB.postMessage({myMapState: transferableState});
Worker B (inflating the Map again)
import {ShareableMap} from "shared-memory-datastructures";
self.onmessage = async (event) => {
const mapState = event.data.myMapState;
// Create a new ShareableMap object that uses the same block of memory as the object in the main thread.
const sharedMap = ShareableMap.fromTransferableState<string, number>(mapState);
console.log(`Value for key "x" is: ${sharedMap.get("x")}`);
}
[!NOTE] Note that the map can still be updated by both workers at the same time. this library itself handles any required synchronization or thread-safety transparently.
API
See our API reference for a detailed description of all functions, interfaces and classes supported by this library.
ShareableMap<K, V>
[!NOTE] Since v1.0.0-alpha.1 overwriting existing keys with
set, and removing keys withdeleteare also supported. This means that theShareableMapnow fully supports theMapinterface as defined by JavaScript.
Constructor
constructor(options?: ShareableMapOptions<V>)
Creates a new ShareableMap instance.
Parameters:
- (optional): Configuration options for the map
expectedSize: Expected number of elements to be stored (default: 1024)averageBytesPerValue: Expected average size in bytes per value (default: 256)serializer: Optional custom serializer for value types
Example:
const map = new ShareableMap<string, object>({
expectedSize: 10000,
averageBytesPerValue: 512
});
set
set(key: K, value: V): this
Sets a key-value pair in the map. If the key already exists, its value is updated.
Parameters:
key: The key to setvalue: The value to store
Returns: The map instance for chaining
Example:
map.set('user', { id: 1, name: 'John' });
get
get(key: K): V | undefined
Retrieves a value from the map by its key.
Parameters:
key: The key to look up
Returns: The stored value or if the key doesn't exist undefined
Example:
const user = map.get('user'); // { id: 1, name: 'John' } or undefined
has
has(key: K): boolean
Checks if a key exists in the map.
Parameters:
key: The key to check for
Returns: true if the key exists, false otherwise
Example:
if (map.has('user')) {
// Key exists
}
toTransferableState
toTransferableState(): TransferableState
Extracts the internal buffers representing the map for efficient transfer between threads.
Returns: An object containing:
indexBuffer: ArrayBuffer containing the map's index datadataBuffer: ArrayBuffer containing the map's valuesdataType: String identifier (always "map")
Example:
const state = map.toTransferableState();
worker.postMessage({ state }, [state.indexBuffer, state.dataBuffer]);
ShareableMap.fromTransferableState
static fromTransferableState<K, V>(
state: TransferableState,
options?: ShareableMapOptions<V>
): ShareableMap<K, V>
Creates a new ShareableMap from previously exported state.
Parameters:
state: The state object returned bytoTransferableState()options(optional): Configuration options (same as constructor)
Returns: A new ShareableMap instance with the same data as the original
Throws: TypeError if the provided state is invalid for an array.
Example:
// In a worker or after receiving the state
const map = ShareableMap.fromTransferableState(receivedState);
Additional Information
- The map is thread-safe with internal read/write locking mechanisms
- Automatically handles memory management with defragmentation when needed
- Supports any serializable JavaScript value as keys and values
- Implements the standard Map interface methods (entries, keys, values, forEach)
For complete documentation and advanced usage, please refer to the full documentation - coming soon.
ShareableArray<T>
[!NOTE] Available since v1.0.0-alpha.10. The array implements almost all methods and functions provided by the standard JavaScript Array API (with the same type signatures). However, it does not implement the JavaScript
Arrayinterface because it cannot fully adhere to its semantics due to limitations in the JavaScript language.
Constructor
constructor(options?: ShareableArrayOptions<T>, ...items: T[])
Creates a new ShareableArray instance.
Parameters:
- (optional): Configuration options:
serializer: Optional custom serializer for value types
items: Initial values to populate the array with
Example:
// Create an empty array
const array = new ShareableArray<number>();
// Create an array with initial values
const arrayWithValues = new ShareableArray<string>(undefined, "apple", "banana", "cherry");
// Create an array with a custom serializer
const customArray = new ShareableArray<MyObject>({
serializer: new MyObjectSerializer()
});
set
set(index: number, value: T | undefined): this
Sets the element at the specified index to the given value.
Parameters:
index: Zero-based index at which to set the valuevalue: The value to assign
Returns: The array instance for chaining
Example:
const array = new ShareableArray<number>(undefined, 1, 2, 3);
array.set(1, 42); // array now contains [1, 42, 3]
at
at(index: number): T | undefined
Returns the element at the specified index. Supports negative indices, where -1 refers to the last element.
Parameters:
index: Zero-based index of the element to retrieve
Returns: The element at the specified position, or undefined if the index is out of bounds.
Example:
const array = new ShareableArray<number>(undefined, 10, 20, 30);
array.at(1); // Returns 20
array.at(-1); // Returns 30
array.at(5); // Returns undefined
delete
delete(index: number): T | undefined
Removes the element at t
