Repository navigation
Releases: EndstoneMC/spark
Releases · EndstoneMC/spark
Release list
v0.6.3
Added
- Add optional MSPT-triggered automatic execution profiling after sustained high
tick times, with configurable threshold, trigger duration, profile duration,
sampling interval, cooldown, thread grouping, and thread selection. Automatic
profiles are always bounded to at most 600 seconds.
Changed
- Define profiler priority as manual > automatic > background. Manual profiles
preempt automatic profiles, automatic profiles temporarily replace background
profiling, and background profiling resumes after foreground stop, timeout,
cancellation, or finalization/export failure. Explicitly cancelling the
background profiler still pauses it until Spark is reloaded.
Fixed
- Preserve the remaining bounded-profile deadline when stop or cancel fails, and
request an immediate stop if the deadline cannot be restored safely. - Allow automatic profiling to retry after a startup failure without consuming
the post-session cooldown, and preserve the live-viewer transaction boundary
when profiler replacement cannot complete safely.
Full Changelog: v0.6.2...v0.6.3
v0.6.2
Added
- Notify the server console and players when the crash-recovery journal degrades,
including when a session may no longer be recoverable.
Changed
- Reduce CPU overhead of persistent Linux allocation-rate metrics while preserving
allocation profiler and unload behavior. Single-writer counters reduced observer
cost by 7.3-13.3 ns/op across seven single-thread benchmark workloads, with
unchanged reported counters and one-thread hook coverage.
Fixed
- Exclude resolved Linux allocation-hook callback frames from execution profiles.
- Keep recovery journal size accounting accurate when retained segments disappear
or cannot be statted, and stop journal growth after persistent metadata snapshot
failure or stalled pruning while profiling continues. - Prevent repeated startup replay of the same journal generation after cleanup
fails, and retain the first degradation cause and notices across session finalization. - Preserve world gauge counts while the level is unavailable and retry failed tile
reconciliation after a five-second backoff.
Full Changelog: v0.6.1...v0.6.2
v0.6.1
Added
- Support Linux allocation profiling with standard shared jemalloc and mimalloc
loaded at startup throughLD_PRELOAD.
Fixed
- Recognize startup-preloaded Linux allocators after Endstone clears the runtime
LD_PRELOADenvironment variable. - Show the resolved Linux allocator provider in allocation profile backend metadata.
Full Changelog: v0.6.0...v0.6.1
v0.6.0
Added
- Add Java-compatible health reports and a live health dashboard with background
uploads, rolling TPS, tick-duration, CPU, world, and ping history, and trusted
viewer clients. - Add an optional
sparkexpansion for Endstone PlaceholderAPI with TPS,
tick-duration, and process/system CPU placeholders. Spark continues to work
normally when PAPI is not installed or active. - Add one-hour process-memory history and 1m/5m/15m allocation-rate metrics on
Windows and Linux, withhealth show --memoryand--networkdetail views. - Attribute sampled Python plugin call chains on CPython 3.12+; CPython 3.11
remains native-only. - Export active Bedrock behavior-pack metadata and a reviewed safe subset of
server.properties, with opt-in support for additional safe keys. - Preserve the initiating player's UUID across profiler, health, activity,
upload, and recovery metadata. - Allow
/spark profiler open --comment <text>to override the comment shown in
the live viewer. - Report the number of ticks included by
--only-ticks-over, and distinguish
samples discarded from an unfinished terminal tick from other incomplete data. - Improve Windows native symbol attribution for templates, lambdas, local
classes, and other ambiguous compiler-generated names. - Support Java-compatible Spark configuration environment variables.
Changed
- Align command parsing, help visibility, profiler action precedence, umbrella
permissions, and zero-interval defaults more closely with Java spark. - Align live-viewer updates and profiling windows to stable global cadences, and
use monotonic deadlines for timed profiles, uptime, ping, and network sampling
so wall-clock changes or server stalls do not skew them. - Distribute Linux builds as a single
endstone_spark.so. A full server restart
is recommended when upgrading from the old helper-based runtime or after an
update that changes Spark's persistent native allocation support. - BREAKING: Linux allocation profiling now supports allocator providers that
are part of the server's startup dependency graph. Custom allocator providers
loaded later at runtime are not supported. - Improve Windows x64 allocation profiling so plugin unload does not leave native
callbacks targeting unloaded Spark code. - Reduce sampler/allocation aggregation overhead, profile-export allocations, and
peak memory use during crash-recovery replay. - Make Linux native symbol attribution more conservative by rejecting ambiguous
evidence instead of presenting uncertain labels as resolved functions.
Fixed
- Improve allocation-profiler cleanup and failure handling on Windows and Linux,
including Windows stack unwinding andLastErrorpreservation, Linux caller
attribution, and bounded stop/finalize paths so slow cleanup cannot freeze the
server indefinitely. - Keep persistent Linux allocation support safe across plugin unload and late
callbacks. Incompatible or exhausted process-lifetime state is reported and
requires a full server restart. - Make recovery-journal flushing, rotation, and module-definition ordering more
durable, and retain recovery data when shutdown cleanup is incomplete. - Preserve independent complete call trees for different threads that share the
same display name. - Export Python filename leaves and code identifiers without server-owner
directory paths while retaining available line information. - Harden live-viewer and health-dashboard connection lifecycle, reconnects,
trusted-client validation, malformed input handling, and bounded send/receive
queues. - Keep viewer and health notification failures off the server tick path and ensure
failed connections are cleaned up. - Include players correctly in aggregate world entity gauges and include world
metadata in the initial health report. - Match upstream spark protocol details for profile data version, tick-threshold
units, and tick-duration placeholder windows and percentile ranks. - Prevent Spark's native allocation-hook internals from being charged to Spark in
execution-profile Plugins View. - Prevent the viewer's process-memory denominator from decoding as zero while
preserving native RSS/committed-memory semantics. - Skip unsafe device-metadata ping polling for unauthenticated headless BDS
clients. - Keep a completed allocation profile stable until serialization finishes before
persistent allocation-rate counting resumes. - Prevent Windows execution sampling failures from leaving the target BDS thread
suspended. - Preserve recovery journals when export shutdown cleanup does not complete, and
report cleanup warnings only when cleanup actually remains incomplete.
Full Changelog: v0.5.3...v0.6.0
v0.5.3
Added
- Attribute sampled native frames to their owning Endstone C++ plugin on Windows
and Linux using a profile-start module snapshot. - Resolve hidden Linux plugin functions from ELF/DWARF data during profile export.
Full Changelog: v0.5.2...v0.5.3
v0.5.2
Added
- Accept
/spark profiler upload(and/spark sampler upload) as a
compatibility alias for/spark profiler stop, matching upstream spark.
--uploadand--stoplegacy flag forms are also accepted.
Fixed
- Harden crash recovery against corrupted, truncated, or rotation-damaged
journals. A recovery journal missing its early segments (head-truncated by
segment rotation), referencing module IDs whoseModuleDefrecords were
deleted, or carrying aCLEAN_ENDmarker no longer causes plugin enable to
fail. Rolling journals now preserve session metadata in a crash-consistent
snapshot sidecar before pruning old segments, so rotated profiles remain
recoverable. Allocation profiles record an explicit module-0 sentinel so
samples referencing the catch-all module resolve correctly during replay.
Clean-end sessions skip replay entirely; incomplete or malformed journals are
safely discarded (or quarantined on unexpected exceptions) and the server
continues starting up normally. Previously this could abort the plugin on
Windows (invalid vector subscript) or crash the entire BDS process on Linux
via an exception crossing the plugin DSO boundary.
Full Changelog: v0.5.1...v0.5.2
v0.5.1
Added
- Support continuously updating Live Viewer sessions for
--allocand
--alloc-live-onlyprofiles.
Full Changelog: v0.5.0...v0.5.1
v0.5.0
Added
- Automatically recover profiling data after a BDS crash or forced process
termination. During execution and allocation profiling sessions (including the
background profiler), samples are written to a crash-safe recovery journal under
plugins/spark/profiles/recovery/. On the next startup, an unclean supported
session is replayed into a.sparkprofilefile underplugins/spark/profiles/.
The recovery directory is cleaned after a successful save. Both Windows and
Linux are supported. - Detect main-thread stalls with an independent watchdog thread that monitors a
monotonic heartbeat updated every tick. When the server thread stops ticking for
more than 5 seconds, stall begin/end events are recorded in the recovery journal
so that recovered profiles retain stall evidence. The watchdog never calls
Endstone APIs and never stops the profiler. - Add persistent Spark configuration (
config.tomlin the plugin data directory)
with configurableviewerUrl,bytebinUrl,bytesocksHost, background
profiler settings, and response broadcast toggle. Invalid config is reported and
preserved byte-for-byte while that startup uses safe defaults. Trusted viewer
keys are stored separately intrusted-viewers.json. - Add automatic background profiler that starts on plugin enable and runs
indefinitely at a configurable interval (default 10ms). A foreground
profiler (/spark profiler start) pauses the background session; stopping
the foreground profiler via/spark profiler stoprestarts the background.
Timeout and cancel do not restart the background profiler. - Add
/spark pingcommand with rolling 15-minute player ping RTT statistics
(min/median/p95/max),--player <name>lookup, and profile metadata
integration viaPlatformStatistics.Ping. - Add per-interface network throughput monitoring (RX/TX bytes and packets per
second) with 15-minute rolling averages, displayed in/spark healthand
exported in profile metadata viaSystemStatistics.NetInterface. - Add
/spark health --uploadto generate and upload a sparkHealthData
report (platform metadata, system resources, 15-minute time-window history,
and plugin list) to the spark viewer. - Add
/spark activitycommand with persisted activity log (profiler uploads,
saved profiles, and health report uploads), JSON storage with atomic writes
and corruption-safe loading, 60-day URL expiry, and--pagepagination. - Add
--not-combinedand--combine-allprofiler flags to control how sampled
threads appear in the viewer: separate roots per thread, a single merged root,
or the default pool-based grouping. - Preserve exact sampled native PCs and their independently validated function
roots in forward-compatible profile fields for offline normalization metrics. - Resolve Linux vtable labels for shared implementations by parsing Itanium RTTI
inheritance edges, attributing virtual functions to their common ancestor class
instead of leaving the RVA unresolved. - Label unresolved Linux main-executable functions that reference uniquely-owned
BDS debug trace strings ("N _functionName"patterns) with low-confidence
str?hints. - Label unresolved Linux main-executable functions that reference multiple unique
weak string hints with tentativestr?accumulated labels. - Propagate lambda type names from
std::function::__funcvtable thunks to their
single large unresolved call target on Linux with low-confidencecall?hints. - Label unresolved Linux main-executable functions with characteristic code
patterns (Knuth multiplicative hash, 64-bit hash multiplier, atomic
lock cmpxchg/lock xadd, binary search range-halving) with low-confidence
type?behavior hints. - Add
/spark profiler opencommand to open a live, auto-updating spark
viewer during an active execution profile. Connects to the spark WebSocket
relay with RSA2048-signed messages and uploads sampler data every 10 seconds.
The viewer closes automatically when the profiler stops, is cancelled, or
times out. - Add
/spark profiler trust-viewer --id <client id>command to approve a
pending live viewer client. Untrusted clients receive an UNTRUSTED connect
response; trusted clients receive ACCEPTED and gain access to the live
sampler data stream. Trusted public keys are persisted intrusted-viewers.json. - Add command aliases matching upstream spark:
samplerforprofiler,cpu
fortps,healthreportandhtforhealth,activitylogandlogfor
activity,tickmonitoringfortickmonitor. - Add per-command permissions (
spark.profiler,spark.tps,spark.ping,
spark.health,spark.activity,spark.tickmonitor) in addition to the
umbrellaendstone.command.sparkpermission. - Populate per-window entity and chunk counts in profile metadata from rolling
gauge samples, matching upstream spark'sWindowStatisticsfields. - Group world chunk statistics into regions using 8-neighbor connected-component
analysis, matching upstream spark'sWorldStatisticsProvider.groupIntoRegions()
algorithm. - Include safe
server.propertiesvalues (max-players, view-distance,
tick-distance, compression settings, etc.) in profile metadata via
SamplerMetadata.server_configurationsusing a strict whitelist that excludes
level-seed, passcodes, and any credential-like fields. - Pretty-print
activity.jsonwith 2-space indentation for readability.
Fixed
- Keep live viewer updates ordered across interrupted WebSocket sends and report unexpected transport closures.
- Remove expired call-tree nodes and thread roots from continuous background
profiles instead of retaining dead topology beyond the one-hour history window. - Serialize live snapshots with profiler lifecycle transitions so stop, cancel,
timeout, and shutdown cannot resume an ended sampling session. - Contain exceptions at every production worker entry and recover export/viewer
state when dispatch or background processing fails. - Preserve Linux signal-handler synchronization when bounded capture teardown
cannot prove that an active handler has completed. - Include the strict allowlisted server configuration map in health reports and
validate configured HTTP/WebSocket endpoint syntax before applying it. - Send a bounded WebSocket close frame during ordinary local viewer shutdown.
- Bound continuous background profile history to the upstream one-hour retention
window while preserving complete finite foreground profiles. - Keep live viewer metadata capture on the server thread and move relay setup,
compression, health uploads, and profile uploads to owned background workers. - Complete WebSocket receive-worker joins after remote disconnects and make live
viewer open/close/reconnect safe during stop, shutdown, and network failure. - Isolate recovery journal segments by session, validate segment continuity, retain
journals after profile save failures, and synchronize writer teardown with the
stall watchdog. - Validate activity page numbers without narrowing or overflowing pagination
arithmetic, including values aboveINT_MAX. - Preserve invalid user-owned
config.tomlfiles and validate endpoint, enum,
interval, type, and integer bounds before applying configuration. - Validate foreground profiler options before pausing the background profiler and
keep stop, cancel, timeout, and export transitions consistent. - Use non-blocking allocation lifecycle shards under contention and mark exported
allocation data incomplete whenever callback accounting is dropped. - Isolate delayed Linux sampling signals by capture generation and wait for queued
deliveries before restoring the process signal handler. - Serialize process-wide Windows DbgHelp ownership so live symbolization cannot
clean up an active capture session. - Rebaseline network interfaces on counter reset or reappearance, use 64-bit
Windows counters, and calculate rates from measured elapsed time. - Enforce formatting and project-owned clang-tidy checks in CI, and publish GitHub
releases only after both platform artifacts pass their full test suites. - Match upstream pool grouping labels for threads whose names do not identify a
numbered worker pool. - Save
.sparkprofilefiles as raw uncompressed protobuf instead of gzip-compressed
data. The spark viewer's file upload expects uncompressed protobuf; gzip-wrapped
files could not be opened when manually uploaded to spark.lucko.me. Bytebin uploads
remain gzip-compressed as before. - Reconstruct per-window tick statistics in crash-recovered profiles. Previously,
recovered profiles lackedWindowStatistics.ticksdata, causing the spark viewer's
"Time per tick" label to display total elapsed time instead of per-tick time. - Skip crash recovery for sessions that ended cleanly. Normal profiler stop,
plugin unload, and BDS shutdown all write a CLEAN_END marker to the recovery
journal; on the next startup, these journals are cleaned up without generating
a duplicate.sparkprofile. Only journals without CLEAN_END (crash or forced
termination) trigger recovery. - Refuse recovery for allocation live-only (
--alloc-live-only) sessions.
The recovery journal records allocation requests but not free/realloc events,
so retained-allocation lifecycle state cannot be reconstructed. The recovery
player returns an error instead of producing a semantically incorrect profile. - Stop the recovery journal writer when the profiler is shut down in allocation
mode, preventing the writer thread from outliving the plugin during unload. - Prevent BDS crash when running
/spark healthafter ~5 minutes of uptime.
The network interface display loop usedstd::vformatwith 8std::string
arguments, which threw a non-standard exception on Linux/libc++ once network
monitoring data became available. Replaced with direct string concatenation. - Catch any uncaught C++ exception in command...
v0.4.1
Added
- Append evidence-tagged native name guesses to unresolved main-executable frames
on Windows and Linux while preserving the RVA. Function
extents come from PE exception data or ELF unwind metadata, with class/slot and
semantic hints recovered from validated RTTI, vtables, thunks, and decoded
string references.
Changed
- Store profiles created by
--save-to-fileor upload-failure recovery under
plugins/spark/profiles/instead of the plugin data root. - Make Linux vtable guesses deterministic and reject conflicting class owners;
decode string references only at real x86-64 instruction boundaries and only
for functions present in the exported profile.
Full Changelog: v0.4.0...v0.4.1
v0.4.0
Added
- Maintain a fixed-capacity 15-minute history of completed ticks and one-second
process/system CPU observations even when no profiler is running. - Calculate independent 5-second, 10-second, 1-minute, 5-minute, and 15-minute TPS
windows plus query-time MSPT distributions and rolling CPU usage. - Populate profile metadata and per-second Viewer windows from the shared history,
including exact time bounds, CPU, TPS, MSPT median/max, and low-cost player counts. - Report real rolling TPS, MSPT distributions, and process/system CPU from
/spark tps, with the available history duration shown during warm-up.
Changed
- Share one cross-platform process CPU normalization rule and keep allocation,
sorting, and percentile work out of the per-tick statistics path. - Omit unavailable per-second entity and chunk fields instead of copying a final
world snapshot or serializing zero as though it were an observation. - Make
/spark healthuse the shared performance snapshot and consistently report
available process RSS/virtual memory, threads, physical memory, swap/page-file,
disk, uptime, players, CPU, and OS resources on Windows and Linux. - Track resource-field availability explicitly and omit failed system/profile
queries rather than presenting synthetic zero values.
Fixed
- Stop copying one TPS/CPU average across every rolling field or labeling MSPT
means and maxima as median, minimum, and p95 values in profile metadata. - Preserve the suspended thread's top instruction address on Windows when
StackWalk64cannot unwind a caller, instead of discarding the whole sample. - Report reserved/committed process virtual address space on Windows instead of
incorrectly labeling private commit charge as virtual memory. - Retry Windows hook removal within the existing bounded shutdown interval when
a concurrently starting or exiting thread temporarily rejects context capture.
Full Changelog: v0.3.2...v0.4.0