bun-shared-memory 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +18 -18
- package/package.json +2 -1
- package/src/growable-buffer.ts +198 -4
- package/src/memory.ts +404 -41
- package/src/refcount.ts +31 -8
- package/src/shared.ts +643 -168
package/src/refcount.ts
CHANGED
|
@@ -160,6 +160,8 @@ export class RefCountCoordinator {
|
|
|
160
160
|
private nextWorkerId = 0;
|
|
161
161
|
/** Free-space threshold (fraction of maxByteLength) that triggers defrag. */
|
|
162
162
|
private readonly defragThreshold: number;
|
|
163
|
+
/** Minimum number of freed blocks before a table is considered fragmented. */
|
|
164
|
+
private readonly minFreeBlocks: number;
|
|
163
165
|
private maintenanceTimer: ReturnType<typeof setInterval> | null = null;
|
|
164
166
|
/** Called after a defragmentation pass with the new chunk lists. */
|
|
165
167
|
private readonly onDefragment?: (buffers: {
|
|
@@ -174,6 +176,7 @@ export class RefCountCoordinator {
|
|
|
174
176
|
buffer?: RefCountBuffer,
|
|
175
177
|
opts: {
|
|
176
178
|
defragThreshold?: number;
|
|
179
|
+
minFreeBlocks?: number;
|
|
177
180
|
autoMaintenance?: boolean;
|
|
178
181
|
maintenanceInterval?: number;
|
|
179
182
|
onDefragment?: (buffers: {
|
|
@@ -198,7 +201,8 @@ export class RefCountCoordinator {
|
|
|
198
201
|
mem.attachRefCountBuffer(b.sab);
|
|
199
202
|
return b;
|
|
200
203
|
})());
|
|
201
|
-
this.defragThreshold = opts.defragThreshold ?? 0.
|
|
204
|
+
this.defragThreshold = opts.defragThreshold ?? 0.8;
|
|
205
|
+
this.minFreeBlocks = opts.minFreeBlocks ?? 64;
|
|
202
206
|
// Start periodic maintenance automatically so refcount events are drained
|
|
203
207
|
// and dead space is reclaimed without an explicit call.
|
|
204
208
|
if (opts.autoMaintenance ?? true) {
|
|
@@ -298,15 +302,29 @@ export class RefCountCoordinator {
|
|
|
298
302
|
}
|
|
299
303
|
}
|
|
300
304
|
|
|
301
|
-
/**
|
|
305
|
+
/**
|
|
306
|
+
* Whether any table is highly fragmented enough to warrant a defragmentation
|
|
307
|
+
* pass.
|
|
308
|
+
*
|
|
309
|
+
* Writes are lock-free bump allocations: overwriting a value allocates a new
|
|
310
|
+
* block and leaves the old one as dead space (there is no free list to reuse
|
|
311
|
+
* it). The used length therefore grows monotonically even when the live data
|
|
312
|
+
* set stays the same size. When the used length occupies a significant share
|
|
313
|
+
* of the buffer's capacity, a defragmentation pass is warranted to compact
|
|
314
|
+
* the live data and reclaim the dead space.
|
|
315
|
+
*
|
|
316
|
+
* A table triggers defrag when its used length exceeds `defragThreshold` of
|
|
317
|
+
* the buffer's capacity.
|
|
318
|
+
*/
|
|
302
319
|
needsDefrag(): boolean {
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
320
|
+
const frag = (b: { capacity: number; byteLength: number }) => {
|
|
321
|
+
if (b.capacity === 0) return false;
|
|
322
|
+
return b.byteLength / b.capacity > this.defragThreshold;
|
|
323
|
+
};
|
|
306
324
|
return (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
325
|
+
frag(this.mem.dataTable) ||
|
|
326
|
+
frag(this.mem.arrayTable) ||
|
|
327
|
+
frag(this.mem.stringTable)
|
|
310
328
|
);
|
|
311
329
|
}
|
|
312
330
|
|
|
@@ -327,7 +345,12 @@ export class RefCountCoordinator {
|
|
|
327
345
|
this.maintenanceTimer = setInterval(() => {
|
|
328
346
|
this.drainEvents();
|
|
329
347
|
if (this.needsDefrag()) {
|
|
348
|
+
// Set the defrag flag so lock-free writes fall back to the mutex, then
|
|
349
|
+
// wait for any in-flight lock-free writes to finish before compacting.
|
|
350
|
+
this.mem.setDefragmenting();
|
|
351
|
+
this.mem.waitForWritesToFinish();
|
|
330
352
|
const buffers = this.mem.withLock(() => this.mem.defragment());
|
|
353
|
+
this.mem.clearDefragmenting();
|
|
331
354
|
this.onDefragment?.(buffers);
|
|
332
355
|
}
|
|
333
356
|
}, intervalMs);
|