Skip to content

Releases: EndstoneMC/spark

v0.6.3

Choose a tag to compare

@github-actions github-actions released this 04 Oct 17:49

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

Choose a tag to compare

@github-actions github-actions released this 01 Oct 11:54

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

Choose a tag to compare

@github-actions github-actions released this 27 Sep 16:39

Added

  • Support Linux allocation profiling with standard shared jemalloc and mimalloc
    loaded at startup through LD_PRELOAD.

Fixed

  • Recognize startup-preloaded Linux allocators after Endstone clears the runtime
    LD_PRELOAD environment variable.
  • Show the resolved Linux allocator provider in allocation profile backend metadata.

Full Changelog: v0.6.0...v0.6.1

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 17 Sep 18:43

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 spark expansion 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, with health show --memory and --network detail 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 and LastError preservation, 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

Choose a tag to compare

@github-actions github-actions released this 14 Aug 16:24

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

Choose a tag to compare

@github-actions github-actions released this 11 Aug 06:22

Added

  • Accept /spark profiler upload (and /spark sampler upload) as a
    compatibility alias for /spark profiler stop, matching upstream spark.
    --upload and --stop legacy 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 whose ModuleDef records were
    deleted, or carrying a CLEAN_END marker 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

Choose a tag to compare

@github-actions github-actions released this 09 Aug 17:54

Added

  • Support continuously updating Live Viewer sessions for --alloc and
    --alloc-live-only profiles.

Full Changelog: v0.5.0...v0.5.1

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 09 Aug 08:03

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 .sparkprofile file under plugins/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.toml in the plugin data directory)
    with configurable viewerUrl, 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 in trusted-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 stop restarts the background.
    Timeout and cancel do not restart the background profiler.
  • Add /spark ping command with rolling 15-minute player ping RTT statistics
    (min/median/p95/max), --player <name> lookup, and profile metadata
    integration via PlatformStatistics.Ping.
  • Add per-interface network throughput monitoring (RX/TX bytes and packets per
    second) with 15-minute rolling averages, displayed in /spark health and
    exported in profile metadata via SystemStatistics.NetInterface.
  • Add /spark health --upload to generate and upload a spark HealthData
    report (platform metadata, system resources, 15-minute time-window history,
    and plugin list) to the spark viewer.
  • Add /spark activity command 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 --page pagination.
  • Add --not-combined and --combine-all profiler 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 tentative str? accumulated labels.
  • Propagate lambda type names from std::function::__func vtable thunks to their
    single large unresolved call target on Linux with low-confidence call? 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 open command 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 in trusted-viewers.json.
  • Add command aliases matching upstream spark: sampler for profiler, cpu
    for tps, healthreport and ht for health, activitylog and log for
    activity, tickmonitoring for tickmonitor.
  • Add per-command permissions (spark.profiler, spark.tps, spark.ping,
    spark.health, spark.activity, spark.tickmonitor) in addition to the
    umbrella endstone.command.spark permission.
  • Populate per-window entity and chunk counts in profile metadata from rolling
    gauge samples, matching upstream spark's WindowStatistics fields.
  • Group world chunk statistics into regions using 8-neighbor connected-component
    analysis, matching upstream spark's WorldStatisticsProvider.groupIntoRegions()
    algorithm.
  • Include safe server.properties values (max-players, view-distance,
    tick-distance, compression settings, etc.) in profile metadata via
    SamplerMetadata.server_configurations using a strict whitelist that excludes
    level-seed, passcodes, and any credential-like fields.
  • Pretty-print activity.json with 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 above INT_MAX.
  • Preserve invalid user-owned config.toml files 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 .sparkprofile files 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 lacked WindowStatistics.ticks data, 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 health after ~5 minutes of uptime.
    The network interface display loop used std::vformat with 8 std::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...
Read more

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 02 Aug 02:41

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-file or 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

Choose a tag to compare

@github-actions github-actions released this 31 Jul 01:58

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 health use 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
    StackWalk64 cannot 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