@rbxts/allocator
v1.1.2
Published
Roblox-TS object pooling system with configurable allocation strategies for efficient object management.
Downloads
17
Maintainers
Readme
@rbxts/allocator
Roblox-TS object pooling system with configurable allocation strategies for efficient object management.
NPM
Features
- Four Allocation Strategies:
Unbounded: Infinite growth for high-intensity scenariosElastic: Temporary expansion with automatic shrinkageFixed: Strict reuse of initial poolFailSilent: Silent failure when exhausted
- Thread-Safe Disposal: Uses Roblox events for cross-thread cleanup
- Lifecycle Hooks: Full control over creation, activation, and destruction
- Diagnostic Tracking: Creation IDs and usage counters for debugging
Installation
#npm
npm install @rbxts/allocator
#bun
bun add @rbxts/allocatorUsage
Basic Example: Colored Part Pool
import { Workspace } from "@rbxts/services";
import { EObjectPoolType, ObjectPool } from "@rbxts/allocator";
interface IPartData {
Part: BasePart;
Thread?: thread;
}
class PartObjectPool extends ObjectPool<IPartData, Color3> {
protected CreateObj(): IPartData {
return identity<IPartData>({ Part: new Instance("Part") });
}
protected StartObj(value: IPartData, start_data: Color3, dispose: () => void): void {
value.Part.Position = new Vector3(0, 100, 0);
value.Part.Parent = Workspace;
value.Part.Color = start_data;
value.Thread = task.delay(3, dispose);
}
protected DisposeObj(value: IPartData, safe_cancel_thread: (t?: thread) => void): void {
value.Part.Parent = undefined;
safe_cancel_thread(value.Thread);
}
protected DestroyObj(value: IPartData): void {
print("Destroyed");
value.Part.Destroy();
}
}
const part_object_pool = new PartObjectPool(15, EObjectPoolType.Elastic);
for (const i of $range(0, 200)) {
task.wait(0.2);
part_object_pool.UseObject(new Color3(math.random(), math.random(), math.random()));
}Initialization Behavior
The pool uses lazy initialization - objects are only created when first needed:
// No objects are created at this point
const pool = new PartObjectPool(15, EObjectPoolType.Elastic);
// First call to UseObject() triggers initialization
pool.UseObject(new Color3(1, 0, 0));If you need to pre-initialize the pool or need parameters before initialization, you can call the protected Init() method in your constructor:
class CustomPool extends ObjectPool<MyType, StartData> {
constructor(size: number, type: EObjectPoolType, customParam: string) {
super(size, type);
this.customParam = customParam;
// Initialize pool immediately instead of on first UseObject()
this.Init();
}
// ...implementation of abstract methods
}Benefits:
- Lazy initialization delays resource allocation until needed
- Explicit initialization gives control when needed
- Supports constructor parameters needed for object creation
Constructor
new ObjectPool(initialSize: number, strategy: EObjectPoolType);Abstract Methods
| Method | Responsibility | Timing |
| --------------------------------------- | --------------------- | ------------------------ |
| CreateObj() | Instance construction | Pool initialization |
| StartObj(value, data, dispose) | Activate instance | On UseObject() call |
| DisposeObj(value, safe_cancel_thread) | Deactivate instance | Before reuse/destruction |
| DestroyObj(value) | Cleanup resources | When pool shrinks |
Public Methods
| Method | Description |
| ----------------- | ------------------------------------------- |
| UseObject(data) | Activates an object from the pool with data |
| Destroy() | Destroys all objects and cleans up the pool |
Strategy Examples
Fixed Pool
// For memory-critical systems where exceeding the initial size is not allowed
const fixedPool = new PartObjectPool(10, EObjectPoolType.Fixed);
// When all 10 items are in use, the oldest active item will be recycledUnbounded Pool
// For high-demand scenarios where performance is critical
const unboundedPool = new PartObjectPool(5, EObjectPoolType.Unbounded);
// Will create new instances indefinitely as neededFailSilent Pool
// For optional visual effects that aren't critical
const failSilentPool = new PartObjectPool(20, EObjectPoolType.FailSilent);
// Returns undefined without allocation when pool is exhaustedDiagnostic Features
The object pool provides debugging information through:
- Creation IDs: Unique identifier for each created object
- Usage counters: Track how many times an object has been used
Error Handling
FailSilent: Returns undefined when the pool is exhaustedFixed: Recycles the oldest active object when pool is exhaustedDestroy(): Safely cleans up all resources when you're done
Manual Object Pool
For simpler use cases where you don't need the full lifecycle management, you can use ManualObjectPool:
import { EObjectPoolType, ManualObjectPool } from "@rbxts/allocator";
const partPool = new ManualObjectPool(
10, // initial size
EObjectPoolType.Elastic,
() => new Instance("Part"), // create function
(part) => part.Destroy(), // destroy function
);
// Get an object from the pool
const part = partPool.UseObj();
if (part) {
//usually check can be avoided if the pool type is not FailSilent
part.Parent = Workspace;
// ... use the part
// Return it to the pool when done
partPool.FreeObj(part);
}
// Clean up when done
partPool.Destroy();ManualObjectPool Methods
| Method | Description |
| -------------- | ------------------------------------------- |
| UseObj() | Gets an object from the pool |
| FreeObj(obj) | Returns an object to the pool |
| Destroy() | Destroys all objects and cleans up the pool |
Performance Characteristics
| Strategy | Allocation Speed | Memory Usage | | ---------- | ----------------- | ---------------- | | Unbounded | ⚡ Instant | 📈 Linear growth | | Elastic | ⚡ Instant (temp) | ↔️ Controlled | | Fixed | ⚡ Fast (reuse) | ✅ Fixed | | FailSilent | ⚡ Instant | ✅ Fixed |
