Claude-skill-registry dev-performance-performance-basics
Core R3F/Three.js performance optimization principles. Use when FPS drops below 60.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-performance-performance-basics" ~/.claude/skills/majiayu000-claude-skill-registry-dev-performance-performance-basics && rm -rf "$T"
manifest:
skills/data/dev-performance-performance-basics/SKILL.mdsource content
Performance Optimization Basics
"Optimize for mobile, scale up for desktop – 60 FPS is the goal."
When to Use
Use when:
- FPS drops below 60
- Debugging performance issues
- Starting optimization work
The 16ms Budget (60 FPS)
| System | Budget | Notes |
|---|---|---|
| Input | ~1ms | Event handling |
| Physics | ~3ms | Rapier/Cannon updates |
| Game Logic | ~4ms | State, AI, animations |
| Render | ~5ms | Three.js draw calls |
| Buffer | ~3ms | Safety margin |
| Total | 16.67ms | 60 FPS target |
Quick Start Canvas Config
// Performance-optimized Canvas <Canvas dpr={[1, 2]} // Limit pixel ratio performance={{ min: 0.5 }} // Auto-reduce quality gl={{ antialias: false }} // Disable for mobile > <Suspense fallback={null}> <Scene /> </Suspense> </Canvas>
Decision Framework
| Symptom | Likely Cause | Solution |
|---|---|---|
| Low FPS everywhere | Too many draw calls | Instancing, merging |
| FPS drops on zoom | LOD not implemented | Add LOD system |
| Mobile slow | DPR too high | Limit to 1.5 |
| Memory grows | Dispose missing | Add cleanup |
| Stuttering | GC pressure | Object pooling |
Progressive Optimizations
Level 1: Basic
// Limit device pixel ratio <Canvas dpr={Math.min(window.devicePixelRatio, 2)}> // Disable expensive features on mobile const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent); <Canvas shadows={!isMobile} gl={{ antialias: !isMobile, powerPreference: 'high-performance', }} >
Level 2: Object Reuse
// Reuse Vector3, Quaternion instances const position = useRef(new THREE.Vector3()); const rotation = useRef(new THREE.Quaternion()); useFrame(() => { position.current.set(0, 0, 0); // Reuse, don't create });
Level 3: Memory Management
// CRITICAL: Dispose of Three.js objects useEffect(() => { const geometry = new THREE.BoxGeometry(); const material = new THREE.MeshStandardMaterial(); return () => { geometry.dispose(); material.dispose(); if (material.map) material.map.dispose(); }; }, []);
Performance Monitoring
import { useFrame } from '@react-three/fiber'; import { useRef } from 'react'; function PerformanceMonitor() { const frameCount = useRef(0); const lastTime = useRef(performance.now()); useFrame(() => { frameCount.current++; const now = performance.now(); if (now - lastTime.current >= 1000) { console.log(`FPS: ${frameCount.current}`); frameCount.current = 0; lastTime.current = now; } }); return null; }
Anti-Patterns
❌ DON'T:
- Create objects inside useFrame
- Skip dispose() calls
- Use shadows on mobile without testing
- Render invisible objects
- Use uncompressed textures
✅ DO:
- Reuse Vector3, Quaternion instances
- Always dispose geometries and materials
- Profile before and after optimizations
- Compress textures (WebP, Basis)
Checklist
- DPR limited appropriately
- No object creation in useFrame
- Dispose called on cleanup
- Shadows disabled on mobile
- Textures compressed
- FPS stable at 60
Common Performance Killers
- Too many draw calls → Use Instances
- High polygon count → Use LOD
- Unoptimized textures → Compress, resize
- No frustum culling → Enable frustumCulled
- Memory leaks → Call dispose()
- GC pressure → Object pooling
Reference
- Three.js Performance Tips
- instancing.md - Instanced rendering
- lod-systems.md - LOD techniques