A high-performance bit pool for managing resource allocation with efficient memory usage and fast bitwise operations.
- High Performance: Optimized bitwise operations with minimal GC pressure
- Memory Efficient: Uses
Uint32Arraybacking for compact storage - Type Safe: Full TypeScript support with comprehensive type definitions
- Iterator Support: Built-in iterators for available and occupied indices
- Flexible Construction: Create pools from scratch, arrays, or
Uint32Array - Large Pools: Supports up to 536,870,911 indices (BitPool.MAX_SAFE_SIZE)
npx jsr add @phughesmcr/bitpoolimport { BitPool } from "@phughesmcr/bitpool";deno add jsr:@phughesmcr/bitpoolimport { BitPool } from "@phughesmcr/bitpool";bunx jsr add @phughesmcr/bitpoolimport { BitPool } from "@phughesmcr/bitpool";import { BitPool } from "@phughesmcr/bitpool";
// Create a pool with 1000 indices (0-999)
const pool = new BitPool(1000);
// Acquire resources
const id1 = pool.acquire(); // 0
const id2 = pool.acquire(); // 1
console.log(pool.isOccupied(id1)); // true
console.log(pool.availableCount); // 998
// Release resources
pool.release(id1);
pool.release(id2);
console.log(pool.isOccupied(id1)); // false
console.log(pool.availableCount); // 1000Creates a new BitPool with the specified size.
const pool = new BitPool(1000);Creates a BitPool from an array of uint32 values representing bit patterns.
Each uint32 value represents 32 bits where 1 = occupied, 0 = available.
// Create a pool with first 4 bits occupied
const pool = BitPool.fromArray(32, [0b11110000]);Creates a BitPool from a Uint32Array or number array.
const mask = new Uint32Array([0xFFFF0000, 0x0000FFFF]);
const pool = BitPool.fromUint32Array(64, mask);The total size of the pool.
const pool = new BitPool(1000);
console.log(pool.size); // 1000The number of available slots.
console.log(pool.availableCount); // Number of free slotsThe number of occupied slots.
console.log(pool.occupiedCount); // Number of used slotsThe next available index, or -1 if the pool is full.
console.log(pool.nextAvailableIndex); // Next free indexChecks if the pool is empty (all slots available).
if (pool.isEmpty) {
console.log("Pool is empty");
}Checks if the pool is full (no slots available).
if (pool.isFull) {
console.log("Pool is full");
}Acquires the next available index. Returns -1 if the pool is full.
const index = pool.acquire();
if (index !== -1) {
console.log(`Acquired index ${index}`);
}Releases an occupied index back to the pool.
pool.release(index);Checks if an index is available.
if (pool.isAvailable(42)) {
console.log("Index 42 is available");
}Checks if an index is occupied.
if (pool.isOccupied(42)) {
console.log("Index 42 is occupied");
}Finds the next available index starting from the specified index. Returns -1 if no available indices are found.
const next = pool.findNextAvailable(100); // Start search from index 100
const looped = pool.findNextAvailable(100, true); // Loop back to start if neededClears the pool, making all indices available.
pool.clear();
console.log(pool.isEmpty); // trueFills the pool, marking all indices as occupied.
pool.fill();
console.log(pool.isFull); // trueRefreshes the pool, ensuring the next available index is set to the first available index.
pool.refresh();Creates a copy of the pool.
const cloned = pool.clone();Iterator that yields all available indices in the specified range.
for (const index of pool.availableIndices()) {
console.log(`Index ${index} is available`);
}
// Iterate over a specific range
for (const index of pool.availableIndices(100, 200)) {
console.log(`Index ${index} is available`);
}Iterator that yields all occupied indices in the specified range.
for (const index of pool.occupiedIndices()) {
console.log(`Index ${index} is occupied`);
}
// Iterate over a specific range
for (const index of pool.occupiedIndices(100, 200)) {
console.log(`Index ${index} is occupied`);
}Iterator that yields the underlying Uint32Array values.
for (const chunk of pool) {
console.log(`Chunk value: ${chunk}`);
}const TOTAL_PORTS = 65_536;
const RESERVED_UNTIL = 49_152;
// Create availability mask for ephemeral ports
function buildPortMask(capacity: number, reservedUntil: number): Uint32Array {
const chunkCount = Math.ceil(capacity / 32);
const mask = new Uint32Array(chunkCount);
for (let i = reservedUntil; i < capacity; i++) {
const chunkIndex = i >>> 5;
const bitPosition = i & 31;
mask[chunkIndex] |= (1 << bitPosition);
}
return mask;
}
const portMask = buildPortMask(TOTAL_PORTS, RESERVED_UNTIL);
const portPool = BitPool.fromUint32Array(TOTAL_PORTS, portMask);
const port = portPool.acquire(); // Get an ephemeral port
portPool.release(port); // Release it backconst entityPool = new BitPool(10_000);
// Acquire IDs for new entities
const playerId = entityPool.acquire();
const enemyId = entityPool.acquire();
// Release IDs when entities are destroyed
entityPool.release(playerId);
entityPool.release(enemyId);const connectionPool = new BitPool(100);
function getConnection(): number {
const connId = connectionPool.acquire();
if (connId === -1) {
throw new Error("Connection pool exhausted");
}
return connId;
}
function releaseConnection(connId: number): void {
connectionPool.release(connId);
}BitPool is designed for high-performance scenarios with minimal GC pressure:
- Backed by
Uint32Arrayfor efficient memory usage - Optimized bitwise operations for fast lookups
- Zero-allocation iterators where possible
- Efficient search algorithms for finding available slots
Run deno task example to see a performance demonstration with ephemeral port allocation.
Contributions are welcome! The aim of the project is performance - both in terms of speed and GC allocation pressure.
Please run deno test and deno task prep before committing.
See jsr.io/@phughesmcr/bitpool for complete API documentation.
BitPool is released under the MIT license. See LICENSE for further details.
© 2025 The BitPool Authors. All rights reserved.
See AUTHORS.md for author details.