hprof-analyzer 0.2.0

Fast, low-memory Java HPROF heap-dump analyzer with Eclipse MAT-parity reports (System Overview, Leak Suspects, Top Consumers).
[workspace]
members = [".", "crates/hprof-wasm"]
resolver = "2"

[package]
name = "hprof-analyzer"
version = "0.2.0"
edition = "2024"
rust-version = "1.85"
description = "Fast, low-memory Java HPROF heap-dump analyzer with Eclipse MAT-parity reports (System Overview, Leak Suspects, Top Consumers)."
license = "MIT"
repository = "https://github.com/parttimenerd/hprof-analyzer"
readme = "README.md"
authors = ["Johannes Bechberger"]
keywords = ["hprof", "heap-dump", "java", "memory", "oom"]
categories = ["command-line-utilities", "development-tools::profiling"]
exclude = [
    "tests/fixtures/*.hprof",
    "tests/fixtures/*.hprof.gz",
    "tests/fixtures/*.hprof.zip",
    "tests/fixtures/*.json",
    "tests/fixtures/*.md",
    "tests/fixtures/*.index",
    "tests/fixtures/*.threads",
    "web/dist/*",
    "web/node_modules/*",
    "dist/*",
    ".git-worktrees/*",
    "docs/*",
    "*.png",
]

[[bin]]
name = "hprof-analyzer"
path = "src/main.rs"

[lib]
name = "hprof_analyzer"
path = "src/lib.rs"
crate-type = ["rlib"]

[features]
# Opt-in Eclipse MAT differential-oracle test harness (tests/mat_oracle.rs).
# No extra deps: the harness shells out to scripts/mat-oracle.sh. Compiled only
# under `--features mat-oracle`; its tests are #[ignore]d and gated on MAT_HOME.
mat-oracle = []
# Native-only dependencies (CLI, server, REPL, HTML scraping, compression).
# The WASM crate depends on hprof-analyzer with default-features = false to
# avoid pulling in these non-WASM-compatible crates.
default = ["native"]
native = ["dep:reedline", "dep:crossterm", "dep:tiny_http", "dep:clap", "dep:clap_complete", "dep:scraper", "dep:zstd", "dep:zip", "dep:tar", "dep:ureq", "dep:self-replace"]

[dependencies]
base64 = "0.22"
tiny_http = { version = "0.12", optional = true }
clap = { version = "4", features = ["derive"], optional = true }
clap_complete = { version = "4", optional = true }
flate2 = "1"
# default-features = false drops legacy/arrays/zdict_builder C extensions; only encode/decode needed
zstd = { version = "0.13", default-features = false, optional = true }
# Used for reading Eclipse MAT plugin jars (DEFLATE-compressed entries) to
# detect the installed MAT parser ID. deflate feature only; no bzip2/zstd needed.
zip = { version = "2", default-features = false, features = ["deflate"], optional = true }
tar = { version = "0.4", optional = true }
# HTTP download for `update` subcommand; TLS via native OS roots (rustls + webpki).
ureq = { version = "3", default-features = false, features = ["rustls"], optional = true }
# Atomic self-replacement of the running binary (handles Windows file locking).
self-replace = { version = "1", optional = true }
scraper = { version = "0.27", optional = true }
# pinned to =1.2.1: schemars 1.x had breaking API changes; bump carefully
schemars = "=1.2.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# only deserializing TOML; "display" feature (TOML serialization) is not needed
toml = { version = "0.8", default-features = false, features = ["parse"] }
chumsky = "0.13.0"
ariadne = "0.6.0"
logos = "0.16.1"
reedline = { version = "0.43", optional = true }
crossterm = { version = "0.28", optional = true }
# full regex (not regex-lite) for MAT's quoted-FROM Java-Pattern class matching
regex = "1"

[target.'cfg(unix)'.dependencies]
libc = "0.2"

[dev-dependencies]
cargo-husky = { version = "1.5.0", features = ["precommit-hook", "run-cargo-fmt", "user-hooks"] }
jsonschema = "0.47.0"
proptest = "1"
tar = "0.4"
tempfile = "3"

[build-dependencies]
flate2 = "1"

# Clippy is run in CI (see .github/workflows/ci.yml). Most lints are enforced;
# the allows below are deliberate patterns in the memory-critical hot paths,
# not tech debt:
#   needless_range_loop  - index drives several parallel per-object arrays at
#                          once (semi/ancestor/label, class_idx, ...); the
#                          iterator rewrite obscures the shared index and can
#                          perturb the bit-exact dominator/pass2 hot loops.
#   ptr_arg              - &mut Vec params are grown via push()/clear() inside
#                          the fill routines; a slice cannot resize.
#   collapsible_if       - nested `if let` guards read more clearly unmerged.
#   too_many_arguments   - the retained-set builder threads many CSR arrays by
#                          reference to avoid extra allocations.
[lints.clippy]
needless_range_loop = "allow"
ptr_arg = "allow"
collapsible_if = "allow"
too_many_arguments = "allow"
redundant_closure_call = "allow"

[profile.release]
lto = true
codegen-units = 1
panic = "abort"

# Fast iteration profile: no LTO, many codegen units, full opt level.
# Use with: cargo build --profile fast
# Suitable for testing on many cores; binary is ~10-15% slower than release.
[profile.fast]
inherits = "release"
lto = false
codegen-units = 256
panic = "abort"