COWMODSКаталог модов

PerformanceAnalyzer

Monitor your server in real-time, find the source of lag spikes in seconds, and keep your players happy — all from a single, lightweight plugin.

Автор: boondocksulfur9243обновлён 22 окт. 2026 г.
УправлениеОптимизацияУтилиты

Описание

Why PerformanceAnalyzer?

Most monitoring plugins tell you that your server is lagging. PerformanceAnalyzer tells you why.

When a TPS drop or MSPT spike occurs, the plugin automatically captures a full snapshot of your server state — loaded chunks, entity counts, player activity, suspect plugins — so you can diagnose the problem instantly instead of guessing.

⚡ New in v3.0.0

  • AntiCheat is now its own plugin. PerformanceAnalyzer is now a focused, pure performance monitor. The XRay/Movement detection lives on in the standalone BSAntiCheat plugin — install it alongside PerformanceAnalyzer and the GUI will link the two together automatically.
  • Per-second drop detection — performance drops are now sampled every second (decoupled from the database logging interval), so short-lived spikes are no longer missed.
  • REST API is live — JSON endpoints for Grafana/Prometheus dashboards.
  • Developer API — other plugins can read live TPS/MSPT/heap/entity data.

Key Features

Real-Time Performance Monitoring

  • TPS, MSPT & Heap tracking with historical data and ASCII sparklines
  • Spark Integration for highly accurate TPS (10s/1m/5m), MSPT (avg/p95/max), and CPU data
  • ProtocolLib Integration for packet analysis and flood detection
  • Database Logging (SQLite or MySQL) with async batch writes via HikariCP
  • Fallback File Logging — if the database goes down, metrics are written to a file instead of being lost

Automatic Lag Diagnosis

  • Performance Drop Detection — triggers automatically when TPS drops or MSPT spikes, sampled every second
  • Full Server Snapshots — captures chunks, entities, memory, and player locations at the moment of the drop
  • Accurate Low/High Tracking — reports the actual worst TPS/MSPT seen during the drop window
  • Lag Source Analysis — identifies the players and plugins most likely responsible
  • Problematic Chunk Detection — finds chunks overloaded with tile entities or redstone
  • Chunk Thrashing Detection — spots chunks that load/unload too frequently
  • Throttled & quiet — the expensive deep analysis is rate-limited and stays out of the console unless debug mode is on, so the diagnostics never make the lag worse

Interactive GUI System

  • Performance Dashboard — live TPS, MSPT, heap with auto-refresh
  • Lag Analysis Page — top 5 active players and suspect plugins with risk scores
  • Performance Drops Page — browse up to 21 recent drops, click for detailed reports
  • Config GUI — toggle settings without touching files
  • Companion detection — shows BSAntiCheat status when the AntiCheat plugin is installed
  • Multi-page navigation, color-coded items, intuitive design

Silent Mode / Streamer Mode

  • /perfsilent — mute all alert notifications in chat
  • /perfsilent performance — mute just the performance alert category
  • /perfsilent list — view your current preferences
  • /perfsilent reset — receive all alerts again
  • Persistent across server restarts
  • Perfect for streamers, builders, or admins who don't need constant notifications

Discord Webhook Integration

  • Automatic notifications for TPS drops, high MSPT, heap warnings, and packet floods
  • Color-coded embeds per alert type
  • Configurable: choose exactly which events get reported
  • Async, rate-limited HTTP requests — zero performance impact
  • SSRF-protected: only valid Discord webhook URLs are accepted

Auto Entity Cleaner

  • Priority-based removal: items > projectiles > monsters > animals
  • Protects named entities, tamed animals, villagers, and boss mobs
  • Per-world and per-chunk limits
  • Dry-run mode for safe testing before enabling

Additional Tools

  • World Statistics (/worldstats) — entities, chunks, density, trend analysis per world
  • Entity Analysis (/entitystats) — breakdown by category, hotspot detection
  • Chunk Statistics (/chunkstats) — load tracking, problematic chunks, thrashing
  • REST API — JSON endpoints for Grafana/Prometheus dashboards with API key auth
  • Developer API — PerformanceAPI for other plugins to read live metrics
  • Auto Database Cleanup — configurable retention (default: 30 days)
  • Multi-Language — English & German, easily extensible

Commands

CommandDescriptionPermission
/perfstatusLive TPS, MSPT, heap dataperformance.status
/perfhistory [min]Historical MSPT sparkline & statsperformance.history
/perfguiOpen the interactive GUIperformance.gui
/perfreloadReload plugin configurationperformance.admin
/perfsilent [type]Toggle alert notifications (streamer mode)performance.admin
/perfdrops [#]View/analyze performance dropsperformance.admin
/worldstats [world]Per-world statistics (alias /ws)performance.admin
/entitystats [world]Entity analysis & hotspots (alias /es)performance.admin
/chunkstats [sub]Chunk load tracking & problems (alias /cs)performance.admin

Permissions

PermissionDescriptionDefault
performance.statusUse /perfstatusEveryone
performance.historyUse /perfhistoryEveryone
performance.guiUse /perfguiEveryone
performance.adminAdmin commands & alert notificationsOP
performance.silentUse silent mode to mute alertsOP

Configuration Highlights

Database (SQLite or MySQL)
database:
  type: sqlite                    # or 'mysql'
  sqlite_file: "plugins/PerformanceAnalyzer/perf.db"
  retention_days: 30              # Auto-cleanup (0 = disabled)
  fallback_file_logging: true     # Log to file if the DB is unavailable
  fallback_log_file: "plugins/PerformanceAnalyzer/fallback.log"
  pool:
    max_pool_size: 10
    minimum_idle: 2
Performance Thresholds
thresholds:
  mspt: 50.0                      # MSPT warning (ms)
  heap_usage_percent: 80.0         # Heap warning (%)
  tps_drop: 19.0                   # TPS drop warning
  packet_flood_per_tick: 1000.0    # Packet flood detection
Lag Analysis Thresholds

All thresholds are adjustable for your hardware:

lag_analysis:
  player_tracking: true
  plugin_analysis: true
  chunk_analysis_timeout_ms: 5000

  # Chunk thresholds (Standard | Powerful | Weak)
  chunk_tile_entities_threshold: 10    # 10 | 20-30 | 5-8
  chunk_redstone_threshold: 30         # 30 | 50-100 | 15-20
  chunk_entity_warning: 50             # 50 | 80-100 | 30-40
  chunk_entity_critical: 100           # 100 | 150-200 | 60-80

  # World thresholds
  world_entity_warning: 5000
  world_entity_critical: 10000
Discord Webhook
discord:
  enabled: false
  webhook_url: ""
  alert_types:
    high_mspt: true
    tps_drop: true
    high_heap: true
    packet_flood: true
REST API
api:
  enabled: false
  port: 8080
  key: "changeme"    # IMPORTANT: Set a secure key! The server won't start otherwise.

Endpoints: /api/health, /api/metrics, /api/worlds, /api/trends Authentication: Authorization: Bearer <key>

Auto Entity Cleaner
entity_cleaner:
  enabled: false
  interval_seconds: 300
  world_limit: 5000
  chunk_limit: 100
  dry_run: true                  # Test mode (logs only, no removal)
  protect_villagers: true
  protect_item_frames: true
  blacklist: ["ENDER_DRAGON", "WITHER", "WARDEN"]
  world_whitelist: []            # Worlds that are never cleaned

Developer API

Other plugins can read live performance data directly:

PerformanceAPI api = (PerformanceAPI) Bukkit.getPluginManager().getPlugin("PerformanceAnalyzer");
double tps = api.getCurrentTPS();
double mspt = api.getCurrentMSPT();
double heap = api.getHeapUsagePercent();
int entities = api.getTotalEntityCount();

Language Support

English and German are included. Language files live in plugins/PerformanceAnalyzer/lang/ and are fully customizable.

Adding a new language:

  1. Copy en.yml to your language code (e.g. fr.yml)
  2. Translate all messages
  3. Set language: fr in config.yml
  4. Run /perfreload

Looking for AntiCheat?

As of v3.0.0, the XRay and Movement detection has moved into its own dedicated plugin: BSAntiCheat. Install both side by side — PerformanceAnalyzer handles performance and lag diagnosis, BSAntiCheat handles cheat detection, and the GUI links them together.


Optional Dependencies

PluginBenefit
sparkAccurate TPS (10s/1m/5m), MSPT (avg/p95/max), CPU monitoring
ProtocolLibPacket analysis & flood detection
BSAntiCheatCompanion AntiCheat plugin (XRay & movement detection)

All integrations are optional — the plugin works fully standalone.


Requirements

  • Java 21
  • Paper 1.21.4 – 1.21.x
  • Thread-safe, async operations, minimal performance overhead

Config Auto-Migration

When updating, your existing config is never overwritten. New settings are automatically added with sensible defaults. Just replace the JAR and restart.


Special Thanks

To ELITEK3V for testing.

Галерея

Xray Test (Discord Hook)MSPT Test (Discord Hook)Anticheat Test IngameGUI

Последние версии

Все версии →
release

PerformanceAnalyzer 3.3.0

3.3.0
22 окт. 2026 г.56Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur, spigot
Скачать
Что нового
## [3.3.0] - 2026-10-21 ### Fixed - `/perfreload` can enable the REST API again after a refused start (empty key, port taken); it restarts on bind/port/key changes. - Spike evaluation runs async instead of inside the lagging tick. - Discord webhooks have connect/read timeouts and honour Retry-After on HTTP 429. - ZGC/Shenandoah concurrent cycles no longer count as GC pause time. - Shutdown no longer overwrites hand edits of config.yml; config saves are atomic and coalesced. - Single-category mutes from `/perfsilent` survive logout. - Entity sweeps are rate-limited, and stale sweep results are no longer reported as incident causes. - Missing optional database drivers fall back instead of disabling the plugin; SQLite uses one connection; MySQL index creation works. - Language reloads no longer show raw keys in alerts; config merging no longer re-adds obsolete v2 alert types. - Language-file texts whose placeholders changed between versions fall back to the bundled text instead of showing `%s`/`%d` (named in one log warning). ### Changed - `/chunkstats` overview, `/entitystats` and `/worldstats` are disabled on Folia (cross-region access); `/perfincidents` and the REST API remain the location signal. - German texts use proper umlauts. ### Removed - Aliases `incidents`, `ps`, `silent` and `calibrate`; use `/perfincidents`, `/perfsilent`, `/perfcalibrate` or `pi`/`pc`.
release

PerformanceAnalyzer 3.2.1

3.2.1
15 авг. 2026 г.173Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur, spigot
Скачать
Что нового
## [3.2.1] - 2026-08-15 Things this version got wrong, all found by running it on a real server and reading back eight days of its own output rather than by reading the code. ### Changed - **A WARNING now means the tick rate suffered, and it has to hold.** Two rules decided it before, and both fired on servers that were fine. The tail bound `p95 >= 50` warned on production at p95 51.3 ms while the rate sat at 19.9 TPS — one tick in twenty a hair past the deadline, nothing anyone could feel. And nothing required the trouble to last: a five-second login burst and a fourteen-second redstone burst each opened an incident. A WARNING is now `TPS < 19` or a 35 ms average, and it has to hold for `alerts.warning_sustain_seconds` (default 30) before an incident opens. CRITICAL and above skip the wait — below 17 TPS or at a 50 ms average the server is already failing and waiting would be absurd. The incident is dated from when the trouble started and carries the peaks measured during the wait, so this filter cannot quietly shorten what it lets through. ### Fixed - **Seventeen WARNING incidents for "somebody is playing".** A baseline deviation alone opened an incident, and on a server that idles at 3.5 ms the first player who logs in is a fourfold jump — `normal * 2 + 10` is crossed by ordinary play. Measured on production: 17 WARNINGs in eight days, every one at 14–19.5 ms average tick with TPS never below 19.8, each coinciding with one or two players online. A deviation now needs the absolute load to be meaningful as well (avg ≥ 25 ms, half the deadline, or p95 ≥ 35 ms) before it reaches WARNING; below that it is a NOTICE, which is recorded but opens no incident. Genuine degradation still escalates — a server drifting to 26 ms average warns as before. The gate first carried a tail arm as well (p95 ≥ 35 ms), which let the same noise straight back in: on rattenkolonie, idling at 0.2 ms, a player logging in produced avg 11.1 ms with a p95 between 35 and 50 ms — five seconds of chunk loading — and opened a WARNING. A tail that genuinely hurts is already a WARNING through the absolute `p95 >= 50` rule, so the arm bought no detection and only cost quiet. The gate is the average alone. - **The cause showed up late, and then under a name that said nothing.** `hotChunks()` only ever exposes the last *completed* 10-second activity window, so the report an incident opens with could be built from data up to ten seconds old — and a lag source that had just started was not in it at all. The window is now closed on the spot when an incident opens; rates divide by the window's real elapsed time, so a short one under-reports slightly rather than inventing load. And the finding is titled by what is actually going on — "Hochaktives Redstone/Pistons in Vorbau bei 192, 48" instead of "Hochaktiver Chunk" — because the incident list and the Discord alert show the title alone, while the plugin knew the answer all along and kept it in the detail line. - **A login was not attributed.** Teleports were, but the case that produced the complaint was a player logging in — same physics, chunks around the logout point being read or generated, and it still reported "no clear cause". Both now share one finding (`PLAYER_ARRIVAL`). Unlike the world-save and command markers it is *not* pinned above the measured findings: an arrival overlapping an incident is a correlation, not proof, so it takes part in the normal sort and surfaces only when nothing measured outranks it. - **Every incident was reported 30 seconds longer than it lasted.** An incident resolved at the end of the grace period, and that timestamp became its end time, so the fixed `RESOLVE_GRACE_MS` was billed to every duration. A 12-second blip on production was announced as "Dauer: 42s". Incidents now end when the server recovered; the grace period remains what it always was — confirmation that the recovery held. - **The database dropped measurements in three places.** `drain` polled an entry and *then* checked whether the batch was full, discarding exactly one measurement on every capped flush. A failed write lost its whole batch: the entries had already left the queue, and the failure path only rescued what was still queued, so the first batch after an outage went nowhere — it is now written to the fallback file, together with whatever else piled up. And `shutdown()` flushed a single batch of at most 1000 entries before closing the pool, which is the one moment a backlog is likely; it now drains completely. If no fallback file is configured the loss is at least logged instead of silent. - **`ChunkTracker` kept every heavy chunk it ever saw.** One entry per chunk above the tile/entity warning thresholds, never evicted, on a map with no upper bound — so it grew for as long as the server ran, and pregeneration or exploration grew it fast. Capped at 4096 like the equivalent map in `ActivityCounters`; chunks skipped once full are counted rather than ignored. - **`/perfreload` did not apply the settings the config GUI offers.** Packet analysis, listener timings and the REST API were wired up at enable time and never touched again, so toggling them and reloading did nothing at all while the GUI said "takes effect after restart or /perfreload". All three now start and stop on reload. `ListenerTimings` is always constructed for this reason — its consumers take the reference once, so a null could never have become non-null again — and `isActive()` carries the on/off state. - **Calibration called `Bukkit.getOnlinePlayers()` off the tick thread**, in a class whose contract says it runs async by design. It now reads the monitor's main-thread sample. - **WorldEdit operations and teleports ended in "no clear cause"** while the reason sat two lines above in the server log. Neither is visible to any of the instrumented sources: the work happens inside the command or the teleport, not in a listener, a chunk counter or a GC pause. Both now set a cause marker like the world save does — verified against `//paste` (TPS 15.5), `/mv delete` + `/mv create` ("Prepared spawn area in 4083 ms") and `/home` jumps producing 778 ms ticks. Command matching is driven by `attribution.expensive_commands` and deliberately short, because anything on that list can collect the blame for a stall it merely overlapped; teleports under 256 blocks within one world are ignored, their destination being loaded already. - **Calibration could tighten a threshold an admin had deliberately raised.** The floor protected only the shipped default, so it did nothing for any install that had ever changed a value. Found on production, where `packet_flood_per_tick` sat at 3000 after 671 real alerts between 1002 and 5104 packets/tick had proven 1000 too tight — and calibration proposed pulling it straight back to 1000, which would have reinstated every one of those alerts. The measurement behind the proposal was 49 packets/tick from a one-minute window on an empty server; the packet counter itself is sound and resets every tick, in v2 as in v3. Every proposal now floors at `max(shipped default, value in effect today)`, so calibration can widen a limit and never narrow one. `startup_grace_seconds` follows the same rule: one fast boot is a single observation, and shortening the grace is what brought the phantom boot incidents back — production's deliberate 120 s is no longer halved by a 34 s boot. - **A floored value was justified with a formula that produced a different number.** "p99 x 2" printed under a proposal of 1000 when p99 x 2 was 98. When a floor decides the value, the reason now says so and names what the sample actually suggested. - **`/perfcalibrate` refused to run because worlds were idle.** Unloaded worlds vetoed the entire calibration once more than a third of them had no loaded chunks — and on a normal server that is the normal state: nobody is in the nether, so the nether has no chunks. Two worlds with one of them quiet was already enough to block. The veto also discarded `spike_tick_ms`, `packet_flood_per_tick` and `startup_grace_seconds`, none of which have anything to do with worlds. The guard existed to stop a thin spatial sample from proposing tight world thresholds, but that job is already done twice over: every proposal is floored and so can only ever relax (`idleSampleCannotTighten…` covers exactly the 6-of-9-worlds case), and the sampler skips empty worlds instead of recording a zero for them, so they never drag the percentiles down. Unloaded worlds are now a warning naming how many worlds *were* measured, and calibration proceeds.
release

PerformanceAnalyzer 3.2.0

3.2.0
9 авг. 2026 г.26Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2folia, paper, purpur, spigot
Скачать
Что нового
## [3.2.0] - 2026-08-09 Adds threshold calibration, so a fresh install no longer has to guess the values that decide when it complains. ### Added - **`/perfcalibrate`** derives threshold values from what the server actually did, shows the proposal and writes nothing until confirmed with `/perfcalibrate apply`. `/perfcalibrate revert` restores the config from before the last run. Only thresholds (plus the measured `startup_grace_seconds`) are written; findings outside that scope — a port already in use, a missing soft dependency — are reported as notes and left alone. - **Guard rails against calibrating a bad moment.** The command refuses to run while the server is not OK, while an incident is open, on a sampling window shorter than 30 minutes, when no player was online for the whole window, and when more than a third of the worlds have no chunks loaded. A thinner but real sample only warns. Thresholds do not adjust themselves afterwards: a threshold that follows its own measurements upward lets a slowly degrading server raise its own bar until nothing is ever reported. - **Calibration may only relax a threshold, never tighten it** below the shipped default. Its purpose is to stop false alarms, which means raising limits; a tighter limit buys no better detection, only noise — the adaptive half of detection is the learned tick baseline, not these backstops. Found by testing: a 34-minute window on an idle server proposed `spike_tick_ms` 100 → 52 and `world_entity_warning` 5000 → 500, values that would have alerted on ordinary play. The old representativeness check could not catch it either, because on a server that never had players the median player count is 0 and `0 < 0` is false. - **New metric series `players_online` and `chunks_loaded`** in the 60-second logging path, sampled from the tick thread. Without them nothing could tell a quiet server from a healthy one after the fact. - **`ProtocolLibHook` now records the observed packets-per-tick peak.** The stored packet series are cumulative counters whose per-interval deltas average every spike away. - **Stalls outside the tick loop are detected and attributed.** Work that blocks the main thread without completing a tick — loading or generating a world, blocking I/O in a plugin, the host itself freezing — fires no `ServerTickEndEvent`, so tick times stayed healthy while TPS collapsed and the incident ended in "no clear cause". Observed on production: `/mv create` froze the server for 4 s and the worst recorded tick was 12 ms. The gap between two tick ends now exposes exactly that time, needs no new instrumentation, and by construction cannot double-count a long tick: a 7-second `save-all` is already its own duration and leaves nothing unaccounted. - **`alerts.dampen_world_save`** (default `true`) stops the nightly backup from paging anyone. `save-all` blocks the tick loop for as long as the worlds need — 7 s on a 25 GB install — and is correctly measured as an EMERGENCY-grade stall, but it is scheduled and harmless. The incident is still recorded in full and visible in `/perfincidents`; only the alert is withheld, so the measurement stays honest. Set to `false` while investigating slow disks. ### Fixed - **Config migration never added missing keys.** Two independent causes: the whole add-missing-key block sat behind an early `config_version` check, and presence was tested with `contains()`, which counts the jar-embedded defaults and therefore reported every key as present. Both are gone; the migration is idempotent and runs on every start, matching the obsolete-key cleanup. Observed on a production install carrying `config_version: 7` with no `api`, `alerts` or `gui` section at all. - **Migration entries added** for `performance.startup_grace_seconds`, `thresholds.spike_tick_ms`, `database.fallback_file_logging`, `database.fallback_log_file` and the four v3.1.0 `discord.alert_types` subkeys, none of which had one. - **`ChunkTracker` ignored its configuration.** `chunk_tile_entities_threshold` and `chunk_entity_warning` were hardcoded at 50 and 30, so `/chunkstats problems` answered from constants and the config keys did nothing. - **A busy API port now says so.** `BindException` is reported with the likely cause (squaremap, dynmap and BlueMap all default to 8080) instead of a bare "address already in use".
release

PerformanceAnalyzer 3.1.0

3.1.0
7 авг. 2026 г.18Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2folia, paper, purpur, spigot
Скачать
Что нового
## [3.1.0] - 2026-08-07 Complete rewrite. PerformanceAnalyzer is now a pure performance plugin with an honest measurement core, an incident-based root-cause engine and a real REST API. The AntiCheat module moved into its own plugin, **BS-AntiCheat**. ### Changed - **MSPT now means real tick work time (BREAKING for dashboards).** v2.x measured the *tick interval* — the time between scheduler runs, which is pinned to ~50 ms on any healthy server. That was the root cause of the permanent false alerts. v3 measures the actual per-tick work duration via Paper's `ServerTickEndEvent`: a healthy server now shows single-digit MSPT, and 50 ms is the deadline at which 20 TPS can no longer be held. Exported MSPT values will drop dramatically after upgrading — the new values are the correct ones. - **Statistics over fixed time windows** (10 s / 60 s) with p50/p95/p99/max percentiles instead of fixed tick counts; a single spike is caught, not averaged away. TPS is counted exactly on Paper and estimated from the worst region on Folia. - **Fixed alert thresholds replaced by a documented severity model** (`analysis/SeverityModel.java`): OK/NOTICE/WARNING/CRITICAL/EMERGENCY plus a transparent 0–100 score (45 pts sustained load vs. the 50 ms deadline, 30 pts p95 tail latency, 25 pts GC pressure). `thresholds.mspt`, `thresholds.tps_drop` and `thresholds.heap_usage` are gone; only `thresholds.spike_tick_ms` and `thresholds.packet_flood_per_tick` remain. - **One-shot "performance drops" became incidents** with an open → escalate → resolve lifecycle, duration tracking and a resolved notification. `/perfincidents` (aliases `pi`, `perfdrops`, `incidents`) replaces `/perfdrops`. - **Root-cause attribution is ordered and confidence-labeled**: findings are marked MEASURED or HEURISTIC and checked world save/backup → GC → plugin listener timings → hot chunks → chunk generation/churn → entity hotspots, so a GC-caused spike is never blamed on redstone. Tick stalls within 12 s of a `WorldSaveEvent` (autosave, backup `save-all` — the nightly false alarm source) are pinned to the save as the top finding. - **Plugin analysis measures real cost**: `timing/ListenerTimings.java` wraps other plugins' event handlers and accumulates actual milliseconds per plugin, replacing the `listeners*2 + tasks*3` registration-count risk score that reliably blamed the wrong plugin. - **Chunk analysis counts activity, not existence** (`ActivityCounters`): per-chunk redstone firings, piston movements, hopper item moves, spawns and chunk loads/gens per second in rolling 10 s windows replace the static redstone/block estimator (idle contraptions cost nothing; a 10 Hz clock costs real time). - **Detection decoupled from database logging**: the evaluation loop runs every second regardless of DB state (v2 detection ran once per minute as a side effect of DB logging and stopped when the DB was down). - `/perfhistory` now queries asynchronously and clamps its range; its permission (`performance.history`) and `performance.gui` default to op. - Alerts are severity-based with escalation and a resolved message, dispatched thread-safely to players with `performance.alerts`; Discord embeds are colored by severity and use new `discord.alert_types` keys: `incident_opened`, `incident_escalated`, `incident_resolved`, `packet_flood`, `performance`. - Config migrated automatically to `config_version: 7` — obsolete keys are deleted, new keys added with safe defaults. ### Added - **Adaptive baseline** (`analysis/Baseline.java`): EWMA over ~10 minutes of healthy samples (120-sample warmup); the severity model alerts on deviation from the server's *own* normal in addition to the hard 50 ms deadline. The baseline is only fed while the server is healthy, so an ongoing incident cannot poison it. - **GC monitoring** (`metrics/GcSampler.java`): GC pause-time deltas, old-gen occupancy *after* the last collection (the only honest memory-pressure signal — 90 % live heap right before a young GC is normal) and metaspace. - **Single-tick spike trigger**: one tick above `thresholds.spike_tick_ms` (default 100 ms) starts incident analysis immediately, rate-limited. - **Real REST API** (`api/MetricsAPI.java`): `GET /api/health` (no auth), `/api/metrics`, `/api/incidents`, `/api/worlds` and Grafana-ready `/api/metrics/prometheus` (text exposition v0.0.4). Constant-time `Authorization: Bearer` check, `api.bind` defaults to `127.0.0.1`, and the server refuses to start while `api.key` is empty or `"changeme"`. - **Folia support**: `folia-supported: true`; all tasks go through the region-aware schedulers (`platform/Scheduling.java`). Tick samples come from every region thread; TPS is a worst-region estimate on Folia. - Fallback file logging when the database is unavailable (`database.fallback_file_logging`, `database.fallback_log_file`). - JUnit 5 unit tests for the pure logic (Baseline, SeverityModel, TickStats) wired into the Maven build via Surefire. - Anonymous [bStats](https://bstats.org/plugin/bukkit/PerformanceAnalyzer/32115) usage metrics (shaded & relocated; opt-out via `plugins/bStats/config.yml`). ### Fixed - **The analyzer no longer freezes the server during lag**: the v2 analyzer took chunk snapshots and iterated worlds on the main thread mid-incident, blocking for seconds. The v3 engine attributes causes exclusively from already-collected data — no chunk snapshots, no main-thread blocking, no Bukkit access from HTTP or monitor threads. - **Fixes from live verification on Paper 26.1.2, Paper 1.21.4 and Folia 26.2 (2026-08-05 … 2026-08-07):** - Plugin crashed on enable when ProtocolLib was absent (`NoClassDefFoundError` — the presence check now runs before the first hook-class reference). - Folia fires no `ServerTickEndEvent`; the interval fallback recorded the ~50 ms tick *period* as work time and produced a permanent false WARNING. Healthy fallback samples now use a nominal value and `/perfstatus` labels the estimate mode. - Scheduled restarts raised a bogus CRITICAL/EMERGENCY on every shutdown (counted TPS collapses while worlds save) — evaluation is now suspended once `Bukkit.isStopping()` and during the new startup grace period (`performance.startup_grace_seconds`, default 60 s; metrics still run). - The baseline learned during NOTICE, letting sustained load ratchet the "normal" value upward until active incidents self-resolved; it now learns only while the severity is OK. - Entity-hotspot findings multiplied chunk coordinates by 16 twice (reported "-256, 0" instead of "-16, 0"). - TPS windows are clamped to the sampler uptime (the first minute after boot divided by a window that had not filled yet and reported bogus low 60 s TPS). - Incident open/escalate/resolve messages are always written to the console (WARNING-level incidents were chat-only and invisible on empty servers). - The shutdown config save runs only when the plugin itself changed the config — the unconditional save wiped `config.yml` edits admins made while the server was running. - Obsolete-key cleanup is now version-independent and idempotent: configs stamped with a matching `config_version` by older builds kept dead sections (the `anticheat:` block survived a 6→7 migration), and the removal list used a wrong key name (`thresholds.heap_usage` vs. `heap_usage_percent`). - `/perfhistory` results are additionally written to the server log for console/RCON senders (async replies never reach the RCON response). - Severity assessment reasons are localized (were hardcoded German). - GUI refresh-task leak fixed; all GUIs now share a single registered listener (`GuiManager`) instead of per-GUI listeners and throwaway instances. GUI texts fully localized (en/de). - Permanent false "high MSPT" alerts on idle servers (see the measurement change above). - CI artifact upload glob matched nothing (`PerformanceAnalyzer-*.jar` vs. actual `performance-analyzer-*.jar`). ### Removed - **AntiCheat module** — now the separate plugin **BS-AntiCheat**. Gone with it: `/acwhitelist`, `/xrayalerts`, `/xrayores`, `/movealerts`, the `performance.anticheat.*` permissions and the `anticheat.*` config section (deleted by migration). - **Auto Entity Cleaner** (`entity_cleaner.*` config section). - Static redstone estimator, `PerformanceDropAnalyzer` and the plugin "risk score" (replaced as described above). - Fixed `thresholds.mspt` / `thresholds.tps_drop` / `thresholds.heap_usage` and the `messages.*` config section. - `discord.alert_types.anticheat` (deleted by migration); the old `high_mspt`/`tps_drop`/`high_heap` Discord alert keys are no longer consulted (replaced by the incident-based keys). - `docs/grafana-dashboard.json` — use the Prometheus endpoint with your own Grafana dashboards instead.
release

PerformanceAnalyzer 3.0.0

3.0.0
17 июн. 2026 г.61Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [3.0.0] - 2026-06-17 ### Changed - **BREAKING: AntiCheat split into a separate plugin (BSAntiCheat).** PerformanceAnalyzer is now a focused performance-monitoring & lag-diagnosis plugin. All XRay and Movement detection — including the related commands, GUI, config, permissions and language strings — has been removed from this plugin and lives on in the standalone **BSAntiCheat** plugin. The performance GUI detects BSAntiCheat and links to it when installed. - **Performance drop detection now runs every second** on its own scheduled task, decoupled from the database logging interval. Previously `checkForDrop()` was only called once per `log_interval_seconds` (60s by default), so short-lived TPS/MSPT spikes were missed. ### Added - **REST API is now active.** The `MetricsAPI` server is started on enable (was previously implemented but never wired up). Endpoints: `/api/health`, `/api/metrics`, `/api/worlds`, `/api/trends`, with API key authentication. Disabled by default. - **Auto Entity Cleaner is now active.** `AutoEntityCleaner` is hooked into plugin enable/disable. Disabled by default with `dry_run: true`. - **Developer API**: `PerformanceAnalyzer` now implements the public `PerformanceAPI` interface — `getCurrentTPS()`, `getCurrentMSPT()`, `getHeapUsagePercent()`, `getTotalEntityCount()`, `getEntityCount(World)`, `getVersion()`. - **Accurate low/high drop tracking**: recorded performance drops now report the actual worst TPS / highest MSPT observed during the drop window instead of the value at the moment of recording. - **Documented config keys** that were previously only added silently via migration: `database.fallback_file_logging`, `database.fallback_log_file`, `gui.auto_refresh`, and the full `api.*` and `entity_cleaner.*` sections. ### Fixed - **Duplicate logging task / task leak on `/perfreload`**: `TickSampler.setDatabase()` now cancels the previously scheduled logging task before scheduling a new one. Previously every reload added another logging task, causing duplicate database writes and duplicate alert/drop checks. - **Verbose console output during lag events**: the per-world / per-chunk diagnostic logging in the performance drop analyzer is now gated behind debug mode, so it no longer floods the console (and adds load) while the server is already struggling. - **Throttled deep analysis**: the expensive server-state/chunk-snapshot analysis now runs at most once per 30 seconds during sustained drops, preventing it from piling up chunk snapshots on the main thread. ### Removed - AntiCheat classes: `XRayDetector`, `MovementChecker`, `ViolationTracker`, `XRayAlertManager`, `MovementAlertManager`, `AntiCheatGUI`, `LuckPermsHook` - AntiCheat commands: `/xrayalerts`, `/movealerts`, `/xrayores`, `/acwhitelist` - AntiCheat permissions: `performance.anticheat.manage`, `performance.anticheat.bypass` - All `anticheat.*` config keys, `performance.anticheat_enabled`, `discord.alert_types.anticheat`, and all AntiCheat/XRay/Movement language strings (EN & DE) - `XRAY` and `MOVEMENT` silent-mode categories — only `ALL` and `PERFORMANCE` remain; `/perfsilent` now accepts `all`, `performance`, `list`, `reset` - Dead code: unused `ConfigMigrator` class (a duplicate migration system with a phantom "prometheus" feature), legacy synchronous `analyzeChunk()`, `DatabaseManager.deleteAntiCheatLogs()`, `isPlayerSuspicious()` from the public API, and empty Javadoc stubs in `Constants` ### Config - `config_version` bumped to **6** — auto-migration adds the new fallback-logging keys to existing configs (existing settings are never overwritten)
release

PerformanceAnalyzer 2.3.4

2.3.4
7 мая 2026 г.61Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [2.3.4] - 2026-05-07 ### Fixed - **Redstone False Positives in Performance Drop Analyzer**: Removed 26 non-performance-impacting blocks (buttons, pressure plates, lecterns, daylight detectors, tripwire, levers, targets) from `isRedstoneComponent()`. These blocks appear in naturally generated structures (villages, temples) and caused massive false positives through sampling extrapolation - **Redstone Sampling Extrapolation**: Added minimum threshold (≥3 components found) before extrapolating redstone counts. Previously, a single naturally-generated button was multiplied by ×64, producing false "problematic redstone" reports - **Wrong Coordinates in Problematic Chunk Reports**: Chunk coordinates are now displayed alongside block coordinates (`[Chunk X,Z | Blocks ~X,Z]`) for easier in-game navigation - **NullPointerException in PerformanceDropAnalyzer**: `worldInfo.get("name").equals(...)` replaced with `Objects.equals()` to prevent NPE when world name is null - **Swallowed Exceptions in Chunk Analysis**: ChunkSnapshot and synchronous chunk analysis errors are now logged at `FINE` level instead of being silently ignored - **Unbounded Database Queue (OOM Risk)**: `DatabaseManager.logAsync()` now enforces a maximum queue size of 10,000 entries. Prevents `OutOfMemoryError` when the database is unavailable for extended periods - **Excessive Block Checks in MovementChecker**: `isNearLiquid()` reduced from 27 block checks (3×3×3 cube) to 7 checks (current block + 6 adjacent faces), reducing CPU load per `PlayerMoveEvent` by ~74% - **Duplicated Alert Cooldown Constants**: `AlertManager` and `MovementAlertManager` now use the centralized `Constants.ALERT_COOLDOWN_MS` instead of defining their own identical values - **Silent Config Parsing Failures**: Invalid alert categories in `AlertPreferenceManager` now log a warning instead of being silently skipped - **Thread-Safety in WorldStatsManager**: Trend history lists now use `Collections.synchronizedList()` to prevent concurrent modification issues ### Added - `Constants.DB_MAX_QUEUE_SIZE` — centralized maximum queue size for database log entries
release

PerfomanceAnalyzer 2.3.3

2.3.3
12 апр. 2026 г.58Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [2.3.3] - 2026-04-12 ### Fixed - **Sneaking/Swimming/Climbing False Positives**: These movement types are now skipped entirely by the speed checker. - **Silk Touch Ores Not Recognized as Self-Placed**: The player-placed block check now applies to ALL worlds, not just restricted worlds. Previously, silk-touching an ore block, placing it in your base, and breaking it would count toward XRay detection - **Y-Level Pattern Analysis Removed**: Completely removed the Y-Level analysis feature. Mining at optimal Y-levels is normal gameplay (anyone can Google "best Y level for diamonds") and produced false positives ### Removed - `analyzeYLevelPattern()`, `trackYLevel()`, `getOptimalYRange()` methods from XRayDetector - `playerOreYLevels` tracking map from XRayDetector - `xray_ylevel_high/medium/low` config entries and validation - `XRAY_YLEVEL` violation type
release

PerfomanceAnalyzer 2.3.2

2.3.2
11 апр. 2026 г.24Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [2.3.2] - 2026-04-11 ### Fixed - **Race Condition in AlertManager**: Cooldown check now uses atomic `compareAndSet()` instead of separate `get()`/`set()`, preventing duplicate alerts under concurrent access - **Race Condition in TickSampler**: Tick sampling now uses `idx.getAndUpdate()` for atomic index read-modify-write, preventing data corruption in the nanos array - **Connection Pool Leak in DatabaseManager**: `shutdown()` now uses try-finally to ensure `HikariDataSource.close()` is always called, even if `flushBatchSafe()` throws an exception - **NullPointerException in GUIs**: Added null-checks for `getItemMeta()` in all GUI classes (PerformanceGUI, AntiCheatGUI, LagAnalysisGUI, PerformanceDropsGUI) — follows the safe pattern already used in ConfigGUI - **Thread-Safety in ViolationTracker**: `resetViolations(UUID, ViolationType)` now uses `computeIfPresent()` to prevent race condition where the PlayerViolations object could be removed between `get()` and `counts.remove()` - **MovementChecker Violation Reset Too Aggressive**: Consecutive violation counters now only reset when speed is significantly below threshold (70%), preventing a single valid move from immediately washing out violations - **XRay Y-Level Thresholds Too Aggressive**: Default thresholds raised from 75%/65%/55% to 85%/75%/65% to reduce false positives from legitimate caving - **UpdateChecker Missing Field Validation**: Now checks for `version_number` field existence in Modrinth API response before accessing it - **Inconsistent Activity Weights**: `PlayerActivityTracker.getTotalActivity()` now uses centralized `Constants.ACTIVITY_WEIGHT_*` values instead of hardcoded numbers ### Added - **Configurable XRay Y-Level Thresholds** (`config.yml`) - `anticheat.xray_ylevel_high` (default: 0.85) — percentage for maximum suspicion - `anticheat.xray_ylevel_medium` (default: 0.75) — percentage for moderate suspicion - `anticheat.xray_ylevel_low` (default: 0.65) — percentage for low suspicion - Config validation ensures values are 0.0-1.0 and properly ordered (low < medium < high) - Auto-migration adds defaults for existing configs ### Changed - `XRayDetector.analyzeYLevelPattern()` reads thresholds from config instead of using hardcoded values
release

PerfomanceAnalyzer 2.3.1

2.3.1
10 апр. 2026 г.20Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [2.3.1] - 2026-04-10 ### Added - **Silent Mode / Streamer Mode** (`/perfsilent`) - Toggle all alerts on/off: `/perfsilent` - Toggle per category: `/perfsilent xray`, `/perfsilent movement`, `/perfsilent performance` - Reset all preferences at once: `/perfsilent reset` - View current status: `/perfsilent list` - Persistent across server restarts (saved in `config.yml` under `alerts.silent_players`) - Aliases: `/ps`, `/silent` - Full tab-completion support - Bilingual: German & English language strings - **AntiCheat DB Cleanup Commands** - `/movealerts clear <player> --db` — deletes movement violation entries from the database - `/xrayalerts clear <player> --db` — deletes XRay detection entries from the database - Without `--db`: only clears in-memory alerts (as before), now shows a hint about the `--db` option - Tab-completion for `--db` flag - **Teleport Immunity for Movement Checks** - New `PlayerTeleportEvent` listener prevents false positives from legitimate teleports (`/tp`, `/home`, ender pearls, etc.) - 1-second grace period after any teleport where movement checks are skipped - `lastLocations` reset to teleport destination to prevent follow-up false positives - Consecutive violation counters reset on teleport ### Fixed - **Version Inconsistency**: pom.xml, plugin.yml, and main class now use the same version dynamically via `getDescription().getVersion()` instead of hardcoded strings - **Race Condition in AsyncConfigSaver**: `pendingSave` changed from `volatile boolean` to `AtomicBoolean` with proper atomic check-and-set operations, preventing lost config saves under concurrent requests - **NullPointerException in PerformanceDropAnalyzer**: Added null-checks for `Player.getWorld()` and `Player.getLocation()` during world unload scenarios - **Memory Leak in AlertManager**: Added periodic cleanup task (every 5 minutes) for stale `lastAlertTimes` entries that were never removed - **AntiCheat False Positives**: Improved lag compensation from linear to square-root scaling (200ms ping = +10%, 500ms = +20%, 1000ms = +30%), reducing false positives for high-ping players without allowing extreme speeds ### Changed - All three alert systems (`AlertManager`, `XRayAlertManager`, `MovementAlertManager`) now respect per-player alert preferences before sending chat notifications - Config auto-migration adds `alerts.silent_players` for new installations
release

PerfomanceAnalyzer 2.3.0

2.3.0
22 февр. 2026 г.76Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11paper, purpur, spigot
Скачать
Что нового
## [2.3.0] - 2026-02-22 ### Added - **Lag Compensation for Movement Checks** - Player ping considered in speed calculations (+10% per 100ms above 100ms) - Reduces false-positives for high-ping players - **Knockback/Damage Immunity Detection** - 2-second immunity window after explosions and entity attacks - Prevents false-positives from legitimate knockback - **Y-Level Analysis for XRay Detection** - Tracks mining height for all ores - Optimal Y-level ranges based on Minecraft 1.21 - New detection method: `XRAY_YLEVEL` - Detects suspicious pattern: 75%+ mining at optimal height - **Async Chunk Analysis** - Uses `ChunkSnapshot` for thread-safe analysis - Parallel processing with `CompletableFuture` - **90% less main-thread load** during performance drop analysis - Timeout protection maintained - **Auto-Cleanup for Database** - Automatic retention policy (default: 30 days) - Runs daily (1h after startup, then every 24h) - Configurable: `database.retention_days` (set to 0 to disable) - **GUI Auto-Refresh System** - Performance data updates every 3 seconds - Only active for open GUIs (no overhead) - Automatic cleanup on GUI close - Configurable: `gui.auto_refresh` - **Trend Analysis for World Stats** - Historical tracking (up to 288 snapshots = 24h @ 5min intervals) - Trend direction: `INCREASING`, `DECREASING`, `STABLE` - Change rate calculation (entities/hour) - Methods: `recordSnapshot()`, `analyzeTrend()`, `analyzeTrendsForAllWorlds()` - **REST API for External Monitoring** - 4 JSON endpoints: `/api/health`, `/api/metrics`, `/api/worlds`, `/api/trends` - API key authentication (`Authorization: Bearer`) - Perfect for Grafana/Prometheus dashboards - Config: `api.enabled`, `api.port`, `api.key` - **Automatic Entity Cleaner** - Smart entity management to prevent lag - Priority-based removal (items → projectiles → monsters → animals) - Protection for named entities, tamed animals, villagers - Boss mob blacklist (Ender Dragon, Wither, Warden) - Per-world and per-chunk limits - Dry-run mode for safe testing - Config: `entity_cleaner.*` ### Changed - **Movement Checker** (`MovementChecker.java`) - Added environmental checks (slime blocks, bubble columns) - 2x vertical speed allowance near slime blocks/bubble columns - Enhanced cleanup method to include new tracking maps - **XRay Detector** (`XRayDetector.java`) - Added Y-level tracking for pattern analysis - New method: `analyzeYLevelPattern()` - New method: `getOptimalYRange()` with Minecraft 1.21 spawn data - Enhanced `checkSuspiciousPattern()` with Y-level analysis - **Performance Drop Analyzer** (`PerformanceDropAnalyzer.java`) - Replaced synchronous chunk analysis with async processing - Added `analyzeChunkAsync()` method using ChunkSnapshot - Legacy `analyzeChunk()` kept as fallback - Improved error handling for async operations - **Database Manager** (`DatabaseManager.java`) - Added auto-cleanup task for retention management - Enhanced shutdown procedure to cancel cleanup task - **World Stats Manager** (`WorldStatsManager.java`) - Added trend tracking infrastructure - New records: `WorldStatsSnapshot`, `TrendAnalysis` - Multiple helper methods for trend calculation - **Performance GUI** (`PerformanceGUI.java`) - Added auto-refresh system with task management - New `InventoryCloseEvent` handler for cleanup - New method: `shutdown()` for proper cleanup - **Plugin Config** (`PluginConfig.java`) - Added 10 new config methods for features - Auto-migration for all new config entries ### Fixed - Memory leaks from incomplete cleanup (movement checker, XRay detector) - False-positives in movement detection from knockback - False-positives in movement detection from environmental effects - Main-thread bottleneck in chunk analysis ### Performance - **90% reduction** in main-thread load during performance drop analysis - Reduced false-positive alerts (less CPU overhead) - More efficient memory usage with automatic cleanup ### Security - REST API authentication with API keys - SSRF protection in Discord webhook validation (from v2.2.0) - SQL injection prevention (from v2.2.0)