Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BOLT'S JOURNAL - PERFORMANCE LEARNINGS.md
Original file line number Diff line number Diff line change
@@ -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.
12 changes: 7 additions & 5 deletions src/systems/asset-streaming/asset-streaming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ============================================================================
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion test-results/.last-run.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"status": "passed",
"status": "failed",
"failedTests": []
}
Loading