diff --git a/BOLT'S JOURNAL - PERFORMANCE LEARNINGS.md b/BOLT'S JOURNAL - PERFORMANCE LEARNINGS.md index f2b04d6e..f687441e 100644 --- a/BOLT'S JOURNAL - PERFORMANCE LEARNINGS.md +++ b/BOLT'S JOURNAL - PERFORMANCE LEARNINGS.md @@ -1 +1,2 @@ - Direct matrix array manipulation (`instanceMatrix.array`) bypasses expensive Object3D composition and matrix allocations, significantly improving rendering batcher update loops. +## 2024-04-09 - TSL and GC Performance Rules\n**Learning:** In Three.js, TSL math nodes are generally faster and preferred over updating uniforms via JS every frame for performance optimization. For Three.js InstancedMesh objects, colors must be updated via `.setColorAt()`. Modifying the material directly will incorrectly affect all instances. In Candy World, collision detection handled in JavaScript becomes a severe bottleneck at >500 entities. AssemblyScript/WASM handles 2000+ entities efficiently.\n**Action:** Use TSL math nodes instead of JS uniforms whenever possible. Always use `.setColorAt()` for InstancedMesh colors. Use WASM for heavy collision detection. diff --git a/src/systems/asset-streaming/asset-streaming.ts b/src/systems/asset-streaming/asset-streaming.ts index 7154b6b5..ff428acc 100644 --- a/src/systems/asset-streaming/asset-streaming.ts +++ b/src/systems/asset-streaming/asset-streaming.ts @@ -40,6 +40,8 @@ import { } from './asset-streaming-types.ts'; import { LRUCache, NetworkManager } from './asset-loading-infrastructure.ts'; +const _scratchFuturePos = new THREE.Vector3(); + // ============================================================================ // SPECIALIZED LOADERS // ============================================================================ @@ -1114,13 +1116,13 @@ export class AssetStreamer { private updatePredictiveLoading(): void { if (this.playerVelocity.lengthSq() < 0.01) return; - // Predict future position - const futurePos = this.playerPosition.clone().add( - this.playerVelocity.clone().multiplyScalar(this.config.predictiveLeadTime) - ); + // ⚡ OPTIMIZATION: Zero-allocation predictive loading to prevent GC spikes + _scratchFuturePos.copy(this.playerVelocity) + .multiplyScalar(this.config.predictiveLeadTime) + .add(this.playerPosition); // Preload region around predicted position - this.preloadRegion(futurePos.x, futurePos.z, 2); + this.preloadRegion(_scratchFuturePos.x, _scratchFuturePos.z, 2); } private getDistanceToCell(cell: GridCell): number { diff --git a/test-results/.last-run.json b/test-results/.last-run.json index cbcc1fba..5fca3f84 100644 --- a/test-results/.last-run.json +++ b/test-results/.last-run.json @@ -1,4 +1,4 @@ { - "status": "passed", + "status": "failed", "failedTests": [] } \ No newline at end of file