# Performance Budget and Optimization Report

Mechanica targets 60 FPS desktop and at least 30 FPS mobile. The architecture is designed for progressive enhancement: every route works with procedural previews now and can later load optimized GLB assets lazily.

## Runtime budgets

| Metric | Desktop target | Mobile target |
| --- | ---: | ---: |
| Catalogue interaction latency | < 50 ms | < 100 ms |
| Initial JS before model route | < 350 KB gzip | < 350 KB gzip |
| Per-machine compressed model payload | 1-8 MB typical | 1-5 MB preferred |
| Frame time | < 16.7 ms | < 33.3 ms |
| Draw calls per machine | < 300 | < 150 |
| Texture memory | < 256 MB | < 96 MB |
| Main-thread long tasks | none > 100 ms | none > 100 ms |

## Current milestone performance choices

- Vite for fast ESM development and optimized production bundling.
- Route-level data flow with no monolithic viewer file.
- Procedural preview avoids missing asset fetches.
- Device pixel ratio capped to `[1, 2]`.
- Registry is static and small enough to load instantly.
- Framer route transitions respect reduced motion.
- CSS theme tokens avoid runtime style recalculation complexity.
- Catalogue filtering is memoized.
- FPS monitor samples with `requestAnimationFrame`.

## 3D optimization plan

### Geometry

- Use instancing for repeated parts: bearing balls, rollers, fan blades, compressor stages, turbine blades, bolt heads, gear teeth.
- Merge static non-selectable geometry when possible.
- Keep selectable parts separate only where interaction requires it.
- Use LODs for dense assemblies.

### Materials

- Reuse materials across parts.
- Avoid cloning materials per frame.
- Use x-ray/wireframe override material caches.
- Compress textures with KTX2.
- Avoid large transparent surfaces unless necessary.

### Animation

- Keep kinematics math-based.
- Avoid React state updates inside every frame.
- Mutate Three.js objects in animation controllers.
- Use normalized cycle time for stable loops.
- Pause or reduce animation when tab is hidden.

### Loading

- Lazy-load machine assets on viewer routes.
- Preload on catalogue hover/focus.
- Use skeleton panels and progress overlays.
- Keep layout stable during loading.
- Show procedural fallback if GLB load fails.

### Mobile

- Cap DPR to 1 on low-end devices.
- Disable expensive shadows under low quality mode.
- Reduce annotation density.
- Use lower LOD models.
- Prefer simpler environment lighting.

## Measurement plan

Add the following later:

- Lighthouse CI for app shell.
- Web Vitals reporting.
- Bundle analyzer.
- GLB budget checker.
- Runtime draw-call and triangle counters behind `VITE_ENABLE_DEBUG_OVERLAYS`.
- Automated smoke tests for low-end viewport sizes.

## Risks

| Risk | Mitigation |
| --- | --- |
| 28 high-detail GLBs inflate load time | Route-level lazy loading, compression, preloading, LODs |
| Transparent x-ray mode harms frame rate | Material override cache, opacity limits, mobile quality fallback |
| Annotation labels overwhelm mobile | Density rules and toggle default based on viewport |
| Complex engines exceed draw-call budget | Instancing and merged non-interactive meshes |
| URL state grows too long | Compact encoding and omission of defaults |
