PerfectOptimizer
| Version | 1.3.0 |
|---|---|
| Platform | Hytale Server Plugin |
| Dashboard languages | EN, FR, ES, PT, DE |
| Dependencies | None (self-registering) |
| JVM requirements | Java 21+, HotSpot recommended |
| Plugin size | ~150 KB |
| Permission node | perfectoptimizer.admin |
PerfectOptimizer is an active server load manager paired with a private live web dashboard hosted at analytics.perfect-plugins.com. Every server gets its own private URL with 19 pages of stats, 17 prescriptive rules, one-click auto-apply, a CPU flamegraph profiler, a heap dump trigger, world entity heatmap, Sentry-style error capture and statistical anomaly detection.
Most Hytale tools only observe your server. PerfectOptimizer acts: distant NPCs are throttled or frozen, per-player chunk radius is tuned in real time, idle entity TTL is accelerated, AFK player chunks shrink, tier hysteresis prevents flapping, and heap pressure triggers escalation. Every recommendation can be applied to the live config with a single click from the dashboard, with one-click rollback.
Installation
- Drop
PerfectOptimizer-1.3.0.jarinto your server's mods folder. - Start or restart the server.
- The plugin auto-registers with the dashboard on first boot and prints your private URL in console.
- Open the URL in any browser. The dashboard is live within seconds, no login required.
- Run
/poptimizer dashboardin-game any time to reprint your private URL as a clickable link.
Config files are auto-generated under
mods/KatsuyaTV_PerfectOptimizer/.
No manual setup required.
Live Dashboard
Once a server has registered, the dashboard streams metrics every 10 seconds and persists 14 days of history. The URL is the auth: anyone with the URL has access, so treat it like a password.
19 pages
| Page | What you see |
|---|---|
| Overview | Live KPIs: status, TPS, players, tier, memory, MSPT p95, CPU, lag spikes. |
| Recommendations | Active suggestions sorted by severity, with Apply / Snooze / Dismiss. |
| TPS history | 10s / 1m / 5m TPS over selectable range. Red dots mark anomalies. |
| MSPT | avg / p50 / p95 / p99 / max milliseconds per tick. |
| Players | Player count history. |
| Memory | Heap used vs max with pool live snapshot. |
| Heap classes | Top 20 Java classes occupying heap, with % of total. |
| GC | Per-collector totals plus pause timeline (concurrent cycles separated from STW pauses). |
| CPU & Threads | Process / system CPU history plus top threads by CPU time. |
| Worlds | Per-world entity count, loaded chunks, individual TPS and tick avg. |
| Ping | Player ping percentiles plus worst-ping leaderboard. |
| System | OS, JVM, disks, network interfaces and counters. |
| Tier history | Every optimizer tier change with from / to / timestamp. |
| Lag spikes | Individual spike events with world, tick avg, severity. |
| Activity log | Unified timeline: tier changes, lag spikes, GC pauses, memory states, escalations. |
| Errors | Captured warnings and exceptions grouped by signature. |
| Heap dumps | Trigger a live heap dump and review past dump metadata. |
| Flamegraph | CPU sampler sessions rendered as clickable SVG flamegraphs. |
| World heatmap | Per-chunk entity density visualized as a 2D grid per world. |
Smart Recommendations
17 prescriptive rules scan the last 24 hours of data continuously and surface actionable suggestions. Each rule produces a card with severity (critical / warn / info), a plain-English explanation, a suggested config change, the expected impact and a dismiss control with snooze options.
Rule categories
- TPS / CPU / scheduling: TPS low with idle CPU, host CPU contention, hidden MSPT spikes, per-world TPS divergence.
- Heap / memory: Old Gen pool saturated, slow heap growth trend over 24h.
- GC: frequent long stop-the-world pauses (concurrent cycles correctly excluded).
- Lag: spike count above threshold, spike cluster around the same hour of day.
- Tier hysteresis: yo-yo flapping, currently escalated emergency.
- ECS optimization features: NPC LOD off when populated, NPC population very high.
- Host / disk: disk usage above 85%, heap tight at peak players.
- Network: p95 player ping high.
- Threads: thread count grew abnormally vs early samples.
Rules are version-aware. If your plugin is older than the version that introduced a fix, the recommendation suggests upgrading first.
One-Click Auto-Apply
Every applicable recommendation gets a green ⚡ Apply now button. One click and the patch
travels to the plugin on its next push (≤ 10 seconds), gets applied to the live OptimizerConfig
via reflection, the file is saved and the scheduler reloads its tier. Zero downtime.
How the closed loop works
- You click Apply now in the dashboard.
- Backend queues a structured patch
{ fieldName: newValue }inpending_applies. - Plugin's next ingest push pulls pending patches from the ingest response body.
- Reflection sets the field on the live config object, then writes config.json.
- Plugin reports back
appliedChangesin its next push with the previous values for rollback. - Dashboard shows the entry under "Applied changes" with a ↩ Rollback button.
Rollback
One click on Rollback enqueues a new pending apply with the previous values restored. Original entry is marked rolled back. Same 10-second round-trip.
Kill-switch
Set dashboardAutoApplyEnabled to false in config.json to disable remote patching
entirely. Recommendations still appear in the dashboard but the Apply button has no effect.
CPU Flamegraph
In-game command /poptimizer cpu <sec> starts a sampling session.
The sampler wakes every 10 ms, dumps every live thread's stack via ThreadMXBean,
folds the frames into a call tree with per-node sample counts.
Result appears in the dashboard within ~10 seconds.
- Duration: 5 to 300 seconds (default 30).
- Sampling interval: 2 to 100 ms (default 10).
- Reading: wider rectangles = more time spent. Hover for sample percentage.
- Sessions kept: last 10 per server.
Use it to identify unexpected hot frames. Plugin slowdowns, runaway redstone, or AI tick contention become obvious as wide bars in the flamegraph.
Heap Dumps
One-click ⚡ Live objects dump or Full heap (slower) from the dashboard calls
HotSpotDiagnosticMXBean.dumpHeap() on the live JVM.
The .hprof file is written to disk on the server (multi-GB possible, no upload).
The JVM pauses briefly during the write (1-30 s depending on heap size).
Open the file in Eclipse MAT or VisualVM to analyse what is eating your heap. Dump metadata (path, size, status) appears in the dashboard history.
Error Capture
A java.util.logging handler is attached to the root logger on plugin start.
Every WARNING and SEVERE record with a Throwable is hashed by signature
(exception class + normalized message + top 3 frames), grouped by occurrence count and shipped
with every ingest push.
The dashboard Errors page shows each unique error once with a ×N count badge.
Plain logger warnings (without exception) are also captured so you see recurring "Took too long" messages.
Mark an error as resolved with a single click; it disappears from the active view until it reoccurs.
World Heatmap
Every 30 seconds, the plugin iterates every entity with a TransformComponent across all
started worlds and tallies them per chunk (x >> 4, z >> 4).
The top 500 hottest chunks per world are pushed to the dashboard.
The frontend renders a 2D grid colored from cold (dark blue) to hot (bright red) where each cell is one chunk. Hot spots equal chunks that probably need entity cleanup, lower spawn density, or a stricter world tier override.
Anomaly Detection
A backend z-score detector scans the last 24 hours of samples for TPS, MSPT p95, heap ratio and CPU. Threshold is 2.5 sigma, minimum window is 30 samples to avoid spurious markers.
Outliers appear as red dots overlaid on the TPS, MSPT, Memory and CPU charts. They make sudden spikes visually obvious without scrolling through hours of charts.
Active Optimization (Always Running)
The optimizer adapts its behaviour to load in real time. Even with the dashboard disabled, these subsystems run continuously.
NPC LOD
Iterates every NPC every 2 seconds. Distance to the nearest player is computed.
Beyond 160 blocks, NPCs are fully frozen (zero AI). Mid / far / very-far distance
tiers modulate the StepComponent tick interval (0.2 s / 0.5 s / 1.0 s).
Massive TPS win on NPC-heavy worlds.
Per-player ChunkTracker radius
For each player in each world, if TPS drops below 18, the player's hot radius shrinks by 2 chunks. Hysteresis cooldown of 30 s prevents oscillation. Original radius restored once TPS recovers.
Despawn accelerator
Entities with a DespawnComponent and no player within 64 blocks for 30 seconds
see their remaining TTL multiplied by 0.5 (floor 30 s). Cleans up forgotten mob accumulations
without aggressive culling.
Idle player chunk shrink
An AFK player's loaded chunk radius collapses to a minimum. On return from AFK, the radius is restored gradually (hot immediate, minLoaded after 15 s).
Tier hysteresis
Softening a tier requires both a 15-minute cooldown since the last degradation AND a 25% drop in player count. Prevents yo-yo flapping when player count oscillates around a threshold.
Heap pressure escalation
Heap ratio is a second axis alongside TPS. Above 80% used, tier is forced to "high". Above 92%, tier is forced to "emergency", independently of TPS.
Critical escalator
Sustained critical TPS locks all worlds to emergency tier with a global override. Releases automatically when TPS recovers.
Console log noise filter
26 default regex patterns strip Hytale spam from the root logger ("Took too long", "missing manifest", "overpopulation", etc.). Custom patterns can be added in config.
Commands
| Command | Description |
|---|---|
/poptimizer | Show command help. |
/poptimizer ui | Open the in-game admin panel. |
/poptimizer status | Tier, TPS, active / idle / AFK viewer counts. |
/poptimizer dashboard | Print a clickable link to your private dashboard. |
/poptimizer apply | Force re-apply the current tier. |
/poptimizer reload | Reload config.json from disk. |
/poptimizer save | Save current config to disk. |
/poptimizer cpu <N> | CPU flamegraph sampler for N seconds (default 30). |
/poptimizer profile <N> | Profile session, exports TXT and JSON report. |
/poptimizer lag | Lag spike counters. |
/poptimizer memory | JVM heap status (live). |
/poptimizer metrics | Public Prometheus metrics endpoint info. |
/poptimizer npc | NPC LOD counters. |
/poptimizer logfilter | Log noise filter status. |
All commands require the permission node perfectoptimizer.admin.
In-Game Admin Panel
/poptimizer ui opens a live panel that shows the same KPIs as the dashboard:
tier, TPS, player count, LOD ratio, viewer breakdown, spawn pause state, NPC counts.
Sliders let you tune the medium and high tier thresholds, plus the force-high TPS threshold,
directly in-game. Changes auto-save and trigger a re-apply.
Configuration
The plugin auto-generates its config file on first run with sensible defaults. Edit it then reload in-game with /poptimizer reload to apply changes without a restart.
Config file path:
mods/KatsuyaTV_PerfectOptimizer/config.json
Key fields
| Field | Default | Notes |
|---|---|---|
enabled | true | Master switch. |
updateIntervalSec | 5 | Scheduler tick. |
tpsForceHighThreshold | 17.0 | Force tier high below this TPS. |
tpsCriticalThreshold | 12.0 | Force tier emergency below this TPS. |
tierHysteresisEnabled | true | Anti-flapping on tier transitions. |
heapPressureEscalateEnabled | true | Use heap ratio as a 2nd axis for tier. |
heapPressureHigh | 0.80 | Force tier high above this heap ratio. |
heapPressureCritical | 0.92 | Force tier emergency above this heap ratio. |
npcLodEnabled | true | Distance-based NPC tick throttling and freeze. |
npcLodFreezeDistance | 160 | Blocks beyond which NPCs are frozen. |
perPlayerRadiusEnabled | true | Tune chunk radius per player based on TPS. |
despawnAcceleratorEnabled | true | Accelerate idle entity despawn. |
idlePlayerActionsEnabled | true | Shrink AFK player chunks. |
memoryWatchdogEnabled | true | Heap warn / critical thresholds. |
memoryWarnRatio | 0.75 | Warn above this heap ratio. |
memoryCriticalRatio | 0.90 | Critical above this heap ratio. |
lagProfilerEnabled | true | Detect and log tick spikes. |
lagSpikeMs | 100.0 | Tick threshold to count a spike. |
lagSevereSpikeMs | 250.0 | Tick threshold for severe spikes. |
criticalEscalatorEnabled | true | Lock all worlds to emergency on sustained low TPS. |
gcMonitorEnabled | true | Capture GC events live. |
heapSummaryEnabled | true | Capture class histogram every minute. |
worldHeatmapEnabled | true | Capture per-chunk entity density every 30 s. |
logNoiseFilterEnabled | true | 26 default regex strip patterns on root logger. |
dashboardPushEnabled | true | Stream metrics to analytics.perfect-plugins.com. |
dashboardPushIntervalSec | 10 | Push frequency. |
dashboardAutoApplyEnabled | true | Allow remote config patches from the dashboard. |
Per-world overrides are supported via the worldOverrides map (mode: stricter, relaxed, force-tier, disabled).
Discord Webhooks
Set discordWebhookUrl in config to receive alerts. Five event types are configurable:
webhookOnTierChange— when the optimizer changes tier.webhookOnTpsAlert— when TPS drops below the critical threshold.webhookOnLagSpike— on severe lag spikes (cooldown enforced).webhookOnMemoryAlert— on heap critical transitions.webhookOnSustainedCritical— when the critical escalator locks all worlds.webhookOnGcPause— on long stop-the-world pauses (concurrent cycles excluded since v1.3.0).
Dashboard Languages
The dashboard supports five languages with per-user preference stored in browser localStorage. Flag picker is at the bottom of the sidebar.
- 🇬🇧 English
- 🇫🇷 French
- 🇪🇸 Spanish
- 🇵🇹 Portuguese
- 🇩🇪 German
Every page has an inline help banner explaining the metric, the safe range and what to do when values go red.
FAQ
Does the plugin send any data outside my server?
Yes, performance metrics are streamed every 10 seconds to analytics.perfect-plugins.com.
Only operational metrics are sent (TPS, MSPT, heap pool sizes, GC events, error groups,
per-world counters, ping summaries). No player data, no chat, no inventory contents, no positions.
Set dashboardPushEnabled to false to disable the stream entirely;
the plugin still works as a local optimizer.
Who can access my dashboard?
Anyone with the private URL (token-in-URL auth, 192-bit randomness). Treat it like a password. Sharing it with your staff team is the intended workflow.
What if my JVM is not HotSpot?
The plugin still runs and active optimization works. Two features are limited on non-HotSpot JVMs:
heap class summary (no DiagnosticCommand MBean) and heap dumps (no
HotSpotDiagnosticMXBean). The relevant pages will say "unavailable" instead of crashing.
How long are metrics kept?
14 days of samples, lag events, GC events and activity log entries. Cleared every 6 hours by a background sweep. Recommendations history, applied changes history and heap dump metadata are kept indefinitely.
Can I disable auto-apply but keep the dashboard?
Yes, set dashboardAutoApplyEnabled to false. The dashboard stays fully functional, only the Apply now buttons stop having effect.
What about Hytale Update 5 / JOML?
Fully compatible. All vector math has been ported to org.joml.
Multi-server setups?
Each server is registered independently with its own fingerprint and gets its own dashboard URL. Restart preserves the token. There is no cross-server shared dashboard yet.
Troubleshooting
Dashboard URL never appears in console
Check that dashboardPushEnabled is true. Verify the server has outbound HTTPS access. Run /poptimizer dashboard to force-print the URL once registration completes.
No metrics on the dashboard
Run /poptimizer dashboard to confirm you have the right URL. Check console for "Dashboard push failed" entries. First sample appears within 10 seconds of plugin start.
Heap classes page says "Histogram unavailable"
Your JVM is not HotSpot (e.g. OpenJ9). The histogram requires the HotSpot diagnostic MBean. Other pages keep working.
Apply now button does nothing
Check that dashboardAutoApplyEnabled is true and the plugin can write to its config folder. Reports failures with error_message in the Applied changes history.
Recommendations include "Upgrade to vX first"
Your installed plugin version is below the version that introduced the field the rule wants to set. Update the JAR.
Documentation for PerfectOptimizer v1.3.0. Generated by PerfectPlugins. For support, open a ticket on the PerfectPlugins Discord.