perf Stable WINMACLNX
Real-time frame-level performance metrics — frame time, JS time, layout time, GPU time, and memory usage. Works in both dev and production builds.
Import
import { perf } from 'veloxkit'perf.snapshot()
Synchronously returns a snapshot of all current metrics.
const snap = perf.snapshot()Returns PerfSnapshot | null
type PerfSnapshot = {
fps: number // frames per second (rolling average)
frameTime: number // average frame time in ms
frameTimeP99: number // 99th-percentile frame time (worst-case)
jsTime: number // time spent in JS per frame (ms)
layoutTime: number // time spent in Taffy layout (ms)
gpuTime: number // GPU command submission time (ms)
memoryJS: number // V8 heap used in MB
nodeCount: number // number of live layout nodes
}Returns null when the bindings are unavailable (e.g. in tests).
perf.onBudgetExceeded(cb, opts?)
Register a callback that fires whenever a frame exceeds a target time budget.
const unsub = perf.onBudgetExceeded((violation) => {
console.warn('Slow frame:', violation)
// → { budget: 16.667, actual: 24.3, jsTime: 18.1, layoutTime: 1.2 }
}, {
target: 16.667, // ms — default: 16.667 ms (60 fps)
})
// Remove listener:
unsub()Returns an unsubscribe function.
perf.onLeakDetected(cb)
Register a callback for dev-mode memory / node-count leak warnings. Only fires in development builds — silently no-ops in production.
const unsub = perf.onLeakDetected((warning) => {
console.warn('[leak]', warning.msg)
// → { type: 'node_count', count: 342, msg: 'Node count growing steadily...' }
})Examples
Live FPS display
import { perf } from 'veloxkit'
import { useState, useEffect } from 'react'
function FpsCounter() {
const [fps, setFps] = useState(0)
useEffect(() => {
const id = setInterval(() => {
const snap = perf.snapshot()
if (snap) setFps(Math.round(snap.fps))
}, 500)
return () => clearInterval(id)
}, [])
return (
<Text style={{
position: 'absolute',
top: 8, right: 8,
fontSize: 12,
color: fps >= 55 ? '#4ade80' : fps >= 30 ? '#facc15' : '#f87171',
}}>
{fps} fps
</Text>
)
}Performance overlay (dev mode)
import { perf } from 'veloxkit'
import { useState, useEffect } from 'react'
function PerfOverlay() {
const [snap, setSnap] = useState(null)
useEffect(() => {
const id = setInterval(() => setSnap(perf.snapshot()), 200)
return () => clearInterval(id)
}, [])
if (!snap) return null
return (
<View style={{
position: 'absolute', bottom: 0, left: 0, right: 0,
backgroundColor: '#00000099',
padding: '4px 8px',
flexDirection: 'row',
gap: 16,
}}>
{[
['FPS', snap.fps.toFixed(1)],
['Frame', `${snap.frameTime.toFixed(1)} ms`],
['P99', `${snap.frameTimeP99.toFixed(1)} ms`],
['JS', `${snap.jsTime.toFixed(1)} ms`],
['Nodes', snap.nodeCount],
['Mem', `${snap.memoryJS.toFixed(1)} MB`],
].map(([label, value]) => (
<View key={label} style={{ alignItems: 'center' }}>
<Text style={{ fontSize: 9, color: '#9999bb' }}>{label}</Text>
<Text style={{ fontSize: 11, color: '#e7ecff' }}>{value}</Text>
</View>
))}
</View>
)
}Budget monitoring in production
// Log frame budget violations to crash reporter
perf.onBudgetExceeded((v) => {
if (v.actual > 50) { // only log severely slow frames (< 20 fps)
crash.getReports() // fire-and-forget; actual logging is in Rust
console.error(`[perf] Frame ${v.actual.toFixed(1)}ms (budget ${v.budget}ms)`)
}
}, { target: 16.667 })perf.snapshot() is synchronous and costs ~1 µs — safe to call every frame or on every render without performance impact.