Skip to content

Commit 19d4fa2

Browse files
committed
Add object-pool.md by Gemini 2.5
1 parent 84712de commit 19d4fa2

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

object-pool.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Object Pooling for ViewportPattern: Summary
2+
3+
This document summarizes the investigation into using an object pool to optimize `ViewportPattern` allocations and reduce Garbage Collection (GC) overhead.
4+
5+
## Problem
6+
7+
- Profiling has indicated significant GC pauses related to the frequent allocation and deallocation of `ViewportPattern` objects.
8+
- The `combinePatterns` function, in particular, has been identified as a hotspot for these allocations.
9+
10+
## Proposed Solution: Object Pooling
11+
12+
The proposed solution is to implement an object pool for `ViewportPattern` objects. This involves reusing `ViewportPattern` instances rather than creating new ones for each operation.
13+
14+
## Structural Analysis
15+
16+
- The `ViewportPattern` type is defined as `Pattern<ViewportNumber>`, which consists of an `anchor: Point<ViewportNumber>` and a `target: Point<ViewportNumber>`.
17+
- `Point<N>` is a two-element array `[x: N, y: N]`.
18+
- This simple and fixed structure makes `ViewportPattern` (and its constituent `Point`s) well-suited for object pooling.
19+
20+
## Necessary Code Modifications
21+
22+
1. **Create `ViewportPatternPool` Class:**
23+
24+
- Implement a class (e.g., in `src/object-pool.ts`) with:
25+
- `acquire(): ViewportPattern`: Retrieves an available `ViewportPattern` from the pool or creates a new one (up to a configurable limit).
26+
- `release(pattern: ViewportPattern)`: Returns a `ViewportPattern` to the pool, making it available for reuse.
27+
- The pool would internally manage a list of `ViewportPattern` instances. Pooled patterns would have their `anchor` and `target` `Point` arrays pre-allocated.
28+
29+
2. **Modify Core Functions to Mutate Output Parameters:**
30+
31+
- Update functions that currently return new `ViewportPattern` or `Point` instances to accept an optional `out` parameter. If provided, these functions will mutate the `out` object/array instead of allocating a new one.
32+
- **Point Manipulation Functions (e.g., in `src/functions.ts`):**
33+
- `mapPointToViewportSpace(point, screenSize, outPoint: ViewportPoint)`
34+
- `resolveRelativePointPosition(relativePoint, pattern, outPoint: Point<N>)` (or adapt `resolveRelativePointPositionInPlace`)
35+
- **Pattern Manipulation Functions (e.g., in `src/functions.ts`):**
36+
- `mapPatternToViewportSpace(pattern, screenSize, outPattern: ViewportPattern)`
37+
- `combinePatterns(parent, child, outPattern: Pattern<ParentNumber>)`
38+
- These functions would then modify `outPattern.anchor`, `outPattern.target`, `outPoint[0]`, `outPoint[1]` directly.
39+
40+
3. **Integrate Pool into `streamDrawablePatterns` (in `src/draw/stream-drawable-patterns.ts`):**
41+
42+
- Instantiate or import a global `ViewportPatternPool`.
43+
- **Acquire:** Before calling `mapPatternToViewportSpace` (for initial screens) or `combinePatterns` (in the generation loop), acquire a `ViewportPattern` from the pool.
44+
```typescript
45+
// const newViewportPattern = combinePatterns(entry.currentPattern, pattern); // OLD
46+
const pooledPattern = globalViewportPatternPool.acquire()
47+
const newViewportPattern = combinePatterns(entry.currentPattern, pattern, pooledPattern)
48+
```
49+
- **Release:** After a `ViewportPattern` is no longer needed (i.e., after its `QueueEntry` is processed and it has been used to generate children patterns, or if `isValidPattern` returns false and the pattern is discarded), release it back to the pool.
50+
51+
```typescript
52+
// yield entry; // OLD
53+
// ...
54+
// // After entry.currentPattern is fully processed:
55+
// globalViewportPatternPool.release(entry.currentPattern);
56+
57+
// If a newly combined pattern is not valid:
58+
if (isValidPattern(newViewportPattern, viewportBoundaries)) {
59+
// ... push to queue ...
60+
} else {
61+
globalViewportPatternPool.release(newViewportPattern) // Release if not used
62+
}
63+
```
64+
65+
- Care must be taken to ensure patterns are released exactly once and only when they are no longer in use.
66+
67+
## Trade-offs
68+
69+
- **Benefits:**
70+
- Reduced GC pressure, leading to fewer and shorter GC pauses.
71+
- Potentially improved overall performance and smoother rendering, especially in the pattern generation loop.
72+
- **Costs:**
73+
- **Increased Code Complexity:** Introduces manual memory management aspects (acquire/release).
74+
- **New Bug Class:** Risk of bugs related to incorrect pool usage (e.g., double-release, use-after-release, pool exhaustion if releases are missed).
75+
- **Function Signature Changes:** Core utility functions will have modified signatures.
76+
77+
## Conclusion
78+
79+
Pooling `ViewportPattern` objects is a viable strategy for addressing the identified GC performance issues. While it introduces complexity, the potential performance gains in the critical pattern generation path could be significant. Careful implementation of the pool and the acquire/release logic is paramount.

0 commit comments

Comments
 (0)