5.5 KiB
JevPlayer Performance Guide & Profiling Protocol
This document details the performance constraints, memory budgets, zero-GC strategies, and profiling protocols used to ensure JevPlayer runs stably for extended 1+ hour survival sessions without causing frame drops or memory growth.
1. Per-Tick Latency Budgets
Minecraft runs at 20 ticks per second (1 tick = 50.0 ms). Rendering at 60+ FPS requires the client thread to complete all per-frame and per-tick tasks within a fraction of this window.
| Pipeline Phase | Target Budget (Average) | Hard Threshold (Worst Case) | Execution Thread |
|---|---|---|---|
| World Sensor Perception | < 0.15 \text{ ms} |
< 0.80 \text{ ms} |
Client Main Thread |
| Legal Action Masking | < 0.05 \text{ ms} |
< 0.20 \text{ ms} |
Client Main Thread |
| Reflex Evaluation | < 0.03 \text{ ms} |
< 0.15 \text{ ms} |
Client Main Thread |
| Watchdog Verification | < 0.02 \text{ ms} |
< 0.10 \text{ ms} |
Client Main Thread |
| Actuator Dispatch (Baritone) | < 0.05 \text{ ms} |
< 0.75 \text{ ms} |
Client Main Thread |
| Total Client Tick Overhead | $< 0.30 \text{ ms}$ | $< 2.00 \text{ ms}$ | Client Main Thread |
| Decision Query (Jev HTTP/2) | 70 \text{ -- } 250 \text{ ms} |
< 500 \text{ ms} |
Background Daemon Thread |
| Decision Query (Mock Heuristic) | < 0.50 \text{ ms} |
< 2.00 \text{ ms} |
Background Daemon Thread |
2. Allocation Avoidance & Zero-GC Strategies
Frequent garbage collection cycles on the client JVM cause perceptible micro-stuttering. JevPlayer incorporates strict allocation-minimization practices:
Reusable Buffers for Prompt Formatting
- Instead of creating short-lived
Stringinstances on every tick,StateSnapshotformats its state prompt into pre-allocatedStringBuilderinstances. - Primitive fields (
float health,int food,int level,long timeOfDay,int coalCount, etc.) are directly formatted without boxed object wrappers (Integer,Float).
Bounded Collections & Ring Buffers
ActionHistoryEntryinstances are stored in a fixed-size ring buffer (capacity 10). When new history arrives, the oldest entry is overwritten in-place without expanding or reallocating arrays.- Legal actions use
EnumSet<ActionType>, backed by a single 64-bit primitive long bitmask. Adding, removing, or checking legal actions requires zero memory allocations.
HUD Rendering Throttling
- Minecraft invokes HUD rendering callbacks on every frame (60 to 144+ times per second).
- String assembly and metric calculations are throttled to update at most once every
hudRefreshRateMs(default: 200 ms). Between updates, the HUD simply renders the cached text components.
Non-Blocking HTTP Client
- All remote I/O is performed using Java's built-in
java.net.http.HttpClientconfigured with:- HTTP/2 multiplexing.
- Connection reuse and TLS session caching.
- A fixed daemon thread pool (
Executors.newSingleThreadExecutor(...)).
3. Profiling with Spark
Spark is the standard profiler for modern Fabric environments.
Profiling the Client Thread
To profile JevPlayer's client-side tick footprint in-game:
/spark profile --thread Client --timeout 60
When the 60-second profile concludes, inspect the call tree under:
net.minecraft.client.MinecraftClient.tick()- Look for
com.typesafe.jevplayerpackages. - Ensure total sampling percentage for
com.typesafe.jevplayerremains< 0.5\%of client tick time.
Profiling Memory Allocation Rate
To identify any memory allocations generated by JevPlayer:
/spark heap --alloc
Filter classes for com.typesafe.jevplayer. Memory allocation rate should be < 5 \text{ KB/sec} during steady-state autonomous play.
4. Profiling with Java Flight Recorder (JFR)
Java Flight Recorder is built directly into OpenJDK and provides low-overhead JVM diagnostics.
Launching with JFR Enabled
Add the following JVM argument in the Gradle runClient task or Minecraft launcher:
-XX:+UnlockDiagnosticVMOptions \
-XX:+DebugNonSafepoints \
-XX:StartFlightRecording=dumponexit=true,filename=jevplayer-profile.jfr,settings=profile
Key Metrics to Validate in JDK Mission Control
- Garbage Collection Pauses:
- Verify that young-gen GC pause times remain
< 5 \text{ ms}. - Confirm that old-gen full GCs do not occur during a 1-hour session.
- Verify that young-gen GC pause times remain
- Thread Allocations:
- Filter the "Allocation in new TLAB" and "Allocation outside TLAB" views by
com.typesafe.jevplayer. - Confirm that no tick-level allocation loops exist.
- Filter the "Allocation in new TLAB" and "Allocation outside TLAB" views by
- Socket I/O:
- Confirm that all
java.net.httpnetwork activity is confined to thejev-decision-workerthread.
- Confirm that all
5. One-Hour Soak Test Validation Protocol
Before recording or deploying an episode:
- Launch singleplayer survival in mock mode:
{ "mockMode": true, "confidenceThreshold": 0.65, "fairMode": true } - Enable HUD overlay (
F8) and let the bot play undisturbed for 60 minutes (72,000 game ticks). - Verify the following exit criteria:
- No Out-Of-Memory (OOM): Heap usage remains flat with normal sawtooth GC reclamation.
- No Deadlocks: Worker threads terminate cleanly when leaving world.
- Watchdog Stability: If the bot gets stuck in terrain, watchdog recovers within 45 seconds without operator intervention.
- Kill Switch: Pressing
F9immediately releases all Baritone controls and stops autonomous ticking.