A self-contained, zero-dependency performance overlay for Solar2D. Drop in one file and get a real-time frame stats HUD with two layout modes, a live bar graph, and smart decoupled-mode detection.
- Real-time frame-time bar graph with color-coded green / yellow / red bars
- Two layout modes — horizontal bar view and compact vertical view (draggable)
- Decoupled mode detection — automatically corrects jitter reporting when logic rate ≠ refresh rate
- Monitor change detection (Windows) — recalculates all derived constants when the window moves to a different display
- Budget metric (Windows, enhanced builds) — CPU frame work time averaged per second
- Responds to window resize and fullscreen toggles automatically
- No external dependencies — pure Lua, single file
| Build | Support |
|---|---|
| Official Solar2D releases | Full support (core stats) |
2026.3729-siu.3 or higher |
Full support + monitor refresh rate, budget estimates, higher-precision CPU values |
Some statistics may not be available on all platforms. The budget metric is Windows-only and will read
0.00elsewhere.
Copy sph.lua into your Solar2D project, then require it as any other Lua module:
local sph = require("sph")That's it. The HUD appears immediately.
| Key | Action |
|---|---|
F2 |
Show / hide the HUD |
F3 |
Toggle between horizontal and vertical layout |
Keys are configurable — see setConfig() below.
The vertical window can be dragged to any position on screen.
Rescales the entire HUD. Any positive number is valid. Default is 1.0.
sph.setScale(1.5)Override default keys or starting mode. All fields are optional.
sph.setConfig({
mode = 2, -- starting layout mode (1 or 2)
keyHide = "f6", -- key to show/hide
keyMode = "f7", -- key to toggle layout
})Stops the HUD from updating (removes the enterFrame listener).
sph.pause()Resumes updates after a pause().
sph.resume()Programmatically toggles between horizontal and vertical layout.
Switch to a specific mode: 1 (horizontal) or 2 (vertical).
sph.setMode(2)Returns the current mode number (1 or 2).
Returns the active display.newGroup for the current mode. Useful if you need to manage z-ordering manually.
The module table proxies property reads and writes directly to the active display group, so you can position or adjust the HUD without needing a wrapper function:
sph.x = 20
sph.y = 40
sph.alpha = 0.8
sph.isVisible = false
print(sph.x) -- reads from the active groupWhichever layout mode is currently active receives the assignment. If you switch modes, set the position again — each mode has its own independent group.
When Solar2D's renderSync is enabled and the configured logic rate differs from the display refresh rate, SPH enters decoupled mode and adjusts automatically:
- Jitter is corrected for the structural beat frequency between the two rates, so only genuine jitter is flagged
- The stutter threshold is widened to account for the structural beat
- The config row shows
DECOUPLEDas a visual indicator - The graph target line shifts to reflect the render cadence
MIT — see LICENSE for details.

