pprof-0.13.0/.cargo_vcs_info.json0000644000000001360000000000100122430ustar { "git": { "sha1": "4939f73f0cc2e8d92e3c2c50c9d02d6d4c205a86" }, "path_in_vcs": "" }pprof-0.13.0/.github/dependabot.yml000064400000000000000000000003161046102023000152230ustar 00000000000000version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" pprof-0.13.0/.github/workflows/rust.yml000064400000000000000000000107251046102023000161550ustar 00000000000000on: [push, pull_request] name: build concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true jobs: lint: name: Format and Clippy runs-on: ubuntu-latest steps: - name: Checkout sources uses: actions/checkout@v3 - name: Install Rust toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: 1.64.0 override: true components: rustfmt, clippy - name: Install protobuf compiler run: sudo apt-get install -y protobuf-compiler - name: Run cargo fmt uses: actions-rs/cargo@v1.0.3 with: command: fmt args: --all -- --check - name: Remove pre-generated prost files to force regeneration run: rm proto/*.rs - name: Run cargo clippy prost uses: actions-rs/cargo@v1.0.3 with: command: clippy args: --all-targets --features flamegraph,prost-codec -- -D warnings - name: Run cargo clippy protobuf uses: actions-rs/cargo@v1.0.3 with: command: clippy args: --all-targets --features flamegraph,protobuf-codec -- -D warnings - name: Check if the prost file committed to git is up-to-date run: | git diff --no-ext-diff --exit-code build: name: Build strategy: matrix: os: [ubuntu-latest, macos-latest] toolchain: [stable, nightly, 1.64.0] target: [ x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-apple-darwin, aarch64-apple-darwin, ] exclude: - os: ubuntu-latest target: x86_64-apple-darwin - os: ubuntu-latest target: aarch64-apple-darwin - os: macos-latest target: x86_64-unknown-linux-gnu - os: macos-latest target: aarch64-unknown-linux-gnu - os: macos-latest target: x86_64-unknown-linux-musl fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Checkout sources uses: actions/checkout@v3 - name: Install Rust toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} target: ${{ matrix.target }} override: true - name: Run cargo build prost uses: actions-rs/cargo@v1.0.3 with: command: build args: --features flamegraph,prost-codec --target ${{ matrix.target }} - name: Run cargo build protobuf uses: actions-rs/cargo@v1.0.3 with: command: build args: --features flamegraph,protobuf-codec --target ${{ matrix.target }} - name: Run cargo build frame pointer if: ${{ matrix.toolchain == 'nightly' && matrix.os == 'ubuntu-latest' }} uses: actions-rs/cargo@v1.0.3 with: command: build args: --no-default-features --features frame-pointer --target ${{ matrix.target }} test: name: Test strategy: matrix: os: [ubuntu-latest, macos-latest] toolchain: [stable, nightly] target: [ x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-apple-darwin, ] exclude: - os: ubuntu-latest target: x86_64-apple-darwin - os: macos-latest target: x86_64-unknown-linux-gnu - os: macos-latest target: x86_64-unknown-linux-musl fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Checkout sources uses: actions/checkout@v3 - name: Install Rust toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} target: ${{ matrix.target }} override: true - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }} name: Install musl run: sudo apt install musl-tools - name: Run cargo test prost uses: actions-rs/cargo@v1.0.3 with: command: test args: --features flamegraph,prost-codec --target ${{ matrix.target }} - name: Run cargo test protobuf uses: actions-rs/cargo@v1.0.3 with: command: test args: --features flamegraph,protobuf-codec --target ${{ matrix.target }} pprof-0.13.0/.gitignore000064400000000000000000000003221046102023000130200ustar 00000000000000# Generated by Cargo # will have compiled files and executables /target/ # These are backup files generated by rustfmt **/*.rs.bk .idea .vscode # Ignore some files produced by the examples. *.svg profile.pb pprof-0.13.0/CHANGELOG.md000064400000000000000000000153621046102023000126530ustar 00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.13.0] - 2023-09-27 ### Changed - Upgrade `prost`, `prost-derive`, `prost-build` to 0.12 (#223) ## [0.12.1] - 2023-07-25 ### Fixed - Handle potentially unaligned frame pointer (#217) - Fix the register field name according to libc (#218) ## [0.12.0] - 2023-07-03 ### Added - Support building `pprof-rs` for `android` target (#202) - Support building `pprof-rs` for `freebsd` target (#213) ### Changed - Upgrade `criterion` to 0.5 (#212) - Bump the MSRV to 1.64.0 (#204) ### Fixed - Hide `perf_signal_handler` frames on macOS (#207) ## [0.11.1] - 2023-02-21 ### Added - Support RISC-V architecture (#169) - Support LoongArch64 architecture (#174) ### Fixed - Use a globally shared pipe to validate memory to avoid FD leak (#198) ## [0.11.0] - 2022-11-03 ### Changed - Upgrade prost 0.11 (#166) - Upgrade criterion from 0.3 to 0.4 (#163) ### Fixed - Restart syscalls interuppted by SIGPROF when possible (#167) - Only do per-frame-blocklist-check when frame-pointer is enabled (#172) ## [0.10.1] - 2022-08-29 ### Changed - Update `MAX_DEPTH` to 128 (#159) ### Fixed - Fixed clippy warnnings and ignore prost mod (#160) ## [0.10.0] - 2022-06-27 ### Changed - Remove `backtrace-rs` feature, as the default choice when not specified (#130) ### Added - Add `sample_timestamp` to Frames and UnresolvedFrames in order to have more fine-grained info on when the samples are collected (#133) - ### Fixed - Export `UnresolvedReport` type to allow developers to get the unresolved report (#132) ## [0.9.1] - 2022-05-19 ### Fixed - Protect the error number in signal handler (#128) ## [0.9.0] - 2022-05-09 ### Added - Add `frame-pointer` feature to unwind the stack with frame pointer (#116) ### Changed - The user has to specify one unwind implementation (`backtrace-rs` or `frame-pointer`) in the features (#116) ## [0.8.0] - 2022-04-20 ### Changed - Update prost from 0.9 to 0.10 (#113, #114, #115) ### Fixed - Fix pthread_getname_np not available on musl (#110) ## [0.7.0] - 2022-03-08 ### Added - Add rust-protobuf support by adding protobuf-codec features (#106) ### Changed - protobuf feature is renamed to prost-codec to align all other tikv projects (#106) ## [0.6.2] - 2021-12-24 ### Added - implement `Clone` for `ProfilerGuardBuilder` [@yangkeao](https://github.com/YangKeao) - Add thread names and timing information to protobuf reports [@free](https://github.com/free) ## [0.6.1] - 2021-11-01 ### Added - `blocklist` to skip sampling in selected shared library [@yangkeao](https://github.com/YangKeao) ### Fixed - Fix memory leak in collector of samples [@yangkeao](https://github.com/YangKeao) ## [0.6.0] - 2021-10-21 ### Changed - Bump prost* to v0.9.0 [@PsiACE](https://github.com/PsiACE) ### Security - Bump nix to v0.23 [@PsiACE](https://github.com/PsiACE) ## [0.5.0] - 2021-10-21 ### Changed - Bump version of prost* [@PsiACE](https://github.com/PsiACE) ## [0.4.4] - 2021-07-13 ### Fixed - Fix the lifetime mark is not used by criterion output [@yangkeao](https://github.com/YangKeao) ## [0.4.3] - 2021-03-18 ### Changed - Change the output paths for `criterion::PProfProfiler` to support benchmark groups [@yangkeao](https://github.com/YangKeao) ### Security - Bump nix to v0.20 [@yangkeao](https://github.com/YangKeao) ## [0.4.2] - 2021-02-20 ### Added - Implement criterion profiler [@yangkeao](https://github.com/YangKeao) ### Fixed - Fix compilation error on arm architecture [@yangkeao](https://github.com/YangKeao) ## [0.4.1] - 2021-02-10 ### Added - Allow passing custom flamegraph options [@yangkeao](https://github.com/YangKeao) ## [0.4.0] - 2020-12-30 ### Fix - Fix flamegraph inline functions [@yangkeao](https://github.com/YangKeao) ## [0.3.21] - 2020-12-28 ### Changed - Bump version of prost* [@xhebox](https://github.com/xhebox) ### Security - Bump rand to v0.8 @dependabot - Bump nix to v0.19 @dependabot ## [0.3.20] - 2020-12-11 ### Changed - Split `symbolic-demangle` into multiple features [@yangkeao](https://github.com/YangKeao) ## [0.3.19] - 2020-12-11 ### Fix - Ignore SIGPROF signal after stop, rather than reset to the default handler [@yangkeao](https://github.com/YangKeao) ## [0.3.18] - 2020-08-07 ### Added - Add `Report::build_unresolved` [@umanwizard](https://github.com/umanwizard) ### Changed - Change from `&mut self` to `&self` in `RpoertBuilder::build` [@umanwizard](https://github.com/umanwizard) ## [0.3.16] - 2020-02-25 ### Added - Support cpp demangle [@yangkeao](https://github.com/YangKeao) ## [0.3.15] - 2020-02-05 ### Added - Filter out signal handler functions [@yangkeao](https://github.com/YangKeao) ### Fixed - Fix protobuf unit [@yangkeao](https://github.com/YangKeao) ## [0.3.14] - 2020-02-05 ### Fixed - Don't get lock inside `backtrace::Backtrace` [@yangkeao](https://github.com/YangKeao) ## [0.3.13] - 2020-01-31 ### Added - Export `prost::Message` [@yangkeao](https://github.com/YangKeao) ### Fixed - Only use thread name on linux and macos [@yangkeao](https://github.com/YangKeao) - Disable `#![feature(test)]` outside of tests [@kennytm](https://github.com/kennytm) ## [0.3.12] - 2019-11-27 ### Fixed - Stop timer before profiler stops [@yangkeao](https://github.com/YangKeao) ## [0.3.9] - 2019-11-08 ### Added - Support profobuf output [@lonng](https://github.com/lonng) ## [0.3.5] - 2019-11-04 ### Changed - Change crate name from `rsperftools` to `pprof-rs` [@yangkeao](https://github.com/YangKeao) ## [0.3.4] - 2019-11-04 ### Changed - Use less stack space [@yangkeao](https://github.com/YangKeao) ## [0.3.2] - 2019-11-01 ### Fixed - Seek to the start before reading file in `TempFdArray`[@yangkeao](https://github.com/YangKeao) ## [0.3.1] - 2019-11-01 ### Added - Support customized post processor for frames [@yangkeao](https://github.com/YangKeao) ### Fixed - Fix deadlock inside the `std::thread::current().name()` [@yangkeao](https://github.com/YangKeao) ## [0.2.3] - 2019-10-31 ### Fixed - Avoid calling `malloc` inside the signal handler [@yangkeao](https://github.com/YangKeao) ## [0.1.4] - 2019-10-25 ### Changed - Implement `Send` for `Symbol` [@yangkeao](https://github.com/YangKeao) ## [0.1.3] - 2019-10-24 ### Added - Add log [@yangkeao](https://github.com/YangKeao) ### Fixed - Stop signal handler after processing started [@yangkeao](https://github.com/YangKeao) ## [0.1.1] - 2019-10-22 ### Added - Check whether profiler is running when starting the profiler [@yangkeao](https://github.com/YangKeao) ## [0.1.0] - 2019-10-22 ### Added - Support profiling with signal handler [@yangkeao](https://github.com/YangKeao) - Support generating flamegraph [@yangkeao](https://github.com/YangKeao) pprof-0.13.0/Cargo.lock0000644000001016470000000000100102270ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", ] [[package]] name = "aho-corasick" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" [[package]] name = "anyhow" version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" [[package]] name = "ciborium-ll" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clap" version = "4.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e" dependencies = [ "anstyle", "clap_lex", ] [[package]] name = "clap_lex" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "cpp_demangle" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] [[package]] name = "criterion" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "is-terminal", "itertools", "num-traits", "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-deque" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "debugid" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ "uuid", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", "windows-sys", ] [[package]] name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", "libc", ] [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "findshlibs" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" dependencies = [ "cc", "lazy_static", "libc", "winapi", ] [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "gimli" version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "half" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "home" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ "windows-sys", ] [[package]] name = "indexmap" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "inferno" version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c50453ec3a6555fad17b1cd1a80d16af5bc7cb35094f64e429fd46549018c6a3" dependencies = [ "ahash", "indexmap", "is-terminal", "itoa", "log", "num-format", "once_cell", "quick-xml", "rgb", "str_stack", ] [[package]] name = "is-terminal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", "windows-sys", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linux-raw-sys" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] name = "lock_api" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memmap2" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] [[package]] name = "memoffset" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "multimap" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "nix" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", ] [[package]] name = "num-format" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ "arrayvec", "itoa", ] [[package]] name = "num-traits" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "object" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "petgraph" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "plotters" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] [[package]] name = "pprof" version = "0.13.0" dependencies = [ "backtrace", "cfg-if", "criterion", "findshlibs", "inferno", "libc", "log", "nix", "once_cell", "parking_lot", "prost", "prost-build", "prost-derive", "protobuf", "protobuf-codegen-pure", "rand", "sha2", "smallvec", "symbolic-demangle", "tempfile", "thiserror", ] [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "prost" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" dependencies = [ "bytes", "prost-derive", ] [[package]] name = "prost-build" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac" dependencies = [ "bytes", "heck", "itertools", "log", "multimap", "once_cell", "petgraph", "prettyplease", "prost", "prost-types", "regex", "syn", "tempfile", "which", ] [[package]] name = "prost-derive" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", "syn", ] [[package]] name = "prost-types" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" dependencies = [ "prost", ] [[package]] name = "protobuf" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "protobuf-codegen" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6" dependencies = [ "protobuf", ] [[package]] name = "protobuf-codegen-pure" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865" dependencies = [ "protobuf", "protobuf-codegen", ] [[package]] name = "quick-xml" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" dependencies = [ "memchr", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "rayon" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rgb" version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" dependencies = [ "bytemuck", ] [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" version = "0.38.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" dependencies = [ "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "sha2" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "smallvec" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "str_stack" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" [[package]] name = "symbolic-common" version = "12.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fac08504d60cf5bdffeb8a6a028f1a4868a5da1098bb19eb46239440039163fb" dependencies = [ "debugid", "memmap2", "stable_deref_trait", "uuid", ] [[package]] name = "symbolic-demangle" version = "12.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b212728d4f6c527c1d50d6169e715f6e02d849811843c13e366d8ca6d0cf5c4" dependencies = [ "cpp_demangle", "rustc-demangle", "symbolic-common", ] [[package]] name = "syn" version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tempfile" version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", "windows-sys", ] [[package]] name = "thiserror" version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "uuid" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", "home", "once_cell", "rustix", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" pprof-0.13.0/Cargo.toml0000644000000056730000000000100102540ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.64.0" name = "pprof" version = "0.13.0" authors = ["Yang Keao "] description = "An internal perf tools for rust programs." documentation = "https://docs.rs/pprof/" readme = "README.md" license = "Apache-2.0" repository = "https://github.com/tikv/pprof-rs" [package.metadata.docs.rs] all-features = true [[example]] name = "flamegraph" required-features = ["flamegraph"] [[example]] name = "profile_proto_with_prost" required-features = [ "protobuf", "prost-codec", ] [[example]] name = "profile_proto_with_protobuf_codec" required-features = [ "protobuf", "protobuf-codec", ] [[example]] name = "multithread_flamegraph" required-features = ["flamegraph"] [[example]] name = "criterion" required-features = [ "flamegraph", "criterion", ] [[bench]] name = "collector" path = "benches/collector.rs" harness = false [[bench]] name = "addr_validate" path = "benches/addr_validate.rs" harness = false [dependencies.backtrace] version = "0.3" [dependencies.cfg-if] version = "1.0" [dependencies.criterion] version = "0.5" optional = true [dependencies.findshlibs] version = "0.10" [dependencies.inferno] version = "0.11" features = ["nameattr"] optional = true default-features = false [dependencies.libc] version = "^0.2.66" [dependencies.log] version = "0.4" [dependencies.nix] version = "0.26" features = [ "signal", "fs", ] default-features = false [dependencies.once_cell] version = "1.9" [dependencies.parking_lot] version = "0.12" [dependencies.prost] version = "0.12" optional = true [dependencies.prost-derive] version = "0.12" optional = true [dependencies.protobuf] version = "2.0" optional = true [dependencies.smallvec] version = "1.7" [dependencies.symbolic-demangle] version = "12.1" features = ["rust"] default-features = false [dependencies.tempfile] version = "3.1" [dependencies.thiserror] version = "1.0" [dev-dependencies.criterion] version = "0.5" [dev-dependencies.rand] version = "0.8.0" [build-dependencies.prost-build] version = "0.12" optional = true [build-dependencies.protobuf-codegen-pure] version = "2.0" optional = true [build-dependencies.sha2] version = "0.10" optional = true [features] _protobuf = [] cpp = ["symbolic-demangle/cpp"] default = ["cpp"] flamegraph = ["inferno"] frame-pointer = [] prost-codec = [ "prost", "prost-derive", "prost-build", "sha2", "_protobuf", ] protobuf-codec = [ "protobuf", "protobuf-codegen-pure", "_protobuf", ] pprof-0.13.0/Cargo.toml.orig000064400000000000000000000042571046102023000137320ustar 00000000000000[package] name = "pprof" version = "0.13.0" authors = ["Yang Keao "] edition = "2021" license = "Apache-2.0" description = "An internal perf tools for rust programs." repository = "https://github.com/tikv/pprof-rs" documentation = "https://docs.rs/pprof/" readme = "README.md" rust-version = "1.64.0" # MSRV [features] default = ["cpp"] cpp = ["symbolic-demangle/cpp"] flamegraph = ["inferno"] frame-pointer = [] # A private feature to indicate either prost-codec or protobuf-codec is enabled. _protobuf = [] prost-codec = ["prost", "prost-derive", "prost-build", "sha2", "_protobuf"] protobuf-codec = ["protobuf", "protobuf-codegen-pure", "_protobuf"] [dependencies] backtrace = { version = "0.3" } once_cell = "1.9" libc = "^0.2.66" log = "0.4" nix = { version = "0.26", default-features = false, features = ["signal", "fs"] } parking_lot = "0.12" tempfile = "3.1" thiserror = "1.0" findshlibs = "0.10" cfg-if = "1.0" smallvec = "1.7" inferno = { version = "0.11", default-features = false, features = ["nameattr"], optional = true } prost = { version = "0.12", optional = true } prost-derive = { version = "0.12", optional = true } protobuf = { version = "2.0", optional = true } criterion = {version = "0.5", optional = true} [dependencies.symbolic-demangle] version = "12.1" default-features = false features = ["rust"] [dev-dependencies] criterion = "0.5" rand = "0.8.0" [build-dependencies] prost-build = { version = "0.12", optional = true } sha2 = { version = "0.10", optional = true } protobuf-codegen-pure = { version = "2.0", optional = true } [[example]] name = "flamegraph" required-features = ["flamegraph"] [[example]] name = "profile_proto_with_prost" required-features = ["protobuf", "prost-codec"] [[example]] name = "profile_proto_with_protobuf_codec" required-features = ["protobuf", "protobuf-codec"] [[example]] name = "multithread_flamegraph" required-features = ["flamegraph"] [[example]] name = "criterion" required-features = ["flamegraph", "criterion"] [[bench]] name = "collector" path = "benches/collector.rs" harness = false [[bench]] name = "addr_validate" path = "benches/addr_validate.rs" harness = false [package.metadata.docs.rs] all-features = true pprof-0.13.0/LICENSE000064400000000000000000000261271046102023000120500ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2019 TiKV Project Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. pprof-0.13.0/README.md000064400000000000000000000320051046102023000123120ustar 00000000000000# pprof `pprof` is a cpu profiler that can be easily integrated into a rust program. [![Actions Status](https://github.com/tikv/pprof-rs/workflows/build/badge.svg)](https://github.com/tikv/pprof-rs/actions) [![Crates.io](https://img.shields.io/crates/v/pprof.svg)](https://crates.io/crates/pprof) [![Dependency Status](https://deps.rs/repo/github/tikv/pprof-rs/status.svg)](https://deps.rs/repo/github/tikv/pprof-rs) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftikv%2Fpprof-rs.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftikv%2Fpprof-rs?ref=badge_shield) ## Usage First, get a guard to start profiling. Profiling will continue until this guard was dropped. ```rust let guard = pprof::ProfilerGuardBuilder::default().frequency(1000).blocklist(&["libc", "libgcc", "pthread", "vdso"]).build().unwrap(); ``` During the profiling time, you can get a report with the guard. ```rust if let Ok(report) = guard.report().build() { println!("report: {:?}", &report); }; ``` `Debug` was implemented for `Report`. It will print a human-readable stack counter report. Here is an example: ``` FRAME: backtrace::backtrace::trace::h3e91a3123a3049a5 -> FRAME: pprof::profiler::perf_signal_handler::h7b995c4ab2e66493 -> FRAME: Unknown -> FRAME: prime_number::is_prime_number::h70653a2633b88023 -> FRAME: prime_number::main::h47f1058543990c8b -> FRAME: std::rt::lang_start::{{closure}}::h4262e250f8024b06 -> FRAME: std::rt::lang_start_internal::{{closure}}::h812f70926ebbddd0 -> std::panicking::try::do_call::h3210e2ce6a68897b -> FRAME: __rust_maybe_catch_panic -> FRAME: std::panicking::try::h28c2e2ec1c3871ce -> std::panic::catch_unwind::h05e542185e35aabf -> std::rt::lang_start_internal::hd7efcfd33686f472 -> FRAME: main -> FRAME: __libc_start_main -> FRAME: _start -> FRAME: Unknown -> THREAD: prime_number 1217 FRAME: backtrace::backtrace::trace::h3e91a3123a3049a5 -> FRAME: pprof::profiler::perf_signal_handler::h7b995c4ab2e66493 -> FRAME: Unknown -> FRAME: alloc::alloc::box_free::h82cea48ed688e081 -> FRAME: prime_number::main::h47f1058543990c8b -> FRAME: std::rt::lang_start::{{closure}}::h4262e250f8024b06 -> FRAME: std::rt::lang_start_internal::{{closure}}::h812f70926ebbddd0 -> std::panicking::try::do_call::h3210e2ce6a68897b -> FRAME: __rust_maybe_catch_panic -> FRAME: std::panicking::try::h28c2e2ec1c3871ce -> std::panic::catch_unwind::h05e542185e35aabf -> std::rt::lang_start_internal::hd7efcfd33686f472 -> FRAME: main -> FRAME: __libc_start_main -> FRAME: _start -> FRAME: Unknown -> THREAD: prime_number 1 FRAME: backtrace::backtrace::trace::h3e91a3123a3049a5 -> FRAME: pprof::profiler::perf_signal_handler::h7b995c4ab2e66493 -> FRAME: Unknown -> FRAME: prime_number::main::h47f1058543990c8b -> FRAME: std::rt::lang_start::{{closure}}::h4262e250f8024b06 -> FRAME: std::rt::lang_start_internal::{{closure}}::h812f70926ebbddd0 -> std::panicking::try::do_call::h3210e2ce6a68897b -> FRAME: __rust_maybe_catch_panic -> FRAME: std::panicking::try::h28c2e2ec1c3871ce -> std::panic::catch_unwind::h05e542185e35aabf -> std::rt::lang_start_internal::hd7efcfd33686f472 -> FRAME: main -> FRAME: __libc_start_main -> FRAME: _start -> FRAME: Unknown -> THREAD: prime_number 1 ``` ## Features - `cpp` enables the cpp demangle. - `flamegraph` enables the flamegraph report format. - `prost-codec` enables the pprof protobuf report format through `prost`. - `protobuf-codec` enables the pprof protobuf report format through `protobuf` crate. - `frame-pointer` gets the backtrace through frame pointer. **only available for nightly** ## Flamegraph ```toml pprof = { version = "0.13", features = ["flamegraph"] } ``` If `flamegraph` feature is enabled, you can generate flamegraph from the report. `Report` struct has a method `flamegraph` which can generate flamegraph and write it into a `Write`. ```rust if let Ok(report) = guard.report().build() { let file = File::create("flamegraph.svg").unwrap(); report.flamegraph(file).unwrap(); }; ``` Additionally, custom flamegraph options can be specified. ```rust if let Ok(report) = guard.report().build() { let file = File::create("flamegraph.svg").unwrap(); let mut options = pprof::flamegraph::Options::default(); options.image_width = Some(2500); report.flamegraph_with_options(file, &mut options).unwrap(); }; ``` Here is an example of generated flamegraph: ![flamegraph](https://user-images.githubusercontent.com/5244316/68021936-c1265e80-fcdd-11e9-8fa5-62b548bc751d.png) ## Frame Post Processor Before the report was generated, `frame_post_processor` was provided as an interface to modify raw statistic data. If you want to group several symbols/thread or demangle for some symbols, this feature will benefit you. For example: ```rust fn frames_post_processor() -> impl Fn(&mut pprof::Frames) { let thread_rename = [ (Regex::new(r"^grpc-server-\d*$").unwrap(), "grpc-server"), (Regex::new(r"^cop-high\d*$").unwrap(), "cop-high"), (Regex::new(r"^cop-normal\d*$").unwrap(), "cop-normal"), (Regex::new(r"^cop-low\d*$").unwrap(), "cop-low"), (Regex::new(r"^raftstore-\d*$").unwrap(), "raftstore"), (Regex::new(r"^raftstore-\d*-\d*$").unwrap(), "raftstore"), (Regex::new(r"^sst-importer\d*$").unwrap(), "sst-importer"), ( Regex::new(r"^store-read-low\d*$").unwrap(), "store-read-low", ), (Regex::new(r"^rocksdb:bg\d*$").unwrap(), "rocksdb:bg"), (Regex::new(r"^rocksdb:low\d*$").unwrap(), "rocksdb:low"), (Regex::new(r"^rocksdb:high\d*$").unwrap(), "rocksdb:high"), (Regex::new(r"^snap sender\d*$").unwrap(), "snap-sender"), (Regex::new(r"^snap-sender\d*$").unwrap(), "snap-sender"), (Regex::new(r"^apply-\d*$").unwrap(), "apply"), (Regex::new(r"^future-poller-\d*$").unwrap(), "future-poller"), ]; move |frames| { for (regex, name) in thread_rename.iter() { if regex.is_match(&frames.thread_name) { frames.thread_name = name.to_string(); } } } } ``` ```rust if let Ok(report) = guard.frames_post_processor(frames_post_processor()).report().build() { let file = File::create("flamegraph.svg").unwrap(); report.flamegraph(file).unwrap(); } ``` ## Use with `pprof` With `protobuf` feature enabled, `pprof-rs` can also output [`profile.proto`](https://github.com/google/pprof/blob/master/proto/profile.proto) format. ```rust match guard.report().build() { Ok(report) => { let mut file = File::create("profile.pb").unwrap(); let profile = report.pprof().unwrap(); let mut content = Vec::new(); profile.encode(&mut content).unwrap(); file.write_all(&content).unwrap(); println!("report: {}", &report); } Err(_) => {} }; ``` Then you can use `pprof` command with `profile.pb`. For example: ```shell ~/go/bin/pprof -svg profile.pb ``` Then `pprof` will generate a svg file according to the profile. ![tree](https://user-images.githubusercontent.com/5244316/68571082-1f50ff80-049d-11ea-8437-211ab0d80480.png) ## Integrate with `criterion` With `criterion` feature enabled, a criterion custom profiler is provided in `pprof-rs`. ```rust use pprof::criterion::{PProfProfiler, Output}; criterion_group!{ name = benches; config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); targets = bench } criterion_main!(benches); ``` After running the benchmark, you can find the flamegraph at `target/criterion//profile/flamegraph.svg`. `protobuf` output is also available with the `Output::Protobuf` option; these end up at `target/criterion//profile.pb`. For more details, you can check the [`examples/criterion.rs`](examples/criterion.rs), and the profiling document of [`criterion`](https://bheisler.github.io/criterion.rs/book/user_guide/profiling.html). For a quick start, you can run this example with `cargo run --example criterion --release --features="flamegraph criterion" -- --bench --profile-time 5` ## Why not ... There have been tons of profilers, why we create a new one? Here we make a comparison between `pprof-rs` and other popular profilers to help you choose the best fit one. ### gperftools `gperftools` is also an integrated profiler. There is also a wrapper for `gperftools` in rust called [`cpuprofiler`](https://crates.io/crates/cpuprofiler) which makes it programmable for a rust program. #### Pros 1. `pprof-rs` has a modern build system and can be integrated into a rust program easily while compiling `gperftools` statically is buggy. 2. `pprof-rs` has a native rust interface while `gperftools`'s wrapper is **just** a wrapper. 3. Programming with rust guarantees thread safety natively. #### Cons 1. `gperftools` is a collection of performance analysis tools which contains cpu profiler, heap profiler... `pprof-rs` focuses on cpu profiler now. ### perf `perf` is a performance analyzing tool in Linux. #### Pros 1. You don't need to start another process to perf with `pprof-rs`. 2. `pprof-rs` can be easily integrated with rust program which means you don't need to install any other programs. 3. `pprof-rs` has a modern programmable interface to hack with 4. `pprof-rs` theoretically supports all POSIX systems and can easily support more systems in the future. #### Cons 1. `perf` is much more feature-rich than `pprof-rs`. 2. `perf` is highly integrated with Linux. ## Implementation When profiling was started, `setitimer` system call was used to set up a timer which will send a SIGPROF to this program every constant interval. When receiving a SIGPROF signal, the signal handler will capture a backtrace and increase the count of it. After a while, the profiler can get every possible backtrace and their count. Finally, we can generate a report with profiler data. However, the real world is full of thorns. There are many worths of note parts in the implementation. ### Backtrace Unfortunately, there is no 100% robust stack tracing method. [Some related researches](https://github.com/gperftools/gperftools/wiki/gperftools%27-stacktrace-capturing-methods-and-their-issues) have been done by gperftools. `pprof-rs` uses [`backtrace-rs`](https://github.com/rust-lang/backtrace-rs) which finally uses libunwind provided by `libgcc` **WARN:** as described in former gperftools documents, libunwind provided by `libgcc` is not signal safe. > libgcc's unwind method is not safe to use from signal handlers. One particular cause of deadlock is when profiling tick happens when program is propagating thrown exception. This can be resolved by adding a blocklist: ```rust let guard = pprof::ProfilerGuardBuilder::default().frequency(1000).blocklist(&["libc", "libgcc", "pthread", "vdso"]).build().unwrap(); ``` The `vdso` should also be added to the blocklist, because in some distribution (e.g. ubuntu 18.04), the dwarf information in vdso is incorrect. ### Frame Pointer The `pprof-rs` also supports unwinding through frame pointer, without the need to use `libunwind`. However, the standard library shipped with the rust compiler does not have the correct frame pointer in every function, so you need to use `cargo +nightly -Z build-std` to build the standard library from source. As we cannot get the stack boundaries inside the signal handler, it's also not possible to ensure the safety. If the frame pointer was set to a wrong value, the program will panic. ### Signal Safety Signal safety is hard to guarantee. But it's not *that* hard. First, we have to avoid deadlock. When profiler samples or reports, it will get a global lock on the profiler. Particularly, deadlock happenswhen the running program is getting a report from the profiler (which will hold the lock), at the same time, a SIGPROF signal is triggered and the profiler wants to sample (which will also hold the lock). So we don't wait for the lock in signal handler, instead we `try_lock` in the signal handler. If the global lock cannot be gotten, the profiler will give up directly. Then, signal safety POSIX function is quite limited as [listed here](http://man7.org/linux/man-pages/man7/signal-safety.7.html). The most bothering issue is that we cannot use `malloc` in signal handler. So we can only use pre-allocated memory in profiler. The simplest way is `write` every sample serially into a file. We optimized it with a fix-sized hashmap that has a fixed number of buckets and every bucket is an array with a fixed number of items. If the hashmap is full, we pop out the item with minimum count and write it into a temporary file. Unit tests have been added to guarantee there is no `malloc` in sample functions. `futex` is also not safe to use in signal handler. So we use a spin lock to avoid usage of `futex`. ## TODO 1. Restore the original SIGPROF handler after stopping the profiler. ## Minimum Supported Rust Version Rust 1.64 or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. ## License [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftikv%2Fpprof-rs.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftikv%2Fpprof-rs?ref=badge_large) pprof-0.13.0/benches/addr_validate.rs000064400000000000000000000014241046102023000155740ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use criterion::{criterion_group, criterion_main, Criterion}; use pprof::validate; fn bench_validate_addr(c: &mut Criterion) { c.bench_function("validate stack addr", |b| { let stack_addrs = [0; 100]; b.iter(|| { stack_addrs.iter().for_each(|item| { validate(item as *const _ as *const libc::c_void); }) }) }); c.bench_function("validate heap addr", |b| { let heap_addrs = vec![0; 100]; b.iter(|| { heap_addrs.iter().for_each(|item| { validate(item as *const _ as *const libc::c_void); }) }) }); } criterion_group!(benches, bench_validate_addr); criterion_main!(benches); pprof-0.13.0/benches/collector.rs000064400000000000000000000022051046102023000147750ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use criterion::{criterion_group, criterion_main, Criterion}; use pprof::{Collector, HashCounter}; fn bench_write_to_collector(c: &mut Criterion) { c.bench_function("write_to_collector", |b| { let mut collector = Collector::new().unwrap(); const SIZE: usize = 1000; let mut vec: Vec = Vec::with_capacity(SIZE); for _ in 0..vec.capacity() { vec.push(rand::random()); } b.iter(|| { vec.iter().for_each(|item| { collector.add(*item, 1).unwrap(); }) }) }); c.bench_function("write_into_stack_hash_counter", |b| { let mut collector = HashCounter::default(); const SIZE: usize = 1000; let mut vec: Vec = Vec::with_capacity(SIZE); for _ in 0..vec.capacity() { vec.push(rand::random()); } b.iter(|| { vec.iter().for_each(|item| { collector.add(*item, 1); }) }); }); } criterion_group!(benches, bench_write_to_collector); criterion_main!(benches); pprof-0.13.0/build.rs000064400000000000000000000045511046102023000125050ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. #[cfg(feature = "protobuf-codec")] // Allow deprecated as TiKV pin versions to a outdated one. #[allow(deprecated)] fn generate_protobuf() { use std::io::Write; let out_dir = std::env::var("OUT_DIR").unwrap(); protobuf_codegen_pure::run(protobuf_codegen_pure::Args { out_dir: &out_dir, includes: &["proto"], input: &["proto/profile.proto"], customize: protobuf_codegen_pure::Customize { generate_accessors: Some(false), lite_runtime: Some(true), ..Default::default() }, }) .unwrap(); let mut f = std::fs::File::create(format!("{}/mod.rs", out_dir)).unwrap(); write!(f, "pub mod profile;").unwrap(); } #[cfg(feature = "prost-codec")] fn generate_prost() { use sha2::{Digest, Sha256}; use std::{ fmt::Write, fs::{self, File}, io::{self, BufRead, BufReader}, }; const PRE_GENERATED_PATH: &str = "proto/perftools.profiles.rs"; // Calculate the SHA256 of the proto file let mut hasher = Sha256::new(); let mut proto_file = BufReader::new(File::open("proto/profile.proto").unwrap()); io::copy(&mut proto_file, &mut hasher).unwrap(); let mut hex = String::new(); for b in hasher.finalize() { write!(&mut hex, "{:x}", b).unwrap(); } let hash_comment = format!("// {} proto/profile.proto", hex); let first_line = File::open(PRE_GENERATED_PATH) .and_then(|f| { let mut reader = BufReader::new(f); let mut first_line = String::new(); reader.read_line(&mut first_line)?; Ok(first_line) }) .unwrap_or_default(); // If the hash of the proto file changes, regenerate the prost file. if first_line.trim() != hash_comment { prost_build::Config::new() .out_dir("proto/") .compile_protos(&["proto/profile.proto"], &["proto/"]) .unwrap(); // Prepend the hash comment to the generated file. let generated = fs::read_to_string(PRE_GENERATED_PATH).unwrap(); let with_hex = format!("{}\n\n{}", hash_comment, generated); fs::write(PRE_GENERATED_PATH, with_hex).unwrap(); } } fn main() { #[cfg(feature = "prost-codec")] generate_prost(); #[cfg(feature = "protobuf-codec")] generate_protobuf(); } pprof-0.13.0/examples/backtrace_while_sampling.rs000064400000000000000000000012441046102023000202210ustar 00000000000000// Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. use std::fs::File; fn deep_recursive(depth: i32) { if depth > 0 { deep_recursive(depth - 1); } else { backtrace::Backtrace::new(); } } fn main() { let guard = pprof::ProfilerGuardBuilder::default() .frequency(1000) .blocklist(&["libc", "libgcc", "pthread"]) .build() .unwrap(); for _ in 0..10000 { deep_recursive(20); } if let Ok(report) = guard.report().build() { let file = File::create("flamegraph.svg").unwrap(); report.flamegraph(file).unwrap(); println!("report: {:?}", &report); }; } pprof-0.13.0/examples/criterion.rs000064400000000000000000000017001046102023000152130ustar 00000000000000#[macro_use] extern crate criterion; use criterion::{black_box, BenchmarkId, Criterion}; use pprof::criterion::{Output, PProfProfiler}; // Thanks to the example provided by @jebbow in his article // https://www.jibbow.com/posts/criterion-flamegraphs/ fn fibonacci(n: u64) -> u64 { match n { 0 | 1 => 1, n => fibonacci(n - 1) + fibonacci(n - 2), } } fn bench(c: &mut Criterion) { c.bench_function("Fibonacci", |b| b.iter(|| fibonacci(black_box(20)))); } fn bench_group(c: &mut Criterion) { let mut group = c.benchmark_group("Fibonacci Sizes"); for s in &[1, 10, 100, 1000] { group.bench_with_input(BenchmarkId::from_parameter(s), s, |b, s| { b.iter(|| fibonacci(black_box(*s))) }); } } criterion_group! { name = benches; config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); targets = bench, bench_group } criterion_main!(benches); pprof-0.13.0/examples/flamegraph.rs000064400000000000000000000044761046102023000153400ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::fs::File; #[inline(never)] fn is_prime_number1(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(always)] fn is_prime_number2(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn is_prime_number3(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = prepare_prime_numbers(); let guard = pprof::ProfilerGuard::new(100).unwrap(); let mut v = 0; for i in 2..5000000 { if i % 4 == 0 { if is_prime_number1(i, &prime_numbers) { v += 1; } } else if i % 4 == 1 { if is_prime_number2(i, &prime_numbers) { v += 1; } } else if is_prime_number3(i, &prime_numbers) { v += 1; } } println!("Prime numbers: {}", v); if let Ok(report) = guard.report().build() { let file = File::create("flamegraph.svg").unwrap(); report.flamegraph(file).unwrap(); println!("report: {:?}", &report); }; } pprof-0.13.0/examples/multithread.rs000064400000000000000000000044321046102023000155440ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::sync::Arc; #[inline(never)] fn is_prime_number(v: usize, prime_numbers: Arc>) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers.iter() { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = Arc::new(prepare_prime_numbers()); let guard = pprof::ProfilerGuard::new(100).unwrap(); let p1 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_ONE".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p1.clone()) { _v += 1; } } }) .unwrap(); let p2 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_TWO".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p2.clone()) { _v += 1; } } }) .unwrap(); let p3 = prime_numbers; std::thread::spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p3.clone()) { _v += 1; } } }); loop { if let Ok(report) = guard.report().build() { println!("{:?}", report); }; std::thread::sleep(std::time::Duration::from_secs(1)) } // pprof::PROFILER.lock().unwrap().stop(); } pprof-0.13.0/examples/multithread_flamegraph.rs000064400000000000000000000047031046102023000177330ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::fs::File; use std::sync::Arc; #[inline(never)] fn is_prime_number(v: usize, prime_numbers: Arc>) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers.iter() { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = Arc::new(prepare_prime_numbers()); // println!("{}", std::mem::size_of::>()); let guard = pprof::ProfilerGuard::new(100).unwrap(); let p1 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_ONE".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p1.clone()) { _v += 1; } } }) .unwrap(); let p2 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_TWO".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p2.clone()) { _v += 1; } } }) .unwrap(); let p3 = prime_numbers; std::thread::spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p3.clone()) { _v += 1; } } }); std::thread::sleep(std::time::Duration::from_secs(5)); if let Ok(report) = guard.report().build() { let file = File::create("flamegraph.svg").unwrap(); report.flamegraph(file).unwrap(); println!("{:?}", report); }; // pprof::PROFILER.lock().unwrap().stop(); } pprof-0.13.0/examples/post_processor.rs000064400000000000000000000050051046102023000163030ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::sync::Arc; #[inline(never)] fn is_prime_number(v: usize, prime_numbers: Arc>) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers.iter() { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = Arc::new(prepare_prime_numbers()); // println!("{}", std::mem::size_of::>()); let guard = pprof::ProfilerGuard::new(100).unwrap(); let p1 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_ONE".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p1.clone()) { _v += 1; } } }) .unwrap(); let p2 = prime_numbers.clone(); std::thread::Builder::new() .name("THREAD_TWO".to_owned()) .spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p2.clone()) { _v += 1; } } }) .unwrap(); let p3 = prime_numbers; std::thread::spawn(move || loop { let mut _v = 0; for i in 2..50000 { if is_prime_number(i, p3.clone()) { _v += 1; } } }); loop { if let Ok(report) = guard .report() .frames_post_processor(|frames| { frames.thread_name = "PROCESSED".to_string(); }) .build() { println!("{:?}", report); }; std::thread::sleep(std::time::Duration::from_secs(1)) } // pprof::PROFILER.lock().unwrap().stop(); } pprof-0.13.0/examples/prime_number.rs000064400000000000000000000026641046102023000157130ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. #[inline(never)] fn is_prime_number(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = prepare_prime_numbers(); let guard = pprof::ProfilerGuard::new(100).unwrap(); loop { let mut v = 0; for i in 2..50000 { if is_prime_number(i, &prime_numbers) { v += 1; } } println!("Prime numbers: {}", v); if let Ok(report) = guard.report().build() { println!("{:?}", report); }; } } pprof-0.13.0/examples/profile_proto_with_prost.rs000064400000000000000000000047631046102023000203760ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use pprof::protos::Message; use std::fs::File; use std::io::Write; #[inline(never)] fn is_prime_number1(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(always)] fn is_prime_number2(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn is_prime_number3(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = prepare_prime_numbers(); let guard = pprof::ProfilerGuard::new(100).unwrap(); let mut v = 0; for i in 2..5000000 { if i % 4 == 0 { if is_prime_number1(i, &prime_numbers) { v += 1; } } else if i % 4 == 1 { if is_prime_number2(i, &prime_numbers) { v += 1; } } else if is_prime_number3(i, &prime_numbers) { v += 1; } } println!("Prime numbers: {}", v); if let Ok(report) = guard.report().build() { let mut file = File::create("profile.pb").unwrap(); let profile = report.pprof().unwrap(); let mut content = Vec::new(); profile.encode(&mut content).unwrap(); file.write_all(&content).unwrap(); println!("report: {:?}", report); }; } pprof-0.13.0/examples/profile_proto_with_protobuf_codec.rs000064400000000000000000000047711046102023000222230ustar 00000000000000// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use pprof::protos::Message; use std::fs::File; use std::io::Write; #[inline(never)] fn is_prime_number1(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(always)] fn is_prime_number2(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn is_prime_number3(v: usize, prime_numbers: &[usize]) -> bool { if v < 10000 { let r = prime_numbers.binary_search(&v); return r.is_ok(); } for n in prime_numbers { if v % n == 0 { return false; } } true } #[inline(never)] fn prepare_prime_numbers() -> Vec { // bootstrap: Generate a prime table of 0..10000 let mut prime_number_table: [bool; 10000] = [true; 10000]; prime_number_table[0] = false; prime_number_table[1] = false; for i in 2..10000 { if prime_number_table[i] { let mut v = i * 2; while v < 10000 { prime_number_table[v] = false; v += i; } } } let mut prime_numbers = vec![]; for (i, exist) in prime_number_table.iter().enumerate().skip(2) { if *exist { prime_numbers.push(i); } } prime_numbers } fn main() { let prime_numbers = prepare_prime_numbers(); let guard = pprof::ProfilerGuard::new(100).unwrap(); let mut v = 0; for i in 2..5000000 { if i % 4 == 0 { if is_prime_number1(i, &prime_numbers) { v += 1; } } else if i % 4 == 1 { if is_prime_number2(i, &prime_numbers) { v += 1; } } else if is_prime_number3(i, &prime_numbers) { v += 1; } } println!("Prime numbers: {}", v); if let Ok(report) = guard.report().build() { let mut file = File::create("profile.pb").unwrap(); let profile = report.pprof().unwrap(); let mut content = Vec::new(); profile.write_to_vec(&mut content).unwrap(); file.write_all(&content).unwrap(); println!("report: {:?}", report); }; } pprof-0.13.0/proto/perftools.profiles.rs000064400000000000000000000236541046102023000164150ustar 00000000000000// f9f855b960d01b292a3c2642e263e6156d52631e78e0177fe51416ed5bbecc81 proto/profile.proto #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Profile { /// A description of the samples associated with each Sample.value. /// For a cpu profile this might be: /// \[["cpu","nanoseconds"]\] or \[["wall","seconds"]\] or \[["syscall","count"]\] /// For a heap profile, this might be: /// \[["allocations","count"\], \["space","bytes"]\], /// If one of the values represents the number of events represented /// by the sample, by convention it should be at index 0 and use /// sample_type.unit == "count". #[prost(message, repeated, tag = "1")] pub sample_type: ::prost::alloc::vec::Vec, /// The set of samples recorded in this profile. #[prost(message, repeated, tag = "2")] pub sample: ::prost::alloc::vec::Vec, /// Mapping from address ranges to the image/binary/library mapped /// into that address range. mapping\[0\] will be the main binary. #[prost(message, repeated, tag = "3")] pub mapping: ::prost::alloc::vec::Vec, /// Useful program location #[prost(message, repeated, tag = "4")] pub location: ::prost::alloc::vec::Vec, /// Functions referenced by locations #[prost(message, repeated, tag = "5")] pub function: ::prost::alloc::vec::Vec, /// A common table for strings referenced by various messages. /// string_table\[0\] must always be "". #[prost(string, repeated, tag = "6")] pub string_table: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, /// frames with Function.function_name fully matching the following /// regexp will be dropped from the samples, along with their successors. /// /// Index into string table. #[prost(int64, tag = "7")] pub drop_frames: i64, /// frames with Function.function_name fully matching the following /// regexp will be kept, even if it matches drop_functions. /// /// Index into string table. #[prost(int64, tag = "8")] pub keep_frames: i64, /// Time of collection (UTC) represented as nanoseconds past the epoch. #[prost(int64, tag = "9")] pub time_nanos: i64, /// Duration of the profile, if a duration makes sense. #[prost(int64, tag = "10")] pub duration_nanos: i64, /// The kind of events between sampled ocurrences. /// e.g \[ "cpu","cycles" \] or \[ "heap","bytes" \] #[prost(message, optional, tag = "11")] pub period_type: ::core::option::Option, /// The number of events between sampled occurrences. #[prost(int64, tag = "12")] pub period: i64, /// Freeform text associated to the profile. /// /// Indices into string table. #[prost(int64, repeated, tag = "13")] pub comment: ::prost::alloc::vec::Vec, /// Index into the string table of the type of the preferred sample /// value. If unset, clients should default to the last sample value. #[prost(int64, tag = "14")] pub default_sample_type: i64, } /// ValueType describes the semantics and measurement units of a value. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ValueType { /// Rename it from type to ty to avoid using keyword in Rust. /// /// Index into string table. #[prost(int64, tag = "1")] pub ty: i64, /// Index into string table. #[prost(int64, tag = "2")] pub unit: i64, } /// Each Sample records values encountered in some program /// context. The program context is typically a stack trace, perhaps /// augmented with auxiliary information like the thread-id, some /// indicator of a higher level request being handled etc. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Sample { /// The ids recorded here correspond to a Profile.location.id. /// The leaf is at location_id\[0\]. #[prost(uint64, repeated, tag = "1")] pub location_id: ::prost::alloc::vec::Vec, /// The type and unit of each value is defined by the corresponding /// entry in Profile.sample_type. All samples must have the same /// number of values, the same as the length of Profile.sample_type. /// When aggregating multiple samples into a single sample, the /// result has a list of values that is the elemntwise sum of the /// lists of the originals. #[prost(int64, repeated, tag = "2")] pub value: ::prost::alloc::vec::Vec, /// label includes additional context for this sample. It can include /// things like a thread id, allocation size, etc #[prost(message, repeated, tag = "3")] pub label: ::prost::alloc::vec::Vec