$npx -y skills add TabooHarmony/roblox-brain --skill roblox-performanceUse when profiling Roblox performance or diagnosing FPS, memory, network, mobile, or hot-path problems, including MicroProfiler and optimization.
| 1 | # Roblox Performance |
| 2 | |
| 3 | ## When to Load |
| 4 | |
| 5 | Use when profiling, diagnosing lag, optimizing hot paths, or setting performance budgets. Load if the user mentions FPS drops, memory issues, network bandwidth, or mobile optimization. |
| 6 | |
| 7 | ## Quick Reference |
| 8 | |
| 9 | ### Profiling Tools |
| 10 | - **MicroProfiler (Ctrl+F6)** — Per-frame breakdown: scripts, physics, rendering. Primary tool for finding what's slow. |
| 11 | - **Developer Console (F9)** — Stats tab: memory, network, render stats. Server Stats for server-side metrics. |
| 12 | - **Script Profiler (Ctrl+Alt+F5)** — Per-script CPU usage and heap allocations. |
| 13 | |
| 14 | ### Performance Targets |
| 15 | | Metric | Target | Hard Limit | |
| 16 | |--------|--------|------------| |
| 17 | | Server heartbeat | < 16ms | < 33ms | |
| 18 | | Client FPS (desktop) | 60 | 30 | |
| 19 | | Client FPS (mobile) | 45 | 30 | |
| 20 | | Memory (mobile) | < 800MB | < 1.2GB | |
| 21 | |
| 22 | ### Optimization Patterns |
| 23 | - **Throttle Heartbeat** — Batch expensive work at fixed intervals (10/sec, not 60) |
| 24 | - **Cache references** — Store workspace lookups in variables, avoid repeated FindFirstChild |
| 25 | - **Spatial partitioning** — Distance-based activation instead of checking all entities |
| 26 | - **Lazy loading** — Stream content from ServerStorage as player approaches |
| 27 | |
| 28 | ### Parallel Luau |
| 29 | - Use Actors only after profiling identifies isolatable CPU work. |
| 30 | - Workers compute; synchronize before restricted DataModel writes. |
| 31 | - SharedTable and mutexes add coordination cost; they do not replace ownership boundaries. |
| 32 | |
| 33 | ### Object Pooling |
| 34 | ```luau |
| 35 | -- Core pattern: pre-clone, reuse, avoid GC pressure |
| 36 | local Pool = {} |
| 37 | function Pool:get(): Instance |
| 38 | return table.remove(self._available) or self._template:Clone() |
| 39 | end |
| 40 | function Pool:release(obj: Instance) |
| 41 | obj.Parent = nil |
| 42 | table.insert(self._available, obj) |
| 43 | end |
| 44 | ``` |
| 45 | |
| 46 | ### StreamingEnabled Essentials |
| 47 | - **On by default** for new places. Only BaseParts stream; Folders, ModuleScripts, RemoteEvents load at join. |
| 48 | - **Streamed-out = parented to nil**, not destroyed. Luau refs persist if it streams back. |
| 49 | - **Config**: `StreamingTargetRadius` (start 256, tune down for mobile), `StreamingMinRadius` (~64). |
| 50 | - **Gotcha**: `FindFirstChild("DistantPart")` returns nil if streamed out. Use WaitForChild with timeout. |
| 51 | |
| 52 | ### Mobile Quick Wins |
| 53 | - Keep < 5000 visible parts. Textures max 512x512. Cap particles at 50 emitters. |
| 54 | - Use CanvasGroup for UI batching. Consider disabling GlobalShadows. |
| 55 | |
| 56 | **MCP verification:** collect a baseline and inspect runtime counters after changes. |
| 57 | **Need more detail?** Load `references/full.md` for the complete reference with code examples, API tables, and edge cases. |