Performance & Operations Advice
Belongs to: Reference · Related: Diagnostics & Troubleshooting · Commands
How to tune and operate QI's loading, refreshing, and caching under large item counts / high-population servers.
1. Loading & Reload
- Items / sections / sets / action tables are loaded at startup and on
/qi reload. A reload recompiles everything and hot-refreshes online players. - With large item counts,
/qi reloadhas a one-time cost (compile + validate + refresh). Advice:- Avoid frequent
reloadduring peak hours; make your changes in batches and reload once. - Use
/qi reloadinstead of a restart — hot refresh is faster.
- Avoid frequent
- Compile results have an LRU cache (
CompileSessionStore, up to 4096 entries, keyed by item fingerprint); repeated assembly hits the cache.
2. Equipment Attribute Sync Cost
Attribute sync is driven by EquipmentWatcher and is already debounced:
- It compares the "equipment signature" and only refreshes when it changes, avoiding a full recompute every tick.
- The polling cycle is scheduled at about 1 tick, but an actual refresh only happens when equipment changes.
Optimization points:
- Avoid external logic that "force-calls
refreshEquipmentAttributesevery tick"; let the watcher refresh on demand by itself. - A change in set piece count triggers an additional delayed refresh (about 1 second) — this is normal debouncing.
3. Action Trigger Cost
- Triggers have a 120ms dedup window (
ActionTriggerDedup) to prevent a single operation from triggering multiple times. - Cooldowns are stored in memory (
ConcurrentHashMap) and are lost on restart — this is by design, not persisted. tick-period triggers are scheduled byTickHandTickerevery 20 ticks, acting on held / equipped items. Don't configure overly dense ticks (such as every 1 tick); usetick: 40(2 seconds) etc. as needed.
4. Permanent Effects & Sets
PermEffectSyncrenews permanent potion effects about every 6 seconds (120 ticks); this is a low-frequency task.- When set attributes drop below the threshold, the
qi:set:<id>source is automatically removed.
5. Scoping Refresh Commands
When you need to re-render players' old items according to the new config, pick the scope on demand — don't always full-refresh the whole server:
| Command | Scope | When to use |
|---|---|---|
/qi refresh hand | Main hand only | Fastest for self-testing |
/qi refresh equipment | Equipment slots | Changed equipment-related things |
/qi refresh inventory | Backpack | Changed backpack items |
/qi refresh all | All online players | Uniform refresh after a big change, be careful with many players |
Refresh = rebuild() + variables().refresh() per item; the more items, the heavier. See Diagnostics & Troubleshooting §6.
6. Write Domain / Routing Strict Mode
config.yml:
write-domains.strict: trueandaction-routing.strict: trueare the default and recommended: they turn potential errors into hard errors at save / load time, avoiding runtime hazards.- Only set them to
falsetemporarily during migration / debugging (downgrades to a warning), then change back totrueonce stable.
See Layers & Assembly and Validation Error Quick Reference.
7. Content Packs & Backup
- Use
/qi packs exportto periodically export content packs as content snapshot backups / cross-server distribution. - Items / sets / sections are all plain YAML — just include them in your config version control / scheduled backups directly.
8. Monitoring Checklist
Check periodically / after going live:
- [ ]
/qi diagnose— all subsystems available (N/M with N=M) - [ ]
/qi problems— no unhandled problems - [ ] Startup log — attribute backend / gem backend connected as expected
- [ ]
/qi reloadfrequency kept under control during peak hours
9. Capacity Planning Experience
| Scale | Advice |
|---|---|
| Hundreds of items | Default config is sufficient |
| Thousands of items | Avoid peak-hour reload; manage with split content packs; watch reload duration |
| High population (hundreds online) | Let the watcher self-manage attribute refresh, avoid external per-tick force refresh; widen tick trigger intervals |