Long post, bear with me. Real numbers from a production server, not synthetic.
Setup
96-slot RP server, ~70 concurrent at peak, 110 resources running. Average frametime: 8.2ms, with peaks at 22ms during gunfights.
The investigation
I started with the obvious: resmon, find the worst offenders, optimize them.
Resmon showed nothing pathological — top resource was at 1.4ms. So either lots of small things, or resmon was lying.
I built a custom profiler that wraps every Citizen.CreateThread, every AddEventHandler, and every RegisterNetEvent to measure their actual wall-clock cost over a 60s window.
What I found
A "lightweight UI library" we'd been using for tooltips was registering 47 different event handlers across 12 resources. Each handler was tiny (~0.1ms), but they all chained into a central dispatch event that ran a string-comparison loop on every fire.
Net cost: 5.8ms per frame spread across 47 invisible handlers.
The fix
Replaced the entire library with 80 lines of custom code that uses stateBags + a single dispatcher.
Results
| Metric | Before | After |
|---|---|---|
| Avg frametime | 8.2ms | 0.4ms |
| 99p frametime | 22ms | 1.8ms |
| Crashes/week | 3 | 0 |
Lessons
- Resmon lies about cumulative cost across libraries
- Aggregate string comparisons in event handlers are deadly at scale
- Sometimes the right answer is "rip it out and write 80 lines yourself"
Will publish the profiler tool next week if there's interest.