Performance
On this page7
What this resource costs a server, how that was measured, and what you can do about it.
The short answer
Built and load-tested for a 256-player server. No database query in any tick, no query to recognise somebody, about 32 database writes a minute at full load, and about 2.5 KB of server memory per remembered person. An idle server costs about 0.01 ms per second.
How it was measured
The numbers come from a load simulation: the real server code of the resource runs with 256 simulated characters, and every database call is counted. It is not a test with 256 real players.
The profile is deliberately extreme:
| Characters online | 256 |
|---|---|
| Scans running at the same time | 50 |
| Live results open at the same time | 100 |
| Devices switched on | 32 |
| Deaths being resolved | 8 |
| Staff watching pairs | 4 |
| Memory table | a year of memories, 30 % expired, 15 % disguise memories |
| Scan churn | one scan per player every ten minutes, sustained |
Fifty simultaneous scans on a 256-player server is far beyond what a normal evening looks like. It is chosen as a ceiling, not as a typical load.
What to expect
An idle or quiet server pays almost nothing. With 256 characters loaded and nobody scanning, the server loops cost about 0.01 ms per second: they have nothing to do and return at once.
The database is quiet. About 32 writes and 68 reads per minute at the full profile above: roughly one write per finished scan.
- No query is ever issued from inside a per-second loop.
- Recognising somebody issues no query at all. The answer comes from memories that are already loaded, because the person looking is online.
MySQL is not on this resource's busy path.
Memory is proportional and stable. Each remembered person costs about 2.5 KB of server memory.
| Players | Roughly |
|---|---|
| 64 | ≈ 18 MB |
| 128 | ≈ 36 MB |
| 256 | ≈ 72 MB |
Treat those figures as a floor and budget about 25 % more on a live server (≈ 90 MB at 256 players). Over a sustained run the memory use stayed level — nothing leaks.
The scan and live-result loops are where the cost is. At the full stress profile — 50 simultaneous scans and 100 live results — these two loops are the largest single item. Both scale with activity, not with player count: a server with three scans running pays for three scans.
How the work scales
Everything is sized by what is happening, never by players × players:
| Work | Runs | Grows with |
|---|---|---|
| Scan progress | every 0.5 s | Scans running right now |
| Live results | every 1 s | Live results open right now |
| Device batteries | every 1 s | Devices switched on right now |
| Saving a finished scan | when a scan ends | Scans that just ended |
| Database clean-up | every ServerConfig.Prune.IntervalMinutes (15 min) | Rows past their retention |
That is why an empty server costs almost nothing and a busy one costs in proportion to how busy it is.
Tuning
If you need to reduce the load, these are the levers, in order of effect:
| Setting | Effect |
|---|---|
Config.Scene.Seconds (600) | Shorter live results = fewer to keep updated. The largest single lever |
Config.Scene.ShowDistance (10.0) | Smaller = fewer live results to keep updated |
Config.Scan.MaxScannersPerTarget (3) | Fewer simultaneous scans on the same person |
Config.Scan.MaxParallel (3) | Fewer people one player can scan at once |
Config.Scan.PairCooldownSeconds (60) | Raise it to cut repeated scans of the same pair |
Config.Scan.StaleSlotSeconds (10) | Lower it so scans that gain nothing free their slot sooner |
Config.Environment.Enabled | Switching weather and light off removes one calculation per scan step |
ServerConfig.Retention.* | Shorter retention = smaller tables |
On the client side:
| Setting | Effect |
|---|---|
Config.Scan.CandidateIntervalMs (300) | How often a player's game looks for people in front of them |
Config.Scan.MaxCandidates (8) | How many arrows can be drawn at once |
Config.Prompt.ShowOthers | Off = only the selected person gets an arrow |
Checking your own server
recognition:statusPrints the running scans, cache sizes, which integrations were detected, the voice low-trust flags, the Discord queues and a rolling performance window.
recognition:selftestThe installation check. Every line should say PASS. Include its output when you report a problem.
Database sizing
| Table | Grows with |
|---|---|
| Memories | Players × people each of them has met. Removed when they expire |
| Scans | Scans finished. Kept for the retention time |
| Recognition records | Aims, shots, cuffs, robberies. Kept for the retention time, and the busiest table on a combat-heavy server |
| Clothing classifications | Your clothing packs. Fixed size, written once |
| Papers | Camera reports and statements. Papers go blank after 60 days |
recognition:prune runs the clean-up immediately if you would rather not wait
for the next run (every 15 minutes by default).