111 lines
5.5 KiB
Markdown
111 lines
5.5 KiB
Markdown
# 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 `String` instances on every tick, `StateSnapshot` formats its state prompt into pre-allocated `StringBuilder` instances.
|
|
- 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
|
|
- `ActionHistoryEntry` instances 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.HttpClient` configured with:
|
|
- HTTP/2 multiplexing.
|
|
- Connection reuse and TLS session caching.
|
|
- A fixed daemon thread pool (`Executors.newSingleThreadExecutor(...)`).
|
|
|
|
---
|
|
|
|
## 3. Profiling with Spark
|
|
|
|
[Spark](https://spark.lucko.me/) is the standard profiler for modern Fabric environments.
|
|
|
|
### Profiling the Client Thread
|
|
To profile JevPlayer's client-side tick footprint in-game:
|
|
```text
|
|
/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.jevplayer` packages.
|
|
- Ensure total sampling percentage for `com.typesafe.jevplayer` remains $< 0.5\%$ of client tick time.
|
|
|
|
### Profiling Memory Allocation Rate
|
|
To identify any memory allocations generated by JevPlayer:
|
|
```text
|
|
/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:
|
|
```bash
|
|
-XX:+UnlockDiagnosticVMOptions \
|
|
-XX:+DebugNonSafepoints \
|
|
-XX:StartFlightRecording=dumponexit=true,filename=jevplayer-profile.jfr,settings=profile
|
|
```
|
|
|
|
### Key Metrics to Validate in JDK Mission Control
|
|
1. **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.
|
|
2. **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.
|
|
3. **Socket I/O:**
|
|
- Confirm that all `java.net.http` network activity is confined to the `jev-decision-worker` thread.
|
|
|
|
---
|
|
|
|
## 5. One-Hour Soak Test Validation Protocol
|
|
|
|
Before recording or deploying an episode:
|
|
1. Launch singleplayer survival in mock mode:
|
|
```json
|
|
{
|
|
"mockMode": true,
|
|
"confidenceThreshold": 0.65,
|
|
"fairMode": true
|
|
}
|
|
```
|
|
2. Enable HUD overlay (`F8`) and let the bot play undisturbed for 60 minutes (72,000 game ticks).
|
|
3. 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 `F9` immediately releases all Baritone controls and stops autonomous ticking.
|