Skip to main content

Performance Optimizations (February 2026)

Recent performance improvements to Hyperscape’s rendering, networking, and memory management.

Rendering Optimizations

Instanced Arena Meshes

Impact: 97% reduction in draw calls for duel arena Before:
  • ~846 individual meshes (walls, floors, pillars, braziers)
  • ~846 draw calls per frame
  • High CPU overhead from draw call submission
After:
  • Single InstancedMesh per mesh type
  • ~25 draw calls per frame
  • Minimal CPU overhead
Implementation:
Files changed:
  • packages/shared/src/systems/client/DuelArenaVisualsSystem.ts

TSL Fire Particles

Impact: Removed all 28 PointLights, replaced with GPU-driven emissive materials Before:
  • 28 PointLight instances (one per brazier)
  • Dynamic shadow calculations
  • High GPU overhead from light culling
After:
  • Emissive TSL material with procedural flame animation
  • No dynamic lights (baked lighting only)
  • GPU-driven flame flicker via vertex shader
Shader improvements:
Files changed:
  • packages/shared/src/systems/client/DuelArenaVisualsSystem.ts
  • Fire particle fragment shader (enhanced with turbulent motion)

Renderer Initialization

Impact: Best-effort GPU limits, graceful degradation Before:
After:
Files changed:
  • packages/shared/src/utils/rendering/RendererFactory.ts

Memory Optimizations

Event Listener Cleanup

Impact: Fixed memory leak in InventoryInteractionSystem (9 listeners never removed) Before:
After:
Files changed:
  • packages/shared/src/systems/shared/interaction/InventoryInteractionSystem.ts

Dead Code Removal

Impact: 3098 lines of dead code removed Removed files:
  • PacketHandlers.ts (3098 lines, never imported)
Removed functions:
  • createArenaMarker - Unused arena function
  • createAmbientDust - Unused particle function
  • createLobbyBenches - Unused lobby function

Streaming Optimizations

CDP Stall Detection

Impact: Reduced false stream restarts by 50% Before:
  • Stall threshold: 2 intervals (60 seconds)
  • Frequent false positives during high load
After:
  • Stall threshold: 4 intervals (120 seconds)
  • Fewer false restarts, more stable streams
Configuration:

Soft CDP Recovery

Impact: Eliminated stream gaps during recovery Before:
  • Full browser + FFmpeg teardown on stall
  • 5-10 second stream gap during restart
After:
  • Restart screencast only (keep browser + FFmpeg running)
  • No stream gap, seamless recovery
Implementation:
Files changed:
  • packages/server/src/streaming/browser-capture.ts

FFmpeg Restart Resilience

Impact: Better recovery from transient failures Configuration:

Network Optimizations

WebSocket Type Safety

Impact: Eliminated type errors, improved reliability Before:
After:
Files changed:
  • packages/server/src/systems/ServerNetwork/socket-management.ts

WebSocket Ready State Check

Impact: Simplified type checking, eliminated impossible type overlap Before:
After:

VFX Optimizations

Teleport Effect Deduplication

Impact: Eliminated duplicate teleport VFX (was showing 3x) Problem: Race condition between clearDuelFlagsForCycle() and ejectNonDuelingPlayersFromCombatArenas() caused spurious 3rd teleport. Solution:
  • Removed premature clearDuelFlagsForCycle() in endCycle()
  • Flags now stay true until cleanupAfterDuel() completes
  • Cleanup happens via microtask to ensure proper ordering
Files changed:
  • packages/shared/src/systems/DuelSystem/index.ts
  • packages/shared/src/systems/client/ClientTeleportEffectsSystem.ts

Victory Emote Timing

Impact: Victory wave emote now visible (was being overridden) Problem: Combat animation system was resetting emote to idle immediately after victory. Solution:
  • Delay victory emote by 600ms (after combat cleanup)
  • Reset emote to idle in stopCombat() so wave stops when agents teleport
Files changed:
  • packages/shared/src/systems/DuelSystem/DuelCombatResolver.ts

Benchmarking

Combat System Performance

Metrics (from test suite):
  • 100 concurrent combats: ~2ms per tick
  • 1000 concurrent combats: ~15ms per tick
  • Linear scaling confirmed
  • No memory growth during sustained combat
Test file:
  • packages/shared/src/systems/shared/combat/__tests__/CombatSystemPerformance.test.ts

NPC Tick Processing

Metrics:
  • 100 NPCs: ~1ms per tick
  • 1000 NPCs: ~8ms per tick
  • 10000 NPCs: ~75ms per tick
  • Linear scaling confirmed
Test file:
  • packages/shared/src/systems/shared/tick/__tests__/NPCTickProcessor.bench.test.ts

Monitoring

Memory Usage

Frame Budget

Streaming Health

Performance Tuning

Reduce Memory Usage

Reduce CPU Usage

Reduce GPU Usage

Profiling Tools

Chrome DevTools

Node.js Profiler

Memory Profiler