-
Notifications
You must be signed in to change notification settings - Fork 1
Caching and Performance
VoxLib is a convenience library, not a magical faster replacement for Minecraft's shape code. Its APIs still use vanilla VoxelShape operations underneath.
The cache helps with one specific pattern: repeating the same operation with the same shape instances. If you keep creating new shapes, the cache cannot recognize them as the same work just because their geometry happens to match.
Union and transformation results go through a Caffeine-backed cache with these bounds:
- At most 500 entries.
- Entries expire 10 minutes after last access.
- Keys use object identity (
===), not shape content. Two shapes with identical geometry but different instances are different keys.
Binary unions (the + operator) use a two-touch policy:
- The first union of a pair runs through vanilla directly, with no cache key allocated. The cost matches uncached vanilla work.
- If the same pair of instances is unioned again, the result is admitted to the cache and later calls return it from there.
A small per-thread ring of the four most recent operand pairs makes short interleaved sequences (union a, union b, union a) hit without waiting for an exact back-to-back repeat.
This is why foo() + bar() will not become fast through caching when both functions construct fresh shapes. Every call pays for two new shapes and a new union.
rotateLeft, rotateRight, flipHorizontal, flipVertical, flipZ, and rotate keep a per-thread last-transformation record. The first call on a shape allocates a key immediately, so repeated "rotate this same shape" calls hit the fast path without a second distinct call pattern being needed. Repeated hits are effectively allocation-free.
ShapeCache.clearCache() drops all cached entries immediately. It also clears the calling thread's fast-path state and retires state on other threads through a generation counter when they next use it.
import com.github.mystery2099.voxlib.optimization.ShapeCache
ShapeCache.clearCache()From Java, call ShapeCache.INSTANCE.clearCache().
Most mods should never call this. It exists for tests and tools that need deterministic memory behavior.
VoxelAssembly.union with more than two shapes uses balanced, divide-and-conquer combination instead of folding left to right. For a fresh 32-shape union this measured about 5x faster than the vanilla-equivalent left fold in the project's benchmarks, because balanced combination produces cheaper intermediate shapes. Unions of up to 16 shapes also get a cache entry for the whole sequence.
CommonShapes factories use fixed per-family slot arrays covering every valid parameter combination (321 slots across all families). Results are created lazily and retained for the class loader's lifetime. Repeated factory calls skip construction, validation, and lookup entirely.
- For fixed block shapes, build once and store in a companion object or static field. This beats every cache because no per-query work happens at all.
- Reuse shape instances across calls if you want cache hits. Instance identity is the key.
- Store simplified results from Simplifying shapes as constants too; simplification is not cached.
- Do not rely on the cache as a design crutch for hot paths. It is a bounded convenience, not a guarantee: other operations can evict entries, and the 10-minute expiry applies.
The project ships a JMH suite with acceptance gates, documented with methodology and scoped results in docs/PERFORMANCE.md. Representative historical results from that suite:
| Workload | Result |
|---|---|
| Repeated 8-box binary union | ~72x faster than recomputation |
| Repeated 32-box right rotation | ~1,809x faster than uncached |
| Repeated default table factory | 2.11 ns (memoization hit) |
| Fresh primitive cuboid | within 3% of vanilla-equivalent code |
| Fresh 8-box binary union | within the 10% cold-path gate |
The first call stays close to vanilla by design; the large wins come from repetition. Measure your own shapes and call patterns before making performance decisions. The committed benchmarks are here because a general claim that "VoxLib is faster" would be misleading.