diff --git a/Cargo.lock b/Cargo.lock index d7b89de..fa76003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "aho-corasick" version = "1.1.5" @@ -26,6 +41,18 @@ dependencies = [ "libc", ] +[[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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + [[package]] name = "antlr4rust" version = "0.5.2" @@ -55,7 +82,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73cd58deff2140a0a8eae87e417bd01db68a33e148aa93d1e8cd837e55e312b6" dependencies = [ - "object", + "object 0.39.1", ] [[package]] @@ -107,7 +134,7 @@ dependencies = [ "futures-core", "libc", "portable-atomic", - "rustc-hash", + "rustc-hash 2.1.3", "rustix", "tokio", "tokio-stream", @@ -246,6 +273,21 @@ dependencies = [ "fastrand", ] +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.37.3", + "rustc-demangle", + "windows-link", +] + [[package]] name = "base64" version = "0.22.1" @@ -427,6 +469,12 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.4.3" @@ -566,6 +614,58 @@ dependencies = [ "phf", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + [[package]] name = "cmake" version = "0.1.58" @@ -647,6 +747,40 @@ dependencies = [ "libc", ] +[[package]] +name = "criterion" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +dependencies = [ + "cast", + "itertools 0.13.0", +] + [[package]] name = "crossbeam-channel" version = "0.5.16" @@ -656,6 +790,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.20" @@ -671,6 +815,12 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -802,6 +952,22 @@ dependencies = [ "serde_core", ] +[[package]] +name = "dhat" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cd11d84628e233de0ce467de10b8633f4ddaecafadefc86e13b84b8739b827" +dependencies = [ + "backtrace", + "lazy_static", + "mintex", + "parking_lot", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "thousands", +] + [[package]] name = "digest" version = "0.10.7" @@ -1142,6 +1308,12 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + [[package]] name = "globset" version = "0.4.20" @@ -1173,6 +1345,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1522,6 +1705,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1830,6 +2022,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mintex" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c505b3e17ed6b70a7ed2e67fbb2c560ee327353556120d6e72f5232b6880d536" + [[package]] name = "mio" version = "1.2.2" @@ -2044,6 +2251,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "object" version = "0.39.1" @@ -2059,6 +2275,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "openssl-probe" version = "0.2.1" @@ -2246,6 +2468,34 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "portable-atomic" version = "1.15.0" @@ -2288,6 +2538,23 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppe-benches" +version = "0.1.0" +dependencies = [ + "async-trait", + "criterion", + "dhat", + "praxis-policy-apl-core", + "praxis-policy-apl-runtime", + "praxis-policy-core", + "praxis-policy-pdp-cedar-direct", + "praxis-policy-pdp-cel", + "praxis-policy-pdp-opa", + "serde_yaml", + "tokio", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -2707,6 +2974,26 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redis" version = "1.6.0" @@ -2859,6 +3146,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.3" @@ -3438,6 +3737,12 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "time" version = "0.3.55" @@ -3478,6 +3783,16 @@ dependencies = [ "zerovec", ] +[[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 = "tinyvec" version = "1.12.0" @@ -3894,6 +4209,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index d01cc00..b3bf968 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,10 @@ members = [ # why it is not a builtin. "reference/plugins/pii-scanner", "reference/plugins/audit-logger", + # Criterion suite for issue #19. Unpublished; excluded from default-members + # so everyday `cargo build` stays lean. `cargo bench -p ppe-benches` / + # `make bench` still pick it up, and `clippy --all-targets` compiles it. + "crates/ppe-benches", ] # The session store pulls a redis client and a TLS stack, which slows a default @@ -133,6 +137,10 @@ praxis-policy-pdp-cel = { path = "builtins/pdps/cel", praxis-policy-pdp-opa = { path = "builtins/pdps/opa", version = "0.1.0" } praxis-policy-session-valkey = { path = "builtins/session/valkey", version = "0.1.0" } +# Criterion is only consumed by the unpublished `ppe-benches` crate (issue #19). +# Kept in the workspace table so version bumps stay one-line. +criterion = { version = "0.7", features = ["html_reports", "async_tokio"] } + # Cross-crate inlining and dead-code elimination, one codegen unit for # optimization quality. # diff --git a/Makefile b/Makefile index c2d366a..8d32a0e 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,11 @@ help: @echo "Test:" @echo " test Run all workspace tests" @echo "" + @echo "Benchmarks (on demand — not part of make ci; see docs/benchmarks.md):" + @echo " bench Criterion suite (ppe-benches / issue #19)" + @echo " bench-percentiles p50/p95/p99 from target/criterion samples" + @echo " bench-heap dhat per-decision + policy-size footprint" + @echo "" @echo "Supply chain & coverage:" @echo " audit cargo deny check (advisories, licenses, bans, sources)" @echo " coverage Coverage summary, gated at COVERAGE_FLOOR percent" @@ -55,6 +60,8 @@ help: @echo "" @echo "CI:" @echo " ci What CI runs: lint + test" + @echo " (benches compile via clippy --all-targets;" + @echo " make bench is on-demand — docs/benchmarks.md)" @echo "" @echo "Release:" @echo " release-dry Preview a release (no changes)" @@ -149,6 +156,29 @@ test: @$(CARGO) test --workspace @$(CARGO) test --workspace --all-features +# ============================================================================= +# Benchmarks (issue #19) — on demand, never part of `make ci` +# ============================================================================= +# +# Wall-clock benches do not gate PRs: CI runners are noisy and a flaky +# p99 gate would train people to ignore failures. Clippy --all-targets +# still *compiles* the suite so bitrot is caught. See docs/benchmarks.md. + +.PHONY: bench +bench: + @echo "Criterion suite (ppe-benches) — on demand, not a CI gate ..." + @$(CARGO) bench -p ppe-benches + @echo "HTML reports under target/criterion/; write-up in docs/benchmarks.md" + +.PHONY: bench-percentiles +bench-percentiles: + @python3 tools/bench_percentiles.py + +.PHONY: bench-heap +bench-heap: + @echo "dhat heap_profile (per-decision + policy-size) ..." + @$(CARGO) bench -p ppe-benches --features dhat-heap --bench heap_profile + # ============================================================================= # Supply chain & coverage # ============================================================================= diff --git a/crates/ppe-benches/Cargo.toml b/crates/ppe-benches/Cargo.toml new file mode 100644 index 0000000..7db6539 --- /dev/null +++ b/crates/ppe-benches/Cargo.toml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 Praxis Contributors + +# ppe-benches — Criterion microbenchmarks for the Praxis Policy Engine +# (https://github.com/praxis-proxy/policy/issues/19). +# +# Unpublished on purpose: measurement harness, not a library. +# +# Run: +# make bench +# cargo bench -p ppe-benches --bench full_decision +# +# Profiles (on demand, not part of `make ci`): +# cargo flamegraph -p ppe-benches --bench full_decision +# cargo bench -p ppe-benches --features dhat-heap --bench memory + +[package] +name = "ppe-benches" +description = "Criterion benchmarks for the Praxis Policy Engine (issue #19)." +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +repository.workspace = true +rust-version.workspace = true +publish = false + +[dependencies] +praxis-policy-core = { workspace = true } +praxis-policy-apl-core = { workspace = true } +praxis-policy-apl-runtime = { workspace = true } +praxis-policy-pdp-cedar-direct = { workspace = true } +praxis-policy-pdp-cel = { workspace = true } +praxis-policy-pdp-opa = { workspace = true } +async-trait = { workspace = true } +serde_yaml = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "sync", "time"] } +dhat = { version = "0.3", optional = true } + +[dev-dependencies] +criterion = { workspace = true } + +[features] +dhat-heap = ["dep:dhat"] + +[lints] +workspace = true + +[[bench]] +name = "hook_overhead" +harness = false + +[[bench]] +name = "full_decision" +harness = false + +[[bench]] +name = "throughput" +harness = false + +[[bench]] +name = "pdp_cost" +harness = false + +[[bench]] +name = "memory" +harness = false + +[[bench]] +name = "heap_profile" +harness = false +required-features = ["dhat-heap"] diff --git a/crates/ppe-benches/benches/full_decision.rs b/crates/ppe-benches/benches/full_decision.rs new file mode 100644 index 0000000..625aea3 --- /dev/null +++ b/crates/ppe-benches/benches/full_decision.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Full-decision latency (issue #19 — Time: full decision + eval vs dispatch). +//! +//! | Fixture | Path | +//! |----------------------|-------------------------------------------| +//! | `plugin_only` | APL route → `plugin(noop)` | +//! | `cedar_only` | APL route → `cedar:` PDP step | +//! | `plugin_then_cedar` | APL → plugin then Cedar (operator shape) | +//! +//! Flamegraph: `cargo flamegraph -p ppe-benches --bench full_decision` + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + reason = "benchmark harness — Criterion macros + fixture expects" +)] + +use std::hint::black_box; +use std::time::Duration; + +use criterion::{Criterion, criterion_group, criterion_main}; +use ppe_benches::{ + YAML_CEDAR_ONLY, YAML_PLUGIN_ONLY, YAML_PLUGIN_THEN_CEDAR, engine_from_yaml, extensions_reader, + invoke_once, +}; +use tokio::runtime::Runtime; + +fn full_decision(c: &mut Criterion) { + let rt = Runtime::new().expect("tokio runtime"); + let mut group = c.benchmark_group("full_decision"); + group + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(5)) + .sample_size(80); + + let (plugin_only, _) = rt.block_on(engine_from_yaml(YAML_PLUGIN_ONLY, None)); + group.bench_function("plugin_only", |b| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&plugin_only, extensions_reader()).await); + }); + }); + + let (cedar_only, _) = rt.block_on(engine_from_yaml(YAML_CEDAR_ONLY, None)); + group.bench_function("cedar_only", |b| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&cedar_only, extensions_reader()).await); + }); + }); + + let (full, _) = rt.block_on(engine_from_yaml(YAML_PLUGIN_THEN_CEDAR, None)); + group.bench_function("plugin_then_cedar", |b| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&full, extensions_reader()).await); + }); + }); + + group.finish(); +} + +criterion_group!(benches, full_decision); +criterion_main!(benches); diff --git a/crates/ppe-benches/benches/heap_profile.rs b/crates/ppe-benches/benches/heap_profile.rs new file mode 100644 index 0000000..c6268de --- /dev/null +++ b/crates/ppe-benches/benches/heap_profile.rs @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Isolated heap measurements (issue #19 — Memory). +//! +//! Unlike the Criterion `memory` target, this binary runs a **fixed** number of +//! decisions under `dhat` so totals are attributable: +//! +//! - **per-decision** — `total_bytes / N` after N hot-path invokes (setup outside) +//! - **policy-size footprint** — `max_bytes` after load + one decide for 1/10/50 +//! Cedar policies +//! +//! ```bash +//! cargo bench -p ppe-benches --features dhat-heap --bench heap_profile +//! ``` + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::print_stdout, + clippy::print_stderr, + reason = "heap profile harness — prints findings for docs/benchmarks.md" +)] + +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + +use std::sync::Arc; + +use ppe_benches::{ + YAML_PLUGIN_THEN_CEDAR, engine_from_yaml, extensions_reader, extensions_with_session, + invoke_once, yaml_cedar_policy_count, +}; +use tokio::runtime::Runtime; + +const PER_DECISION_ITERS: usize = 500; + +fn main() { + let rt = Runtime::new().expect("tokio runtime"); + + println!("ppe-benches heap_profile (dhat-heap)"); + println!("--- per-decision allocation ---"); + { + let _profiler = dhat::Profiler::new_heap(); + let (mgr, _) = rt.block_on(engine_from_yaml(YAML_PLUGIN_THEN_CEDAR, None)); + let before = dhat::HeapStats::get(); + for _ in 0..PER_DECISION_ITERS { + rt.block_on(invoke_once(&mgr, extensions_with_session("bench-sess"))); + } + let after = dhat::HeapStats::get(); + let delta = after.total_bytes.saturating_sub(before.total_bytes); + let per = delta / PER_DECISION_ITERS as u64; + println!( + "iters={PER_DECISION_ITERS} delta_total_bytes={delta} per_decision_bytes≈{per} peak_max_bytes={}", + after.max_bytes + ); + } + + println!("--- policy-size footprint (load + 1 decide) ---"); + for &n_policies in &[1_usize, 10, 50] { + let _profiler = dhat::Profiler::new_heap(); + let yaml = yaml_cedar_policy_count(n_policies); + let (mgr, _) = rt.block_on(engine_from_yaml(&yaml, None)); + rt.block_on(invoke_once(&mgr, extensions_reader())); + let stats = dhat::HeapStats::get(); + println!( + "policies={n_policies} total_bytes={} max_bytes={} curr_bytes={}", + stats.total_bytes, stats.max_bytes, stats.curr_bytes + ); + // Keep engine alive until after stats read. + let _keep = Arc::clone(&mgr); + } + + println!("dhat-heap.json written on profiler drop (see docs/benchmarks.md)"); +} diff --git a/crates/ppe-benches/benches/hook_overhead.rs b/crates/ppe-benches/benches/hook_overhead.rs new file mode 100644 index 0000000..4c1ecb8 --- /dev/null +++ b/crates/ppe-benches/benches/hook_overhead.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Hook / plugin-dispatch overhead (issue #19 — Time: plugin dispatch). +//! +//! Isolates the executor path with **no APL visitor and no PDP**: +//! `register_handler_for_names` → `invoke_named` → N no-op `HookHandler`s. + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + reason = "benchmark harness — Criterion macros + fixture expects" +)] + +use std::hint::black_box; +use std::time::Duration; + +use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use ppe_benches::{ + HOOK_TOOL_PRE, cmf_payload, engine_plugins_only, extensions_reader, invoke_once, +}; +use praxis_policy_core::cmf::CmfHook; +use praxis_policy_core::plugin::PluginMode; +use tokio::runtime::Runtime; + +fn hook_overhead(c: &mut Criterion) { + let rt = Runtime::new().expect("tokio runtime"); + let mut group = c.benchmark_group("hook_overhead"); + group + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(3)) + .sample_size(100); + + for &n in &[1_usize, 4, 16] { + let mgr = rt.block_on(engine_plugins_only(n, PluginMode::Sequential)); + group.throughput(Throughput::Elements(n as u64)); + group.bench_with_input(BenchmarkId::new("sequential", n), &n, |b, _| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&mgr, extensions_reader()).await); + }); + }); + + let mgr_c = rt.block_on(engine_plugins_only(n, PluginMode::Concurrent)); + group.bench_with_input(BenchmarkId::new("concurrent", n), &n, |b, _| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&mgr_c, extensions_reader()).await); + }); + }); + } + + // Reset throughput so empty_registry is not reported as Elements(16). + group.throughput(Throughput::Elements(1)); + let empty = rt.block_on(engine_plugins_only(0, PluginMode::Sequential)); + group.bench_function("empty_registry", |b| { + b.to_async(&rt).iter(|| async { + let (result, _bg) = empty + .invoke_named::( + HOOK_TOOL_PRE, + cmf_payload("bench"), + extensions_reader(), + None, + ) + .await; + black_box(result.continue_processing); + }); + }); + + group.finish(); +} + +criterion_group!(benches, hook_overhead); +criterion_main!(benches); diff --git a/crates/ppe-benches/benches/memory.rs b/crates/ppe-benches/benches/memory.rs new file mode 100644 index 0000000..626cab1 --- /dev/null +++ b/crates/ppe-benches/benches/memory.rs @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Memory / session-taint growth (issue #19 — Memory). +//! +//! 1. **`SessionStore` curve** — `append_labels` / `load_labels` as label +//! set and session count grow (session taint sticks across requests). +//! 2. **Policy-size sweep** — full decision latency as Cedar policy count grows. +//! 3. **Optional dhat** — `cargo bench -p ppe-benches --features dhat-heap +//! --bench memory` writes `dhat-heap.json`. See `docs/benchmarks.md`. +//! For isolated per-decision / policy-size heap numbers use +//! `--bench heap_profile` (requires `dhat-heap`). + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + reason = "benchmark harness — Criterion macros + fixture expects" +)] +#![cfg_attr(feature = "dhat-heap", allow(dead_code))] + +#[cfg(feature = "dhat-heap")] +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + +use std::hint::black_box; +use std::sync::Arc; +use std::time::Duration; + +use criterion::{BatchSize, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use ppe_benches::{ + YAML_PLUGIN_THEN_CEDAR, engine_from_yaml, extensions_reader, extensions_with_session, + invoke_once, yaml_cedar_policy_count, +}; +use praxis_policy_apl_runtime::{MemorySessionStore, SessionStore as _}; +use tokio::runtime::Runtime; + +fn seed_store(rt: &Runtime, n_labels: usize) -> Arc { + let store = Arc::new(MemorySessionStore::new()); + let seed: Vec = (0..n_labels).map(|i| format!("L{i}")).collect(); + rt.block_on(async { + store + .append_labels("sess-taint", &seed) + .await + .expect("seed"); + }); + store +} + +fn memory(c: &mut Criterion) { + #[cfg(feature = "dhat-heap")] + let _profiler = dhat::Profiler::new_heap(); + + let rt = Runtime::new().expect("tokio runtime"); + let mut group = c.benchmark_group("memory"); + group + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(4)) + .sample_size(60); + + for &n_labels in &[8_usize, 64, 512] { + let store = seed_store(&rt, n_labels); + group.throughput(Throughput::Elements(n_labels as u64)); + group.bench_with_input( + BenchmarkId::new("session_load_labels", n_labels), + &n_labels, + |b, _| { + let store = Arc::clone(&store); + b.to_async(&rt).iter(|| async { + let labels = store.load_labels("sess-taint").await.expect("load"); + black_box(labels.len()); + }); + }, + ); + + // Reseed to exactly `n_labels` every iteration so the starting size is + // stable (unique-append on a shared store would swamp 8/64/512). + // Use sync `iter_batched` (not `to_async`) so setup can `block_on` + // without nesting inside Criterion's async runtime. + group.throughput(Throughput::Elements(1)); + group.bench_with_input( + BenchmarkId::new("session_append_one", n_labels), + &n_labels, + |b, &n| { + b.iter_batched( + || seed_store(&rt, n), + |store| { + rt.block_on(async { + store + .append_labels("sess-taint", &["EXTRA".to_owned()]) + .await + .expect("append"); + black_box(store); + }); + }, + BatchSize::SmallInput, + ); + }, + ); + } + + for &n_sessions in &[10_usize, 100, 1000] { + let store = Arc::new(MemorySessionStore::new()); + rt.block_on(async { + for i in 0..n_sessions { + let sid = format!("s{i}"); + store + .append_labels(&sid, &["PII".to_owned(), "INTERNAL".to_owned()]) + .await + .expect("seed session"); + } + }); + group.throughput(Throughput::Elements(n_sessions as u64)); + group.bench_with_input( + BenchmarkId::new("session_snapshot", n_sessions), + &n_sessions, + |b, _| { + let store = Arc::clone(&store); + b.iter(|| { + let snap = store.snapshot(); + black_box(snap.len()); + }); + }, + ); + } + + // Reset so this single-decision bench is not reported as Elements(1000). + group.throughput(Throughput::Elements(1)); + let (mgr, _store) = rt.block_on(engine_from_yaml(YAML_PLUGIN_THEN_CEDAR, None)); + group.bench_function("full_decision_with_session_id", |b| { + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&mgr, extensions_with_session("bench-sess")).await); + }); + }); + + // Policy-size sweep: decision latency as Cedar rule count grows (ticket: + // footprint / cost vs policy size). Heap bytes for the same sweep live in + // `--bench heap_profile`. + for &n_policies in &[1_usize, 10, 50] { + let yaml = yaml_cedar_policy_count(n_policies); + let (mgr, _) = rt.block_on(engine_from_yaml(&yaml, None)); + group.throughput(Throughput::Elements(1)); + group.bench_with_input( + BenchmarkId::new("policy_size_decision", n_policies), + &n_policies, + |b, _| { + let mgr = Arc::clone(&mgr); + b.to_async(&rt).iter(|| async { + black_box(invoke_once(&mgr, extensions_reader()).await); + }); + }, + ); + } + + group.finish(); +} + +criterion_group!(benches, memory); +criterion_main!(benches); diff --git a/crates/ppe-benches/benches/pdp_cost.rs b/crates/ppe-benches/benches/pdp_cost.rs new file mode 100644 index 0000000..8fcb10a --- /dev/null +++ b/crates/ppe-benches/benches/pdp_cost.rs @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Per-PDP evaluation cost (issue #19 — Cedar / CEL / OPA separately). +//! +//! Compiles / loads each resolver **once** in setup. Timed loop is only +//! `PdpResolver::evaluate`. + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + reason = "benchmark harness — Criterion macros + fixture expects" +)] + +use std::hint::black_box; +use std::sync::Arc; +use std::time::Duration; + +use criterion::{Criterion, criterion_group, criterion_main}; +use praxis_policy_apl_core::attributes::AttributeBag; +use praxis_policy_apl_core::evaluator::Decision; +use praxis_policy_apl_core::step::{PdpCall, PdpDialect, PdpResolver as _}; +use praxis_policy_pdp_cedar_direct::CedarDirectResolver; +use praxis_policy_pdp_cel::CelResolver; +use praxis_policy_pdp_opa::OpaResolver; +use tokio::runtime::Runtime; + +/// Fail loud in setup if a fixture times a deny path (same idea as `invoke_once`). +fn assert_allow(label: &str, d: &praxis_policy_apl_core::step::PdpDecision) { + assert!( + matches!(d.decision, Decision::Allow), + "{label} fixture must allow; got {:?}", + d.decision + ); +} + +fn cedar_call() -> PdpCall { + PdpCall { + dialect: PdpDialect::Cedar, + args: serde_yaml::from_str( + r#" +action: 'Action::"read"' +resource: + type: Document + id: doc-1 +"#, + ) + .expect("cedar args"), + } +} + +fn cel_call(expr: &str) -> PdpCall { + let mut m = serde_yaml::Mapping::new(); + m.insert( + serde_yaml::Value::String("expr".into()), + serde_yaml::Value::String(expr.into()), + ); + PdpCall { + dialect: PdpDialect::Cel, + args: serde_yaml::Value::Mapping(m), + } +} + +fn opa_call(query: &str) -> PdpCall { + let mut m = serde_yaml::Mapping::new(); + m.insert( + serde_yaml::Value::String("query".into()), + serde_yaml::Value::String(query.into()), + ); + PdpCall { + dialect: PdpDialect::Opa, + args: serde_yaml::Value::Mapping(m), + } +} + +fn reader_bag() -> AttributeBag { + let mut bag = AttributeBag::new(); + bag.set("subject.id", "alice"); + bag.set("subject.type", "User"); + bag.set("role.reader", true); + bag +} + +fn pdp_cost(c: &mut Criterion) { + let rt = Runtime::new().expect("tokio runtime"); + let mut group = c.benchmark_group("pdp_cost"); + group + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(4)) + .sample_size(100); + + const CEDAR_POLICY: &str = r#" + @id("reader-permit") + permit(principal, action == Action::"read", resource) + when { principal.roles.contains("reader") }; + "#; + let cedar = + Arc::new(CedarDirectResolver::from_policy_text(CEDAR_POLICY).expect("cedar compile")); + let cedar_args = cedar_call(); + let bag = reader_bag(); + { + let d = rt + .block_on(cedar.evaluate(&cedar_args, &bag)) + .expect("cedar setup"); + assert_allow("cedar_evaluate", &d); + } + group.bench_function("cedar_evaluate", |b| { + b.to_async(&rt).iter(|| async { + let d = cedar + .evaluate(black_box(&cedar_args), black_box(&bag)) + .await + .expect("cedar eval"); + black_box(d); + }); + }); + + let cel = Arc::new(CelResolver::new()); + let cel_args = cel_call("subject.id == 'alice'"); + { + let d = rt + .block_on(cel.evaluate(&cel_args, &bag)) + .expect("cel setup"); + assert_allow("cel_evaluate", &d); + } + group.bench_function("cel_evaluate", |b| { + b.to_async(&rt).iter(|| async { + let d = cel + .evaluate(black_box(&cel_args), black_box(&bag)) + .await + .expect("cel eval"); + black_box(d); + }); + }); + + const OPA_MODULE: &str = r#"package authz +default allow := false +allow if input.subject.id == "alice" +"#; + let mut opa_cfg = serde_yaml::Mapping::new(); + opa_cfg.insert( + serde_yaml::Value::String("kind".into()), + serde_yaml::Value::String("opa".into()), + ); + opa_cfg.insert( + serde_yaml::Value::String("modules".into()), + serde_yaml::Value::Sequence(vec![serde_yaml::Value::String(OPA_MODULE.into())]), + ); + let opa = + Arc::new(OpaResolver::from_config(&serde_yaml::Value::Mapping(opa_cfg)).expect("opa load")); + let opa_args = opa_call("data.authz.allow"); + { + let d = rt + .block_on(opa.evaluate(&opa_args, &bag)) + .expect("opa setup"); + assert_allow("opa_evaluate", &d); + } + group.bench_function("opa_evaluate", |b| { + b.to_async(&rt).iter(|| async { + let d = opa + .evaluate(black_box(&opa_args), black_box(&bag)) + .await + .expect("opa eval"); + black_box(d); + }); + }); + + group.finish(); +} + +criterion_group!(benches, pdp_cost); +criterion_main!(benches); diff --git a/crates/ppe-benches/benches/throughput.rs b/crates/ppe-benches/benches/throughput.rs new file mode 100644 index 0000000..688d640 --- /dev/null +++ b/crates/ppe-benches/benches/throughput.rs @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Throughput under concurrency (issue #19 — Throughput). +//! +//! Decisions/sec with many Tokio tasks calling `invoke_named`, including +//! YAML `mode: concurrent`. + +#![allow( + missing_docs, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + reason = "benchmark harness — Criterion macros + fixture expects" +)] + +use std::hint::black_box; +use std::sync::Arc; +use std::time::Duration; + +use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use ppe_benches::{ + YAML_CONCURRENT_PLUGINS, YAML_PLUGIN_THEN_CEDAR, engine_from_yaml, engine_plugins_only, + extensions_reader, invoke_once, +}; +use praxis_policy_core::engine::PolicyEngine; +use praxis_policy_core::plugin::PluginMode; +use tokio::runtime::Runtime; + +async fn burst(mgr: Arc, tasks: usize) { + let mut joins = Vec::with_capacity(tasks); + for _ in 0..tasks { + let m = Arc::clone(&mgr); + joins.push(tokio::spawn(async move { + black_box(invoke_once(&m, extensions_reader()).await); + })); + } + for j in joins { + j.await.expect("task join"); + } +} + +fn throughput(c: &mut Criterion) { + let rt = Runtime::new().expect("tokio runtime"); + let mut group = c.benchmark_group("throughput"); + group + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(5)) + .sample_size(40); + + for &tasks in &[8_usize, 32, 128] { + group.throughput(Throughput::Elements(tasks as u64)); + + let seq = rt.block_on(engine_plugins_only(4, PluginMode::Sequential)); + group.bench_with_input( + BenchmarkId::new("plugins_sequential", tasks), + &tasks, + |b, &t| { + b.to_async(&rt).iter(|| async { + burst(Arc::clone(&seq), t).await; + }); + }, + ); + + let conc = rt.block_on(engine_plugins_only(4, PluginMode::Concurrent)); + group.bench_with_input( + BenchmarkId::new("plugins_concurrent_mode", tasks), + &tasks, + |b, &t| { + b.to_async(&rt).iter(|| async { + burst(Arc::clone(&conc), t).await; + }); + }, + ); + + let (full, _) = rt.block_on(engine_from_yaml(YAML_PLUGIN_THEN_CEDAR, None)); + group.bench_with_input( + BenchmarkId::new("apl_plugin_then_cedar", tasks), + &tasks, + |b, &t| { + b.to_async(&rt).iter(|| async { + burst(Arc::clone(&full), t).await; + }); + }, + ); + + let (yaml_conc, _) = rt.block_on(engine_from_yaml(YAML_CONCURRENT_PLUGINS, None)); + group.bench_with_input( + BenchmarkId::new("apl_yaml_mode_concurrent", tasks), + &tasks, + |b, &t| { + b.to_async(&rt).iter(|| async { + burst(Arc::clone(&yaml_conc), t).await; + }); + }, + ); + } + + group.finish(); +} + +criterion_group!(benches, throughput); +criterion_main!(benches); diff --git a/crates/ppe-benches/src/lib.rs b/crates/ppe-benches/src/lib.rs new file mode 100644 index 0000000..e6a0a63 --- /dev/null +++ b/crates/ppe-benches/src/lib.rs @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 Praxis Contributors + +//! Shared fixtures for the Criterion suite (issue #19). +//! +//! Setup (YAML load, Cedar compile, plugin factory registration) runs +//! **outside** Criterion iters. Timed loops only call the hot path: +//! [`PolicyEngine::invoke_named`], `PdpResolver::evaluate`, or +//! `SessionStore` ops. +//! +//! Patterns mirror `visitor_e2e` / `visitor_pdp_config` so the benches +//! exercise the same wiring operators use in production. + +#![allow( + missing_docs, + trivial_casts, + clippy::expect_used, + clippy::unwrap_used, + clippy::panic, + clippy::indexing_slicing, + clippy::needless_raw_string_hashes, + reason = "benchmark harness — panics surface misconfiguration immediately" +)] + +use std::collections::HashSet; +use std::sync::Arc; + +use async_trait::async_trait; + +use praxis_policy_apl_runtime::{AplOptions, DispatchCache, MemorySessionStore, register_apl}; +use praxis_policy_core::cmf::enums::Role; +use praxis_policy_core::cmf::{CmfHook, Message, MessagePayload}; +use praxis_policy_core::context::PluginContext; +use praxis_policy_core::engine::PolicyEngine; +use praxis_policy_core::error::PluginError as CoreError; +use praxis_policy_core::extensions::{ + AgentExtension, MetaExtension, SecurityExtension, SubjectExtension, SubjectType, +}; +use praxis_policy_core::factory::{PluginFactory, PluginInstance}; +use praxis_policy_core::hooks::adapter::TypedHandlerAdapter; +use praxis_policy_core::hooks::payload::Extensions; +use praxis_policy_core::hooks::trait_def::{HookHandler, PluginResult}; +use praxis_policy_core::plugin::{Plugin, PluginConfig, PluginMode}; +use praxis_policy_core::registry::AnyHookHandler; +use praxis_policy_pdp_cedar_direct::CedarDirectPdpFactory; + +/// Hook name used by every engine-level bench. Matches the CMF tool +/// pre-invocation phase Praxis hits on the request path. +pub const HOOK_TOOL_PRE: &str = "cmf.tool_pre_invoke"; + +/// Tool name baked into the fixture YAML routes. +pub const TOOL_NAME: &str = "get_document"; + +// ===================================================================== +// No-op plugin — zero work inside `handle`, so Criterion attributes +// wall time to the executor / registry path rather than plugin logic. +// ===================================================================== + +/// Pass-through plugin used to measure dispatch cost in isolation. +pub struct NoopPlugin { + cfg: PluginConfig, +} + +#[async_trait] +impl Plugin for NoopPlugin { + fn config(&self) -> &PluginConfig { + &self.cfg + } +} + +impl HookHandler for NoopPlugin { + async fn handle( + &self, + _payload: &MessagePayload, + _extensions: &Extensions, + _ctx: &mut PluginContext, + ) -> PluginResult { + PluginResult::allow() + } +} + +/// Factory for [`NoopPlugin`]. Kind string is `"noop"`. +pub struct NoopFactory; + +impl PluginFactory for NoopFactory { + fn create(&self, config: &PluginConfig) -> Result> { + let plugin = Arc::new(NoopPlugin { + cfg: config.clone(), + }); + let handlers = hooks_for(config, Arc::clone(&plugin)); + Ok(PluginInstance { plugin, handlers }) + } +} + +fn hooks_for( + config: &PluginConfig, + plugin: Arc, +) -> Vec<(&'static str, Arc)> { + // `PluginInstance` requires `&'static str` hook names. Bench fixtures only + // ever use `HOOK_TOOL_PRE`, so map to that constant instead of `Box::leak`. + let names: Vec<&'static str> = if config.hooks.is_empty() { + vec![HOOK_TOOL_PRE] + } else { + config + .hooks + .iter() + .map(|s| { + assert_eq!( + s.as_str(), + HOOK_TOOL_PRE, + "NoopFactory bench fixtures only support {HOOK_TOOL_PRE}" + ); + HOOK_TOOL_PRE + }) + .collect() + }; + names + .into_iter() + .map(|name| { + let adapter: Arc = + Arc::new(TypedHandlerAdapter::::new(Arc::clone(&plugin))); + (name, adapter) + }) + .collect() +} + +/// Build a [`PluginConfig`] for a no-op registered under `name`. +pub fn noop_config(name: &str, mode: PluginMode, priority: i32) -> PluginConfig { + PluginConfig { + name: name.to_owned(), + kind: "noop".to_owned(), + hooks: vec![HOOK_TOOL_PRE.to_owned()], + mode, + priority, + ..Default::default() + } +} + +// ===================================================================== +// Request fixtures +// ===================================================================== + +/// Minimal CMF text payload for tool-pre benches. +pub fn cmf_payload(text: &str) -> MessagePayload { + MessagePayload { + message: Message::text(Role::User, text), + } +} + +/// Route-matching meta for [`TOOL_NAME`]. +pub fn meta_for_tool(name: &str) -> MetaExtension { + MetaExtension { + entity_type: Some("tool".to_owned()), + entity_name: Some(name.to_owned()), + ..Default::default() + } +} + +/// Security subject with the given id and roles (Cedar / CEL bags lift these). +pub fn security_with_roles(id: &str, roles: &[&str]) -> SecurityExtension { + SecurityExtension { + subject: Some(SubjectExtension { + id: Some(id.to_owned()), + subject_type: Some(SubjectType::User), + roles: roles + .iter() + .map(|r| (*r).to_owned()) + .collect::>(), + ..Default::default() + }), + ..Default::default() + } +} + +/// Extensions for a Cedar-allowing reader hitting [`TOOL_NAME`]. +pub fn extensions_reader() -> Extensions { + Extensions { + meta: Some(Arc::new(meta_for_tool(TOOL_NAME))), + security: Some(Arc::new(security_with_roles("alice", &["reader"]))), + ..Default::default() + } +} + +/// Extensions with an agent `session_id` so APL session hydrate/persist runs. +pub fn extensions_with_session(session_id: &str) -> Extensions { + let mut ext = extensions_reader(); + ext.agent = Some(Arc::new(AgentExtension { + session_id: Some(session_id.to_owned()), + ..Default::default() + })); + ext +} + +// ===================================================================== +// Engine builders — all load/compile work is here (un-timed setup) +// ===================================================================== + +fn apl_options_with_cedar(session: Arc) -> AplOptions { + AplOptions { + dispatch_cache: Arc::new(DispatchCache::new()), + session_store: session, + pdps: Vec::new(), + pdp_factories: vec![Arc::new(CedarDirectPdpFactory::new())], + session_store_factories: Vec::new(), + base_capabilities: None, + } +} + +/// Engine with N no-op plugins on the hook, **no** APL visitor. +/// +/// Isolates plugin-executor overhead: registry lookup + mode scheduling + +/// `HookHandler::handle`. Used by `hook_overhead` and the concurrent +/// half of `throughput`. +/// +/// Registers via [`PolicyEngine::register_handler_for_names`] on +/// [`HOOK_TOOL_PRE`] (not `register_handler`, which would bind under +/// `CmfHook::NAME` = `"cmf"` and never run when we invoke the tool-pre hook). +/// +/// # Panics +/// +/// Panics if a handler fails to register, if `count` does not fit in `i32` +/// (bench sizes are tiny), if engine initialization fails, or if a registered +/// plugin is missing from the tool-pre hook (fixture guard). +pub async fn engine_plugins_only(count: usize, mode: PluginMode) -> Arc { + let mgr = Arc::new(PolicyEngine::default()); + for i in 0..count { + let name = format!("noop-{i}"); + let priority = i32::try_from(i).expect("bench plugin count fits i32"); + let cfg = noop_config(&name, mode, priority); + let plugin = Arc::new(NoopPlugin { cfg: cfg.clone() }); + mgr.register_handler_for_names::(plugin, cfg, &[HOOK_TOOL_PRE]) + .expect("register_handler_for_names"); + } + mgr.initialize().await.expect("initialize"); + // Guard: empty-registry early-return looks like a fast bench. Fail loud if + // plugins landed on the wrong hook name. + for i in 0..count { + let name = format!("noop-{i}"); + let entries = mgr.find_plugin_entries(&name); + assert_eq!( + entries.len(), + 1, + "{name}: expected one hook entry, got {} hooks {:?}", + entries.len(), + entries.iter().map(|(h, _)| h.as_str()).collect::>() + ); + assert_eq!( + entries[0].0.as_str(), + HOOK_TOOL_PRE, + "{name}: registered under {:?}, want {HOOK_TOOL_PRE}", + entries[0].0 + ); + } + mgr +} + +/// YAML: one Cedar PDP + one route with a `cedar:` step (no plugins). +pub const YAML_CEDAR_ONLY: &str = r#" +global: + apl: + pdp: + - kind: cedar-direct + policy_text: | + @id("reader-permit") + permit(principal, action == Action::"read", resource) + when { principal.roles.contains("reader") }; +routes: + - tool: get_document + apl: + pre_invocation: + - cedar: + action: 'Action::"read"' + resource: + type: Document + id: doc-42 +"#; + +/// YAML: noop plugin step only (APL path, no PDP) — plugin-via-APL cost. +pub const YAML_PLUGIN_ONLY: &str = r#" +plugins: + - name: noop-0 + kind: noop + hooks: [cmf.tool_pre_invoke] +routes: + - tool: get_document + apl: + pre_invocation: + - "plugin(noop-0)" +"#; + +/// YAML: plugin then Cedar — full decision path operators actually run. +pub const YAML_PLUGIN_THEN_CEDAR: &str = r#" +plugins: + - name: noop-0 + kind: noop + hooks: [cmf.tool_pre_invoke] +global: + apl: + pdp: + - kind: cedar-direct + policy_text: | + @id("reader-permit") + permit(principal, action == Action::"read", resource) + when { principal.roles.contains("reader") }; +routes: + - tool: get_document + apl: + pre_invocation: + - "plugin(noop-0)" + - cedar: + action: 'Action::"read"' + resource: + type: Document + id: doc-42 +"#; + +/// APL + Cedar YAML with `n_policies` Cedar rules (first matches `reader`). +/// +/// Used by memory benches to sweep **policy size** (compile/eval footprint). +/// +/// # Panics +/// +/// Panics if `n_policies` is zero. +pub fn yaml_cedar_policy_count(n_policies: usize) -> String { + assert!(n_policies > 0, "need at least one Cedar policy"); + let mut policy_text = String::from( + r#" + @id("reader-permit") + permit(principal, action == Action::"read", resource) + when { principal.roles.contains("reader") }; +"#, + ); + for i in 1..n_policies { + policy_text.push_str(&format!( + r#" + @id("filler-{i}") + permit(principal, action == Action::"read", resource) + when {{ principal.roles.contains("role-{i}") }}; +"# + )); + } + format!( + r#" +global: + apl: + pdp: + - kind: cedar-direct + policy_text: | +{policy_text} +routes: + - tool: get_document + apl: + pre_invocation: + - cedar: + action: 'Action::"read"' + resource: + type: Document + id: doc-42 +"# + ) +} + +/// YAML: several concurrent-mode plugins on an APL route. +pub const YAML_CONCURRENT_PLUGINS: &str = r#" +plugins: + - name: noop-0 + kind: noop + hooks: [cmf.tool_pre_invoke] + mode: concurrent + - name: noop-1 + kind: noop + hooks: [cmf.tool_pre_invoke] + mode: concurrent + - name: noop-2 + kind: noop + hooks: [cmf.tool_pre_invoke] + mode: concurrent + - name: noop-3 + kind: noop + hooks: [cmf.tool_pre_invoke] + mode: concurrent +routes: + - tool: get_document + apl: + pre_invocation: + - "plugin(noop-0)" + - "plugin(noop-1)" + - "plugin(noop-2)" + - "plugin(noop-3)" +"#; + +/// Load YAML, register noop + Cedar factories, initialize. +/// +/// Returns `(engine, session_store)` so memory benches can inspect taint. +/// +/// # Panics +/// +/// Panics if YAML fails to load or engine initialization fails. Bench +/// fixtures treat that as a broken harness rather than a soft error. +pub async fn engine_from_yaml( + yaml: &str, + session: Option>, +) -> (Arc, Arc) { + let session = session.unwrap_or_else(|| Arc::new(MemorySessionStore::new())); + let mgr = Arc::new(PolicyEngine::default()); + mgr.register_factory("noop", Box::new(NoopFactory)); + register_apl(&mgr, apl_options_with_cedar(Arc::clone(&session))); + mgr.load_config_yaml(yaml).expect("load_config_yaml"); + mgr.initialize().await.expect("initialize"); + (mgr, session) +} + +/// One `invoke_named` on the tool-pre hook (caller-supplied extensions). +/// +/// Returns `continue_processing` so callers can `black_box` a real value +/// (empty `black_box(())` does not pin work). +/// +/// # Panics +/// +/// Panics if the fixture denies. Criterion must not silently time a deny +/// path when the harness expected allow. +pub async fn invoke_once(mgr: &PolicyEngine, ext: Extensions) -> bool { + let (result, _bg) = mgr + .invoke_named::(HOOK_TOOL_PRE, cmf_payload("bench"), ext, None) + .await; + // Fail loud if a fixture drifts into deny — otherwise Criterion + // silently times the deny path and baselines become meaningless. + assert!( + result.continue_processing, + "fixture must allow; violation={:?}", + result.violation + ); + result.continue_processing +} diff --git a/docs/benchmarks.md b/docs/benchmarks.md new file mode 100644 index 0000000..de948ec --- /dev/null +++ b/docs/benchmarks.md @@ -0,0 +1,258 @@ +# Benchmark suite (issue [#19](https://github.com/praxis-proxy/policy/issues/19)) + +This document is the acceptance write-up for the Criterion suite under +`crates/ppe-benches/` (`ppe-benches`). It records **how to run**, **what each target +measures**, **CI policy**, and **baseline / profile** results. + +**Framework:** Criterion **0.7** (`html_reports`, `async_tokio`). + +## Framework choice + +**Criterion only** (with `async_tokio`). One framework keeps the suite +runnable and comparable over time; mixing Divan / iai / ad-hoc `Instant` +instrumentation on the request path was rejected for this ticket. + +## What is in scope + +The hot path is `PolicyEngine::invoke_named` (and, for PDP microbenches, +`PdpResolver::evaluate`). **Out of scope:** Praxis HTTP, Pingora, JWKS, +upstream I/O, Valkey. + +YAML parse, Cedar compile, and APL visitor annotation run in **setup**, +never inside Criterion iters. Compile cost matters at load, not per request. + +## Targets + +| Target | Ticket axis | What it isolates | +|--------|-------------|------------------| +| `hook_overhead` | Time — plugin dispatch | N no-op plugins, sequential + concurrent modes, no APL/PDP | +| `full_decision` | Time — full decision; eval vs dispatch | APL `plugin_only` / `cedar_only` / `plugin_then_cedar` | +| `throughput` | Throughput | Concurrent Tokio callers; YAML `mode: concurrent` | +| `pdp_cost` | Per-PDP cost | Cedar / CEL / OPA `evaluate` only | +| `memory` | Memory | Session taint; policy-size decision sweep; optional dhat | +| `heap_profile` | Memory (bytes) | Per-decision alloc + policy-size footprint (`dhat-heap`) | + +Criterion’s console/HTML report mean / median / slope. It does **not** print +p95/p99 by default. After a bench run, derive percentiles from samples: + +```bash +make bench-percentiles +# → python3 tools/bench_percentiles.py (reads target/criterion/**/new/sample.json) +``` + +## How to run + +```bash +# Full suite (on demand) +make bench +# equivalent: +cargo bench -p ppe-benches + +# One target +cargo bench -p ppe-benches --bench full_decision +cargo bench -p ppe-benches --bench pdp_cost + +# Percentiles for docs / review +make bench-percentiles + +# Heap bytes (requires dhat-heap) +make bench-heap +``` + +### CPU profile (flamegraph) + +```bash +# Linux with perf (not WSL2). Build with symbols, then profile the binary: +# CARGO_PROFILE_BENCH_DEBUG=1 RUSTFLAGS='-C force-frame-pointers=yes' +# cargo bench -p ppe-benches --bench full_decision --no-run +# Direct binary run needs --bench or Criterion stays in test mode: +BIN=target/release/deps/full_decision-* +perf record -g -F 99 -o perf.data -- \ + $BIN --bench cedar_only --warm-up-time 1 --measurement-time 8 --sample-size 25 +perf script | inferno-collapse-perf | inferno-flamegraph > flamegraph.svg +``` + +Artifact checked into the repo: +[`docs/flamegraph-full_decision-cedar_only.svg`](flamegraph-full_decision-cedar_only.svg) +(open in a browser). + +On hosts without `perf`, the Criterion differential table under **CPU profile +findings** remains a useful cross-check. + +### Memory profile (dhat) + +```bash +# Criterion memory target (optional allocator; wall-clock not comparable) +cargo bench -p ppe-benches --features dhat-heap --bench memory + +# Isolated per-decision + policy-size footprint (preferred for byte numbers) +make bench-heap +# → prints per_decision_bytes and max_bytes vs policy count; dhat-heap.json +``` + +`session_append_one` reseeds the store to exactly `n_labels` every iteration +(`iter_batched` setup) and reports `Throughput::Elements(1)`. + +## CI decision (acceptance criterion) + +| Question | Decision | +|----------|----------| +| Do benchmarks gate CI / PRs? | **No.** | +| Why? | Wall-clock p99 on shared runners is noise-dominated; a flaky gate trains people to ignore red CI. | +| What *does* CI do? | `clippy --all-targets` (via `make lint` / `make ci`) **compiles** every `[[bench]]` so the suite cannot bitrot. | +| Is `make bench` part of `make ci`? | **No.** Documented on-demand only. | +| If we ever gate later | Prefer a relative regression threshold ≥ **15–20%** on p50 (not p99) against a stored baseline on dedicated hardware — not default GitHub-hosted runners. | + +## Baseline numbers + +Captured locally on the hardware below. Do **not** treat GitHub-hosted CI +runners as a source of truth for these numbers. + +### Hardware (record when capturing) + +| Field | Value | +|-------|-------| +| Date | 2026-08-26 | +| Host | WSL2 (`C-PF4TF3ED`) | +| CPU | AMD Ryzen 7 PRO 7840HS (8c/16t) | +| Cores / threads | 8 / 16 | +| RAM | 30 GiB (WSL2) | +| OS | Linux 6.18 (WSL2 on Windows 10) | +| `rustc` | 1.96.0 (ac68faa20 2026-05-25) | +| Profile | Criterion default (release for benches) | + +> Re-run `make bench` on bare metal and replace this table if you need +> numbers for release notes — WSL2 adds scheduler noise. + +### Latency (p50 / p95 / p99) + +Derived with `tools/bench_percentiles.py` from Criterion `sample.json` +(`time_per_iter = sample_time / iters`). Means included for comparison. + +| Bench | p50 | p95 | p99 | mean | notes | +|-------|-----|-----|-----|------|-------| +| `hook_overhead/empty_registry` | 270 ns | 278 ns | 284 ns | 272 ns | floor: invoke with no plugins | +| `hook_overhead/sequential/1` | 1.04 µs | 1.11 µs | 1.16 µs | 1.06 µs | real plugin dispatch (fixed hook name) | +| `hook_overhead/sequential/4` | 2.88 µs | 3.01 µs | 3.23 µs | 2.90 µs | | +| `hook_overhead/sequential/16` | 8.48 µs | 8.95 µs | 9.11 µs | 8.55 µs | | +| `hook_overhead/concurrent/1` | 39.8 µs | 44.9 µs | 49.0 µs | 40.4 µs | concurrent-mode executor cost | +| `hook_overhead/concurrent/4` | 46.9 µs | 50.2 µs | 53.1 µs | 47.2 µs | | +| `hook_overhead/concurrent/16` | 70.7 µs | 73.5 µs | 77.3 µs | 70.5 µs | | +| `full_decision/plugin_only` | 5.75 µs | 6.03 µs | 6.29 µs | 5.78 µs | APL + noop plugin | +| `full_decision/cedar_only` | 57.5 µs | 59.1 µs | 63.3 µs | 57.6 µs | APL + Cedar | +| `full_decision/plugin_then_cedar` | 59.9 µs | 62.1 µs | 65.7 µs | 60.2 µs | operator shape | +| `pdp_cost/cel_evaluate` | 7.27 µs | 7.78 µs | 8.34 µs | 7.32 µs | `evaluate` only | +| `pdp_cost/cedar_evaluate` | 40.3 µs | 43.6 µs | 44.8 µs | 40.4 µs | | +| `pdp_cost/opa_evaluate` | 47.0 µs | 50.0 µs | 50.8 µs | 46.5 µs | | + +### Throughput + +32 concurrent Tokio callers per sample (Criterion `thrpt`). Percentiles are +**per burst** (not per single decision). + +| Bench | tasks | p50 / burst | p95 | p99 | elems/s (approx) | notes | +|-------|-------|-------------|-----|-----|------------------|-------| +| `throughput/plugins_concurrent_mode` | 32 | 148 µs | 153 µs | 156 µs | ~216 Kelem/s | plugins only, concurrent mode | +| `throughput/apl_yaml_mode_concurrent` | 32 | 241 µs | 314 µs | 352 µs | ~131 Kelem/s | YAML `mode: concurrent` | +| `throughput/apl_plugin_then_cedar` | 32 | 609 µs | 640 µs | 803 µs | ~52 Kelem/s | APL plugin → Cedar | + +### Memory / session + +| Bench | input | p50 (approx) | observation | +|-------|-------|--------------|-------------| +| `memory/session_load_labels` | 8 / 64 / 512 | 115 ns / 1.58 µs / 12.8 µs | scales with label cardinality | +| `memory/session_append_one` | 8 / 64 / 512 | ~0.46 / 2.1 / 16 µs (p50) | reseed to `n_labels` each iter; thrpt = 1 elem | +| `memory/session_snapshot` | 10 / 100 / 1000 | 844 ns / 10.6 µs / 115 µs | scales with session count | +| `memory/full_decision_with_session_id` | — | 88.4 µs (p50) | `YAML_PLUGIN_THEN_CEDAR` + session hydrate/persist | +| `memory/policy_size_decision` | 1 / 10 / 50 policies | 58.2 / 67.0 / 103 µs | decision latency vs Cedar rule count | + +### CPU profile findings (captured flamegraph) + +**Capture host (RHEL lab VM, 2026-08-26):** + +| Field | Value | +|-------|-------| +| Host | `rhel.mmv9t.sandbox694.opentlc.com` (OpenTLC RHEL 10) | +| CPU / RAM | 2 vCPU / 3.5 GiB | +| Kernel | 6.12.0-55.9.1.el10_0.x86_64 | +| Tool | `perf record -g -F 99` → `inferno-collapse-perf` → `inferno-flamegraph` | +| Case | `full_decision/cedar_only` (APL + Cedar allow path) | +| Binary | bench profile with `debug=1`, `strip=none`, frame pointers | +| Samples | 1889 (`perf.data`); SVG: `docs/flamegraph-full_decision-cedar_only.svg` | + +**How to read the SVG:** a large share of samples sits in Criterion/rayon +bootstrap worker threads (analysis after measurement). The **PPE hot path** +is the stack under `ppe_benches::invoke_once` / `PolicyEngine::invoke_named` +(~25% of process samples in this capture). Within that path: + +| Frame (approx share of process samples) | Role | +|-------------------------------------------|------| +| `PolicyEngine::invoke_named` → `Executor::execute` / `run_serial_phase` | Engine dispatch | +| `AplRouteHandler::invoke` → `evaluate_effects` | APL orchestration | +| `PdpRouter` / `CedarDirectResolver::evaluate` | PDP entry (~22%) | +| `cedar_direct::request::parse` | Request construction (~7%) | +| `cedar_direct::entities::build` / `build_principal` | Entity bag lift (~7%) | +| `cedar_policy` `Entity::from_json_value` / `Context::from_json_value` | Cedar JSON entity/context build | + +**Findings:** + +- On the APL+Cedar path, **time is dominated by Cedar evaluate and its + request/entity construction**, not by sequential no-op plugin dispatch. + Concurrent-mode plugin dispatch is a separate cost center (~40–70 µs). +- YAML parse / Cedar **policy compile** do not appear on the hot stacks + (they run in Criterion setup, outside timed iters) — matches the ticket. +- WSL Criterion differentials (below) agree once hook registration is fixed: + sequential PDP ≫ sequential dispatch; concurrent-mode dispatch is not free. + +**WSL cross-check (differentials, after hook-registration fix):** + +| Slice | Evidence | Finding | +|-------|----------|---------| +| Empty invoke | `hook_overhead/empty_registry` p50 ≈ 270 ns | Floor without plugins | +| Sequential dispatch | `sequential/1` ≈ 1.0 µs → `sequential/16` ≈ 8.5 µs | Real no-op handler cost; scales with N | +| Concurrent-mode dispatch | `concurrent/1` ≈ 40 µs → `concurrent/16` ≈ 71 µs | Concurrent executor path is far costlier than sequential | +| APL + plugin | `full_decision/plugin_only` p50 ≈ 5.8 µs vs `sequential/1` ≈ 1.0 µs | APL orchestration ≈ 4–5 µs over bare sequential dispatch | +| Cedar eval | `pdp_cost/cedar` p50 ≈ 40 µs vs `cedar_only` p50 ≈ 58 µs | PDP dominates; APL tax ≈ 18 µs on Cedar path | +| Session path | `full_decision_with_session_id` p50 ≈ 88 µs vs `plugin_then_cedar` ≈ 60 µs | Session hydrate/persist adds ~28 µs on this fixture | +| PDP ranking | CEL ≪ Cedar ≈ OPA | Dialect choice matters more than sequential dispatch | + +### Memory profile findings + +**Session-taint curve (Criterion):** + +- `load_labels` grows with label set size (~100× from 8 → 512). +- `snapshot` grows with session count (~100× from 10 → 1000). +- `session_append_one` keeps starting size fixed via per-iter reseed. + +**Policy size (Criterion latency):** decision p50 rises ~58 µs → ~103 µs as +Cedar policies go 1 → 50 (fillers do not match `reader`, but still participate +in evaluation work). + +**Per-decision allocation + policy-size footprint** (`make bench-heap`, +`dhat::HeapStats`, 2026-08-26): + +| Measurement | Result | +|-------------|--------| +| Per-decision (`delta_total_bytes / 500` after setup) | ≈ **209 KiB / decision** | +| Peak during that window (`max_bytes`) | ≈ 415 KiB | +| Policy count 1 — `max_bytes` / live `curr_bytes` | ≈ 127 KiB / ≈ 16 KiB | +| Policy count 10 — `max_bytes` / `curr_bytes` | ≈ 212 KiB / ≈ 47 KiB | +| Policy count 50 — `max_bytes` / `curr_bytes` | ≈ 608 KiB / ≈ 184 KiB | + +Notes: + +- Prefer `make bench-heap` over Criterion+dhat totals: fixed N, setup excluded + from the per-decision delta. +- `max_bytes` includes load transients; `curr_bytes` after load+one decide is + the steadier footprint signal as policy size grows. +- dhat slows wall-clock heavily — use it for **bytes**, not latency. + +## Mapping to ticket acceptance criteria + +| Acceptance criterion | Where it lives | +|----------------------|----------------| +| Suite under `crates/ppe-benches/` covering hook, full-decision, throughput, per-PDP | `hook_overhead`, `full_decision`, `throughput`, `pdp_cost` | +| `make bench` | `Makefile` target `bench` | +| Baseline numbers in `docs/` with hardware | this file (p50/p95/p99 via `bench-percentiles`) | +| CPU + memory profiles + findings | `docs/flamegraph-full_decision-cedar_only.svg` + findings; `make bench-heap` | +| CI gate decision (+ threshold if gating) | **CI decision** section — not gating; threshold guidance if revisited | diff --git a/docs/flamegraph-full_decision-cedar_only.svg b/docs/flamegraph-full_decision-cedar_only.svg new file mode 100644 index 0000000..ae029ff --- /dev/null +++ b/docs/flamegraph-full_decision-cedar_only.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch _int_malloc (171,717,170 samples, 0.90%)alloc_perturb (10,101,010 samples, 0.05%)malloc (20,202,020 samples, 0.11%)[unknown] (212,121,210 samples, 1.11%)unlink_chunk.isra.0 (10,101,010 samples, 0.05%)<criterion::html::Html as criterion::report::Report>::measurement_complete (30,303,030 samples, 0.16%)<criterion::plot::plotters_backend::PlottersBackend as criterion::plot::Plotter>::abs_distributions (30,303,030 samples, 0.16%)criterion::kde::sweep_and_estimate (30,303,030 samples, 0.16%)criterion::fs::save_string (10,101,010 samples, 0.05%)_RNvMs3_NtNtCs27Vx93FoQ6z_4core3ffi5c_strNtB5_4CStr19from_bytes_with_nul (10,101,010 samples, 0.05%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)core::ptr::drop_in_place<praxis_policy_core::engine::PolicyEngine::filter_entries_by_route::{{closure}}> (10,101,010 samples, 0.05%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)cfree@GLIBC_2.2.5 (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (10,101,010 samples, 0.05%)<hashbrown::raw::RawTable<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (10,101,010 samples, 0.05%)<hashbrown::raw::RawTable<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)core::ptr::drop_in_place<praxis_policy_core::cmf::message::MessagePayload> (10,101,010 samples, 0.05%)praxis_policy_apl_cmf::meta::extract_meta (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (20,202,020 samples, 0.11%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)praxis_policy_apl_cmf::extensions_bridge::extract_extensions (80,808,080 samples, 0.42%)praxis_policy_apl_cmf::security::extract_security (70,707,070 samples, 0.37%)praxis_policy_apl_core::attributes::AttributeBag::set (40,404,040 samples, 0.21%)hashbrown::map::HashMap<K,V,S,A>::insert (40,404,040 samples, 0.21%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)praxis_policy_apl_cmf::BagBuilder::with_extensions (90,909,090 samples, 0.48%)praxis_policy_apl_cmf::security::extract_security (10,101,010 samples, 0.05%)praxis_policy_apl_cmf::payload::walk (10,101,010 samples, 0.05%)praxis_policy_apl_core::attributes::AttributeBag::set (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h420ac23d91dd28c1E.llvm.10385711493366922269 (10,101,010 samples, 0.05%)<serde_yaml::value::Value as serde_yaml::mapping::Index>::index_into (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (30,303,030 samples, 0.16%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (30,303,030 samples, 0.16%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h64a1133888ad7af3E.llvm.8835512530113933511 (20,202,020 samples, 0.11%)alloc::sync::Arc<T,A>::drop_slow (20,202,020 samples, 0.11%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (20,202,020 samples, 0.11%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h64a1133888ad7af3E.llvm.8835512530113933511 (20,202,020 samples, 0.11%)_ZN4core3ptr61drop_in_place$LT$cedar_policy_core..ast..value..ValueKind$GT$17h1fdf38f9871f2523E.llvm.8835512530113933511 (20,202,020 samples, 0.11%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)<alloc::collections::btree::map::IntoIter<K,V,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)_ZN5alloc11collections5btree3map25IntoIter$LT$K$C$V$C$A$GT$10dying_next17h04c715a5c032a7c2E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)<cedar_policy::api::Diagnostics as core::convert::From<cedar_policy_core::authorizer::Diagnostics>>::from (10,101,010 samples, 0.05%)_ZN79_$LT$cedar_policy_core..ast..request..Request$u20$as$u20$core..clone..Clone$GT$5clone17h0f71457cab69a423E.llvm.14463344612793751328 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)_ZN4core3ptr59drop_in_place$LT$cedar_policy_core..ast..expr..ExprKind$GT$17h3f9a741a475a403bE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)_ZN4core3ptr59drop_in_place$LT$cedar_policy_core..ast..expr..ExprKind$GT$17h3f9a741a475a403bE.llvm.5249237883993513251 (10,101,010 samples, 0.05%)_ZN82_$LT$cedar_policy_core..ast..expr..Expr$LT$T$GT$$u20$as$u20$core..clone..Clone$GT$5clone17hd70e0f7a9913bbb4E.llvm.5249237883993513251 (10,101,010 samples, 0.05%)cedar_policy_core::ast::policy::TemplateBody::condition (20,202,020 samples, 0.11%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)<cedar_policy_core::ast::value::ValueKind as core::cmp::PartialEq>::eq (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::<impl cedar_policy_core::ast::value::Value>::get_as_bool (10,101,010 samples, 0.05%)cedar_policy_core::ast::request::EntityUIDEntry::evaluate (10,101,010 samples, 0.05%)cedar_policy_core::ast::value::Value::new (10,101,010 samples, 0.05%)_ZN9hashbrown3map28HashMap$LT$K$C$V$C$S$C$A$GT$3get17h0057d34b00b2a79cE.llvm.5249237883993513251 (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hc208704170eaf16aE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (80,808,080 samples, 0.42%)cedar_policy_core::evaluator::Evaluator::partial_interpret (60,606,060 samples, 0.32%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (60,606,060 samples, 0.32%)cedar_policy_core::evaluator::Evaluator::partial_interpret (40,404,040 samples, 0.21%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (40,404,040 samples, 0.21%)cedar_policy_core::ast::entity::Entity::get (30,303,030 samples, 0.16%)cedar_policy_core::authorizer::Authorizer::is_authorized_core (131,313,130 samples, 0.69%)cedar_policy_core::evaluator::Evaluator::partial_evaluate (121,212,120 samples, 0.64%)cedar_policy_core::evaluator::Evaluator::partial_interpret (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::Evaluator::partial_interpret (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::Evaluator::partial_interpret (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::binary_relation (10,101,010 samples, 0.05%)cedar_policy_core::authorizer::partial_response::<impl core::convert::From<cedar_policy_core::authorizer::partial_response::PartialResponse> for cedar_policy_core::authorizer::Response>::from (10,101,010 samples, 0.05%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::fold (10,101,010 samples, 0.05%)<cedar_policy_core::ast::policy::Template as core::convert::From<cedar_policy_core::ast::policy::TemplateBody>>::from (10,101,010 samples, 0.05%)<cedar_policy_core::ast::expr_iterator::ExprIterator<T> as core::iter::traits::iterator::Iterator>::next (10,101,010 samples, 0.05%)cedar_policy::api::Authorizer::is_authorized (171,717,170 samples, 0.90%)cedar_policy_core::authorizer::Authorizer::is_authorized (151,515,150 samples, 0.79%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)memcpy@GLIBC_2.2.5 (20,202,020 samples, 0.11%)_RNvNtCsgW8esjfipvk_5alloc4sync32arcinner_layout_for_value_layout (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Cache::new (80,808,080 samples, 0.42%)regex_automata::hybrid::dfa::Lazy::init_cache (80,808,080 samples, 0.42%)regex_automata::hybrid::dfa::Lazy::set_transition (20,202,020 samples, 0.11%)lalrpop_util::lexer::MatcherBuilder::matcher (101,010,100 samples, 0.53%)regex_automata::hybrid::dfa::Lazy::cache_start_group (20,202,020 samples, 0.11%)regex_automata::util::determinize::epsilon_closure (20,202,020 samples, 0.11%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_realloc (10,101,010 samples, 0.05%)_ZN17cedar_policy_core6parser11text_to_cst7grammar14__parse__Ident8__reduce17hfecdb1ac6f40c7deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ident::__token_to_integer (10,101,010 samples, 0.05%)core::ptr::drop_in_place<lalrpop_util::state_machine::Parser<cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__StateMachine,lalrpop_util::lexer::Matcher<cedar_policy_core::parser::node::Node<alloc::string::String>>>> (10,101,010 samples, 0.05%)core::ptr::drop_in_place<regex_automata::hybrid::dfa::Cache> (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)regex_automata::util::determinize::add_nfa_states (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::decision::translate (202,020,200 samples, 1.06%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (202,020,200 samples, 1.06%)_ZN102_$LT$core..iter..adapters..map..Map$LT$I$C$F$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h959bb1abe41b3641E.llvm.10572370534696548218 (202,020,200 samples, 1.06%)cedar_policy::api::Policy::annotation (202,020,200 samples, 1.06%)<cedar_policy_core::ast::id::AnyId as core::str::traits::FromStr>::from_str (202,020,200 samples, 1.06%)cedar_policy_core::parser::text_to_cst::parse_ident (191,919,190 samples, 1.01%)lalrpop_util::state_machine::Parser<D,I>::drive (90,909,090 samples, 0.48%)lalrpop_util::state_machine::Parser<D,I>::next_token (60,606,060 samples, 0.32%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (60,606,060 samples, 0.32%)regex_automata::hybrid::dfa::Lazy::cache_next_state (60,606,060 samples, 0.32%)regex_automata::util::determinize::next (40,404,040 samples, 0.21%)regex_automata::util::determinize::state::Repr::iter_nfa_state_ids (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (20,202,020 samples, 0.11%)cedar_policy_core::entities::update_entity_map (10,101,010 samples, 0.05%)hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S,A>>::rustc_entry (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)_ZN9hashbrown3raw13RawTableInner22fallible_with_capacity17h2125c44b3490aa5bE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)<smol_str::SmolStr as core::cmp::PartialEq>::eq (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::get (20,202,020 samples, 0.11%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h5a1008851f4d3509E.llvm.8307836539513240890 (10,101,010 samples, 0.05%)cedar_policy_core::transitive_closure::cyclic_tc_internal (40,404,040 samples, 0.21%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)cedar_policy_core::entities::Entities::from_entities (90,909,090 samples, 0.48%)cedar_policy_core::transitive_closure::compute_tc (80,808,080 samples, 0.42%)hashbrown::map::HashMap<K,V,S,A>::contains_key (10,101,010 samples, 0.05%)indexmap::inner::Core<K,V>::insert_full (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)_ZN4core3ptr59drop_in_place$LT$cedar_policy_core..ast..expr..ExprKind$GT$17h5fed20512a434df2E.llvm.8666744525983102236 (20,202,020 samples, 0.11%)cedar_policy_core::ast::partial_value::split (10,101,010 samples, 0.05%)cedar_policy_core::ast::value::Value::record (10,101,010 samples, 0.05%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)<alloc::collections::btree::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (10,101,010 samples, 0.05%)<alloc::collections::btree::set::BTreeSet<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (10,101,010 samples, 0.05%)alloc::collections::btree::map::BTreeMap<K,V,A>::bulk_build_from_sorted_iter (10,101,010 samples, 0.05%)alloc::collections::btree::append::<impl alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Owned,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::bulk_push (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)__memset_avx2_unaligned (10,101,010 samples, 0.05%)cedar_policy_core::ast::value::Value::set (40,404,040 samples, 0.21%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (20,202,020 samples, 0.11%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (111,111,110 samples, 0.58%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (111,111,110 samples, 0.58%)_ZN17cedar_policy_core3ast6entity6Entity3new28_$u7b$$u7b$closure$u7d$$u7d$17h036f6018522162a4E.llvm.8666744525983102236 (111,111,110 samples, 0.58%)cedar_policy_core::evaluator::RestrictedEvaluator::partial_interpret (80,808,080 samples, 0.42%)psm::stack_pointer (10,101,010 samples, 0.05%)cedar_policy_core::ast::entity::Entity::new (141,414,140 samples, 0.74%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (141,414,140 samples, 0.74%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::EntityUidJson<C>::into_euid (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::<impl core::convert::TryFrom<cedar_policy_core::entities::json::value::TypeAndId> for cedar_policy_core::ast::entity::EntityUID>::try_from (10,101,010 samples, 0.05%)<cedar_policy_core::ast::name::Name as cedar_policy_core::from_normalized_str::FromNormalizedStr>::from_normalized_str (10,101,010 samples, 0.05%)_ZN14regex_automata4meta5regex5Regex11search_half17h630915ade6198269E.llvm.6869977330162537939 (10,101,010 samples, 0.05%)<regex_automata::meta::strategy::Core as regex_automata::meta::strategy::Strategy>::search_half (10,101,010 samples, 0.05%)regex_automata::hybrid::search::find_fwd (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (10,101,010 samples, 0.05%)<serde_core::de::impls::<impl serde_core::de::Deserialize for alloc::vec::Vec<T>>::deserialize::VecVisitor<T> as serde_core::de::Visitor>::visit_seq (20,202,020 samples, 0.11%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (30,303,030 samples, 0.16%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (40,404,040 samples, 0.21%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (40,404,040 samples, 0.21%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (40,404,040 samples, 0.21%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (40,404,040 samples, 0.21%)serde_json::error::make_error (30,303,030 samples, 0.16%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)_ZN4core3ptr45drop_in_place$LT$serde_json..error..Error$GT$17hc16fcf3bdcf687daE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (30,303,030 samples, 0.16%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)realloc (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc13___rdl_realloc (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (101,010,100 samples, 0.53%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (101,010,100 samples, 0.53%)serde_json::error::make_error (60,606,060 samples, 0.32%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (111,111,110 samples, 0.58%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (10,101,010 samples, 0.05%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)<serde_json::value::de::MapDeserializer as serde_core::de::MapAccess>::size_hint (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as serde_core::de::Deserialize>::deserialize (242,424,240 samples, 1.27%)serde_json::value::de::visit_array (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_seq (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (20,202,020 samples, 0.11%)cedar_policy_core::ast::restricted_expr::RestrictedExpr::record (20,202,020 samples, 0.11%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_core::de::Unexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (101,010,100 samples, 0.53%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (90,909,090 samples, 0.48%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (90,909,090 samples, 0.48%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (60,606,060 samples, 0.32%)memcpy@GLIBC_2.2.5 (30,303,030 samples, 0.16%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_core::de::Unexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (30,303,030 samples, 0.16%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (30,303,030 samples, 0.16%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (50,505,050 samples, 0.26%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (40,404,040 samples, 0.21%)serde_json::error::make_error (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (70,707,070 samples, 0.37%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::custom (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::FnAndArgs>::deserialize (101,010,100 samples, 0.53%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_core::de::impls::<impl serde_core::de::Deserialize for alloc::vec::Vec<T>>::deserialize::VecVisitor<T> as serde_core::de::Visitor>::visit_seq (20,202,020 samples, 0.11%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)serde_json::error::make_error (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (40,404,040 samples, 0.21%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<T as serde_core::de::Expected>::fmt (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde_core::de::Unexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (60,606,060 samples, 0.32%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (60,606,060 samples, 0.32%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (50,505,050 samples, 0.26%)serde_json::error::make_error (30,303,030 samples, 0.16%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (10,101,010 samples, 0.05%)core::ptr::drop_in_place<core::result::Result<cedar_policy_core::entities::json::value::RawCedarValueJson,serde_json::error::Error>> (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::ExtnValueJson>::deserialize (383,838,380 samples, 2.01%)c..cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (161,616,160 samples, 0.85%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::ValueParser::val_into_restricted_expr (676,767,670 samples, 3.55%)ceda..core::ptr::drop_in_place<cedar_policy_core::entities::json::value::CedarValueJson> (20,202,020 samples, 0.11%)_ZN5alloc11collections5btree3map25IntoIter$LT$K$C$V$C$A$GT$10dying_next17h54621d82914c0c5fE.llvm.8835512530113933511 (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::parse_ejson (909,090,900 samples, 4.76%)cedar_..core::iter::adapters::try_process (737,373,730 samples, 3.86%)core..<std::collections::hash::map::HashMap<K,V,S> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (717,171,710 samples, 3.76%)<std..<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (707,070,700 samples, 3.71%)<cor..hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)_ZN9hashbrown3raw13RawTableInner22fallible_with_capacity17h779d3d56f9603f08E.llvm.10365004940126427080 (10,101,010 samples, 0.05%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<<cedar_policy_core::jsonvalue::JsonValueWithNoDuplicateKeys as serde_core::de::Deserialize>::deserialize::ValueVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)<cedar_policy_core::jsonvalue::JsonValueWithNoDuplicateKeys as serde_core::de::Deserialize>::deserialize (30,303,030 samples, 0.16%)serde_json::value::de::visit_array (20,202,020 samples, 0.11%)<<cedar_policy_core::jsonvalue::JsonValueWithNoDuplicateKeys as serde_core::de::Deserialize>::deserialize::ValueVisitor as serde_core::de::Visitor>::visit_seq (20,202,020 samples, 0.11%)<cedar_policy_core::jsonvalue::JsonValueWithNoDuplicateKeys as serde_core::de::Deserialize>::deserialize (10,101,010 samples, 0.05%)<<cedar_policy_core::entities::json::entities::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::entities::EntityJson>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::__DeserializeWith as serde_core::de::Deserialize>::deserialize (70,707,070 samples, 0.37%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (60,606,060 samples, 0.32%)hashbrown::map::HashMap<K,V,S,A>::insert (30,303,030 samples, 0.16%)core::hash::BuildHasher::hash_one (30,303,030 samples, 0.16%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h2f29aacac4f1e349E.llvm.15443442747573432051 (20,202,020 samples, 0.11%)_ZN4core3ptr45drop_in_place$LT$serde_json..error..Error$GT$17hacad68ad97111e28E.llvm.11396761931918974021 (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (30,303,030 samples, 0.16%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17he8c6c663606d3805E.llvm.8666744525983102236 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)cedar_policy::api::Entity::from_json_value (1,030,303,020 samples, 5.40%)cedar_p..cedar_policy_core::entities::json::entities::EntityJsonParser<S>::single_from_json_value (1,030,303,020 samples, 5.40%)cedar_p..serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::value::Value>::deserialize_struct (121,212,120 samples, 0.64%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (121,212,120 samples, 0.64%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::EntityUidJson<Context>>::deserialize (40,404,040 samples, 0.21%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (30,303,030 samples, 0.16%)indexmap::inner::Core<K,V>::insert_full (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::entities::collect_prefixed_bools (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::entities::build_principal (1,131,313,120 samples, 5.93%)praxis_p..serde_core::ser::Serializer::collect_seq (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::EntityUidJson<C>::into_euid (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::<impl core::convert::TryFrom<cedar_policy_core::entities::json::value::TypeAndId> for cedar_policy_core::ast::entity::EntityUID>::try_from (10,101,010 samples, 0.05%)<cedar_policy_core::ast::name::Name as cedar_policy_core::from_normalized_str::FromNormalizedStr>::from_normalized_str (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::parse_ejson (20,202,020 samples, 0.11%)core::iter::adapters::try_process (10,101,010 samples, 0.05%)realloc (10,101,010 samples, 0.05%)cedar_policy::api::Entity::from_json_value (50,505,050 samples, 0.26%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::single_from_json_value (50,505,050 samples, 0.26%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::value::Value>::deserialize_struct (30,303,030 samples, 0.16%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (20,202,020 samples, 0.11%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::EntityUidJson<Context>>::deserialize (20,202,020 samples, 0.11%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17he8c6c663606d3805E.llvm.8666744525983102236 (20,202,020 samples, 0.11%)serde_json::error::make_error (10,101,010 samples, 0.05%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::entities::build (1,333,333,320 samples, 6.99%)praxis_po..praxis_policy_pdp_cedar_direct::entities::build_resource (70,707,070 samples, 0.37%)core::ptr::drop_in_place<serde_yaml::value::Value> (10,101,010 samples, 0.05%)_RNvMNtCs27Vx93FoQ6z_4core3stre12escape_debug (10,101,010 samples, 0.05%)_RNvNtNtCs27Vx93FoQ6z_4core7unicode9printable12is_printable (10,101,010 samples, 0.05%)<cedar_policy_core::ast::entity::EntityUID as core::fmt::Display>::fmt (20,202,020 samples, 0.11%)smol_str::from_buf_and_chars (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Ref>>>::to_ref (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Name>>>::to_internal_name (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Ident>>>::to_valid_ident (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (20,202,020 samples, 0.11%)alloc::raw_vec::RawVec<T,A>::grow_one (10,101,010 samples, 0.05%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17hce8fbab3cd285942E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc13___rdl_realloc (10,101,010 samples, 0.05%)core::ptr::drop_in_place<lalrpop_util::state_machine::Parser<cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__StateMachine,lalrpop_util::lexer::Matcher<cedar_policy_core::parser::node::Node<alloc::string::String>>>> (10,101,010 samples, 0.05%)core::ptr::drop_in_place<regex_automata::hybrid::dfa::Cache> (10,101,010 samples, 0.05%)__memset_avx2_unaligned_erms (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Cache::new (90,909,090 samples, 0.48%)regex_automata::hybrid::dfa::Lazy::init_cache (80,808,080 samples, 0.42%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)regex_automata::util::determinize::add_nfa_states (10,101,010 samples, 0.05%)lalrpop_util::lexer::MatcherBuilder::matcher (111,111,110 samples, 0.58%)regex_automata::hybrid::dfa::Lazy::cache_start_group (20,202,020 samples, 0.11%)regex_automata::util::determinize::epsilon_closure (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (30,303,030 samples, 0.16%)hashbrown::raw::RawTable<T,A>::reserve_rehash (20,202,020 samples, 0.11%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (20,202,020 samples, 0.11%)regex_automata::util::determinize::add_nfa_states (10,101,010 samples, 0.05%)regex_automata::util::determinize::epsilon_closure (10,101,010 samples, 0.05%)lalrpop_util::state_machine::Parser<D,I>::next_token (171,717,170 samples, 0.90%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (161,616,160 samples, 0.85%)regex_automata::hybrid::dfa::Lazy::cache_next_state (151,515,150 samples, 0.79%)regex_automata::util::determinize::next (90,909,090 samples, 0.48%)regex_automata::util::determinize::state::Repr::iter_nfa_state_ids (20,202,020 samples, 0.11%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce220 (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__action477 (10,101,010 samples, 0.05%)smol_str::Repr::new (10,101,010 samples, 0.05%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (404,040,400 samples, 2.12%)<..cedar_policy_core::from_normalized_str::default_from_normalized_str (404,040,400 samples, 2.12%)c..<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (383,838,380 samples, 2.01%)<..cedar_policy_core::parser::text_to_cst::parse_ref (373,737,370 samples, 1.96%)c..cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (353,535,350 samples, 1.85%)c..lalrpop_util::state_machine::Parser<D,I>::parse_eof (40,404,040 samples, 0.21%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce (40,404,040 samples, 0.21%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)<serde_json::value::ser::Serializer as serde_core::ser::Serializer>::serialize_seq (10,101,010 samples, 0.05%)cedar_policy_core::ast::request::Context::from_expr (10,101,010 samples, 0.05%)_ZN5alloc11collections5btree3map25IntoIter$LT$K$C$V$C$A$GT$10dying_next17h8118688be40f9ef6E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_ZN4core3ptr59drop_in_place$LT$cedar_policy_core..ast..expr..ExprKind$GT$17h3f9a741a475a403bE.llvm.8835512530113933511 (20,202,020 samples, 0.11%)_ZN4core3ptr55drop_in_place$LT$cedar_policy_core..ast..expr..Expr$GT$17h16d26b7f2756ca6bE.llvm.10555582910338593950 (40,404,040 samples, 0.21%)alloc::sync::Arc<T,A>::drop_slow (40,404,040 samples, 0.21%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (40,404,040 samples, 0.21%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h319bb81dbf8e892fE.llvm.8835512530113933511 (30,303,030 samples, 0.16%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h319bb81dbf8e892fE.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_ZN4core3ptr59drop_in_place$LT$cedar_policy_core..ast..expr..ExprKind$GT$17h3f9a741a475a403bE.llvm.8835512530113933511 (10,101,010 samples, 0.05%)<alloc::collections::btree::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (10,101,010 samples, 0.05%)cedar_policy_core::ast::value::Value::record (20,202,020 samples, 0.11%)alloc::vec::in_place_collect::<impl alloc::vec::spec_from_iter::SpecFromIter<T,I> for alloc::vec::Vec<T>>::from_iter (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)core::iter::adapters::try_process (70,707,070 samples, 0.37%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (70,707,070 samples, 0.37%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (60,606,060 samples, 0.32%)cedar_policy_core::evaluator::RestrictedEvaluator::partial_interpret (50,505,050 samples, 0.26%)core::iter::adapters::try_process (30,303,030 samples, 0.16%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (30,303,030 samples, 0.16%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (30,303,030 samples, 0.16%)cedar_policy_core::evaluator::RestrictedEvaluator::partial_interpret (30,303,030 samples, 0.16%)cedar_policy_core::ast::partial_value::split (10,101,010 samples, 0.05%)cedar_policy_core::ast::request::Context::from_expr (90,909,090 samples, 0.48%)cedar_policy_core::evaluator::RestrictedEvaluator::partial_interpret (80,808,080 samples, 0.42%)psm::stack_pointer (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (20,202,020 samples, 0.11%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (20,202,020 samples, 0.11%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (50,505,050 samples, 0.26%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (50,505,050 samples, 0.26%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (50,505,050 samples, 0.26%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (50,505,050 samples, 0.26%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (50,505,050 samples, 0.26%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (50,505,050 samples, 0.26%)alloc::collections::btree::append::<impl alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Owned,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::bulk_push (30,303,030 samples, 0.16%)cfree@GLIBC_2.2.5 (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<T as serde_core::de::Expected>::fmt (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (40,404,040 samples, 0.21%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (40,404,040 samples, 0.21%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (40,404,040 samples, 0.21%)serde_json::error::make_error (20,202,020 samples, 0.11%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (30,303,030 samples, 0.16%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (30,303,030 samples, 0.16%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (30,303,030 samples, 0.16%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (30,303,030 samples, 0.16%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (10,101,010 samples, 0.05%)<serde_core::de::impls::<impl serde_core::de::Deserialize for alloc::vec::Vec<T>>::deserialize::VecVisitor<T> as serde_core::de::Visitor>::visit_seq (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (40,404,040 samples, 0.21%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (40,404,040 samples, 0.21%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (40,404,040 samples, 0.21%)serde_json::error::make_error (30,303,030 samples, 0.16%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (30,303,030 samples, 0.16%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (80,808,080 samples, 0.42%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (70,707,070 samples, 0.37%)core::ptr::drop_in_place<core::result::Result<cedar_policy_core::entities::json::value::RawCedarValueJson,serde_json::error::Error>> (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (90,909,090 samples, 0.48%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (161,616,160 samples, 0.85%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (151,515,150 samples, 0.79%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (141,414,140 samples, 0.74%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as serde_core::de::Deserialize>::deserialize (262,626,260 samples, 1.38%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)cedar_policy_core::ast::restricted_expr::RestrictedExpr::record (10,101,010 samples, 0.05%)alloc::collections::btree::map::entry::VacantEntry<K,V,A>::insert_entry (10,101,010 samples, 0.05%)cedar_policy_core::ast::restricted_expr::RestrictedExpr::record (10,101,010 samples, 0.05%)core::iter::adapters::try_process (40,404,040 samples, 0.21%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (40,404,040 samples, 0.21%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (40,404,040 samples, 0.21%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (20,202,020 samples, 0.11%)core::iter::adapters::try_process (10,101,010 samples, 0.05%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::try_fold (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (90,909,090 samples, 0.48%)core::iter::adapters::try_process (70,707,070 samples, 0.37%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (70,707,070 samples, 0.37%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (60,606,060 samples, 0.32%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (60,606,060 samples, 0.32%)core::ptr::drop_in_place<cedar_policy_core::entities::json::value::CedarValueJson> (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (20,202,020 samples, 0.11%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (20,202,020 samples, 0.11%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (20,202,020 samples, 0.11%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (20,202,020 samples, 0.11%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (40,404,040 samples, 0.21%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (30,303,030 samples, 0.16%)alloc::collections::btree::append::<impl alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Owned,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::bulk_push (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::FnAndArgs>::deserialize (40,404,040 samples, 0.21%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (20,202,020 samples, 0.11%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.12012472642644115024 (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.12012472642644115024 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<serde_core::de::Unexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.12012472642644115024 (10,101,010 samples, 0.05%)_ZN4core3ptr58drop_in_place$LT$serde_core..private..content..Content$GT$17h2e2317bc8d0e332bE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc13___rdl_realloc (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (10,101,010 samples, 0.05%)<serde_core::de::impls::<impl serde_core::de::Deserialize for alloc::vec::Vec<T>>::deserialize::VecVisitor<T> as serde_core::de::Visitor>::visit_seq (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_realloc (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (20,202,020 samples, 0.11%)<serde_core::de::Unexpected as core::fmt::Display>::fmt (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)_RNvXsh_NtCs27Vx93FoQ6z_4core3fmteNtB5_5Debug3fmt (20,202,020 samples, 0.11%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (40,404,040 samples, 0.21%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (30,303,030 samples, 0.16%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str (10,101,010 samples, 0.05%)_RINvNvMs2_NtCsgW8esjfipvk_5alloc7raw_vecINtB8_11RawVecInnerpE7reserve21do_reserve_and_handleNtNtBa_5alloc6GlobalEBa_ (10,101,010 samples, 0.05%)_RNvMs4_NtCsgW8esjfipvk_5alloc7raw_vecNtB5_11RawVecInner11finish_growB7_ (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc13___rdl_realloc (10,101,010 samples, 0.05%)malloc (10,101,010 samples, 0.05%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (121,212,120 samples, 0.64%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (111,111,110 samples, 0.58%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (101,010,100 samples, 0.53%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (101,010,100 samples, 0.53%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (101,010,100 samples, 0.53%)serde_json::error::make_error (30,303,030 samples, 0.16%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (141,414,140 samples, 0.74%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)_RNvXs4_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core5clone5Clone5clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (232,323,230 samples, 1.22%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (222,222,220 samples, 1.16%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (202,020,200 samples, 1.06%)serde::private::de::content::content_clone (20,202,020 samples, 0.11%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (20,202,020 samples, 0.11%)serde::private::de::content::content_clone (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc11___rdl_alloc (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (292,929,290 samples, 1.54%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::ExtnValueJson>::deserialize (414,141,410 samples, 2.17%)c..serde_json::value::de::MapDeserializer::new (10,101,010 samples, 0.05%)cfree@GLIBC_2.2.5 (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::ValueParser::val_into_restricted_expr (787,878,780 samples, 4.13%)ceda..core::ptr::drop_in_place<cedar_policy_core::entities::json::value::CedarValueJson> (10,101,010 samples, 0.05%)_ZN4core3ptr145drop_in_place$LT$alloc..collections..btree..map..IntoIter$LT$smol_str..SmolStr$C$cedar_policy_core..entities..json..value..CedarValueJson$GT$$GT$17h0649be8810001275E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_ZN4core3ptr77drop_in_place$LT$cedar_policy_core..entities..json..value..CedarValueJson$GT$17ha6095b70977314bdE.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_ZN4core3ptr145drop_in_place$LT$alloc..collections..btree..map..IntoIter$LT$smol_str..SmolStr$C$cedar_policy_core..entities..json..value..CedarValueJson$GT$$GT$17h0649be8810001275E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_ZN4core3ptr77drop_in_place$LT$cedar_policy_core..entities..json..value..CedarValueJson$GT$17ha6095b70977314bdE.llvm.8835512530113933511 (10,101,010 samples, 0.05%)cedar_policy::api::Context::from_json_value (949,494,940 samples, 4.98%)cedar_..cedar_policy_core::entities::json::context::ContextJsonParser<S>::from_json_value (939,393,930 samples, 4.92%)cedar_..core::ptr::drop_in_place<cedar_policy_core::entities::json::value::CedarValueJson> (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h5a1008851f4d3509E.llvm.13136002666651947288 (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)indexmap::inner::Core<K,V>::insert_full (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::request::parse (1,424,242,410 samples, 7.46%)praxis_pol..indexmap::map::IndexMap<K,V,S>::get (30,303,030 samples, 0.16%)core::hash::BuildHasher::hash_one (30,303,030 samples, 0.16%)<serde_yaml::value::Value as core::hash::Hash>::hash (30,303,030 samples, 0.16%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h8095a3496a814443E.llvm.17787308842342542977 (10,101,010 samples, 0.05%)<smol_str::SmolStr as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<cedar_policy_core::ast::entity::EntityUID as core::fmt::Display>::fmt (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<cedar_policy_core::ast::id::AnyId as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce118 (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__action422 (10,101,010 samples, 0.05%)core::ptr::drop_in_place<lalrpop_util::state_machine::Parser<cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__StateMachine,lalrpop_util::lexer::Matcher<cedar_policy_core::parser::node::Node<alloc::string::String>>>> (10,101,010 samples, 0.05%)core::ptr::drop_in_place<regex_automata::hybrid::dfa::Cache> (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::init_cache (40,404,040 samples, 0.21%)regex_automata::hybrid::dfa::Lazy::set_transition (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Cache::new (60,606,060 samples, 0.32%)regex_automata::util::sparse_set::SparseSets::new (20,202,020 samples, 0.11%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)_RNvMs3_NtCsgW8esjfipvk_5alloc7raw_vecINtB5_6RawVechE8grow_oneB7_ (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::cache_start_group (30,303,030 samples, 0.16%)regex_automata::util::determinize::epsilon_closure (20,202,020 samples, 0.11%)lalrpop_util::lexer::MatcherBuilder::matcher (111,111,110 samples, 0.58%)regex_automata::util::determinize::set_lookbehind_from_start (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (30,303,030 samples, 0.16%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)regex_automata::util::determinize::add_nfa_states (10,101,010 samples, 0.05%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (131,313,130 samples, 0.69%)regex_automata::hybrid::dfa::Lazy::cache_next_state (111,111,110 samples, 0.58%)regex_automata::util::determinize::next (60,606,060 samples, 0.32%)regex_automata::util::determinize::state::Repr::iter_nfa_state_ids (20,202,020 samples, 0.11%)lalrpop_util::state_machine::Parser<D,I>::next_token (151,515,150 samples, 0.79%)regex_automata::hybrid::dfa::Lazy::cache_next_state (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::parse_ref (303,030,300 samples, 1.59%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (303,030,300 samples, 1.59%)lalrpop_util::state_machine::Parser<D,I>::parse_eof (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (343,434,340 samples, 1.80%)<..cedar_policy_core::from_normalized_str::default_from_normalized_str (333,333,330 samples, 1.75%)<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (313,131,310 samples, 1.64%)nonempty::NonEmpty<T>::collect (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::resolver::build_principal_uid (363,636,360 samples, 1.91%)p..praxis_policy_apl_core::attributes::AttributeBag::get_string (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hc5bddd0f77cb3c4cE.llvm.17731787008704995309 (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<cedar_policy_core::ast::id::AnyId as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<cedar_policy_core::ast::entity::EntityUID as core::fmt::Display>::fmt (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str.llvm.15443442747573432051 (10,101,010 samples, 0.05%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_realloc (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Ref>>>::to_ref (20,202,020 samples, 0.11%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Name>>>::to_internal_name (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (20,202,020 samples, 0.11%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17hce8fbab3cd285942E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)alloc::raw_vec::RawVec<T,A>::grow_one (20,202,020 samples, 0.11%)realloc (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)core::ptr::drop_in_place<lalrpop_util::state_machine::Parser<cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__StateMachine,lalrpop_util::lexer::Matcher<cedar_policy_core::parser::node::Node<alloc::string::String>>>> (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)__memset_avx2_unaligned_erms (20,202,020 samples, 0.11%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::init_cache (60,606,060 samples, 0.32%)regex_automata::hybrid::dfa::Lazy::set_transition (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Cache::new (90,909,090 samples, 0.48%)regex_automata::hybrid::dfa::Lazy::set_transition (10,101,010 samples, 0.05%)regex_automata::util::determinize::add_nfa_states (20,202,020 samples, 0.11%)lalrpop_util::lexer::MatcherBuilder::matcher (151,515,150 samples, 0.79%)regex_automata::hybrid::dfa::Lazy::cache_start_group (60,606,060 samples, 0.32%)regex_automata::util::determinize::epsilon_closure (40,404,040 samples, 0.21%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (40,404,040 samples, 0.21%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::set_transition (10,101,010 samples, 0.05%)regex_automata::util::determinize::epsilon_closure (10,101,010 samples, 0.05%)regex_automata::util::determinize::state::Repr::iter_nfa_state_ids (40,404,040 samples, 0.21%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (202,020,200 samples, 1.06%)regex_automata::hybrid::dfa::Lazy::cache_next_state (191,919,190 samples, 1.01%)regex_automata::util::determinize::next (70,707,070 samples, 0.37%)regex_automata::util::determinize::state::StateBuilderMatches::into_nfa (10,101,010 samples, 0.05%)lalrpop_util::state_machine::Parser<D,I>::next_token (212,121,210 samples, 1.11%)regex_automata::util::alphabet::Unit::eoi (10,101,010 samples, 0.05%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (454,545,450 samples, 2.38%)<c..cedar_policy_core::from_normalized_str::default_from_normalized_str (454,545,450 samples, 2.38%)ce..<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (434,343,430 samples, 2.28%)<..cedar_policy_core::parser::text_to_cst::parse_ref (414,141,410 samples, 2.17%)c..cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (414,141,410 samples, 2.17%)c..lalrpop_util::state_machine::Parser<D,I>::parse_eof (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__reduce188 (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__action529 (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::resolver::build_resource_uid (464,646,460 samples, 2.44%)pr..alloc::str::<impl str>::replace (10,101,010 samples, 0.05%)_ZN63_$LT$serde_yaml..value..Value$u20$as$u20$core..clone..Clone$GT$5clone17h8e30cee171624ce2E.llvm.8307836539513240890 (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)praxis_policy_apl_core::evaluator::evaluate_effects::_{{closure}} (4,151,515,110 samples, 21.76%)praxis_policy_apl_core::evaluator:..<core::pin::Pin<P> as core::future::future::Future>::poll (4,151,515,110 samples, 21.76%)<core::pin::Pin<P> as core::future..<praxis_policy_apl_runtime::pdp_router::PdpRouter as praxis_policy_apl_core::step::PdpResolver>::evaluate::_{{closure}} (4,131,313,090 samples, 21.65%)<praxis_policy_apl_runtime::pdp_ro..<praxis_policy_pdp_cedar_direct::resolver::CedarDirectResolver as praxis_policy_apl_core::step::PdpResolver>::evaluate::_{{closure}} (4,111,111,070 samples, 21.55%)<praxis_policy_pdp_cedar_direct::r..praxis_policy_pdp_cedar_direct::template::resolve_refs (40,404,040 samples, 0.21%)praxis_policy_pdp_cedar_direct::template::resolve_refs (10,101,010 samples, 0.05%)_RNvMsa_NtCs27Vx93FoQ6z_4core3fmtNtB5_9Formatter3pad (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_RNvMsa_NtCs27Vx93FoQ6z_4core3fmtNtB5_9Formatter3pad (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (20,202,020 samples, 0.11%)_RNvMsa_NtCs27Vx93FoQ6z_4core3fmtNtB5_9Formatter12pad_integral (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (30,303,030 samples, 0.16%)_RNvXse_NtNtCs27Vx93FoQ6z_4core3fmt3numhNtB7_8LowerHex3fmt (10,101,010 samples, 0.05%)<praxis_policy_apl_runtime::route_handler::AplRouteHandler as praxis_policy_core::registry::AnyHookHandler>::invoke::_{{closure}} (4,414,141,370 samples, 23.13%)<praxis_policy_apl_runtime::route_han..praxis_policy_apl_runtime::session_resolver::resolve_session (70,707,070 samples, 0.37%)praxis_policy_apl_runtime::session_resolver::short_hash (50,505,050 samples, 0.26%)<alloc::string::String as core::iter::traits::collect::FromIterator<alloc::string::String>>::from_iter (50,505,050 samples, 0.26%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17h731fbf5c273145a9E.llvm.15661257894828856886 (10,101,010 samples, 0.05%)<tokio::sync::mpsc::bounded::Semaphore as tokio::sync::mpsc::chan::Semaphore>::add_permits (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (20,202,020 samples, 0.11%)alloc::sync::Arc<T,A>::drop_slow (20,202,020 samples, 0.11%)hashbrown::raw::RawIterRange<T>::fold_impl (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h6ef0fc549765b2b2E.llvm.2024485206901949338 (10,101,010 samples, 0.05%)memcpy@GLIBC_2.2.5 (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)praxis_policy_core::context::PluginContextTable::store_context (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)_ZN9hashbrown3raw13RawTableInner22fallible_with_capacity17h16acbeb1e3f8ec19E.llvm.1257440897361456263 (10,101,010 samples, 0.05%)praxis_policy_core::context::PluginContextTable::take_context (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hb6538396e6783efdE.llvm.14297022766518589247 (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hb6538396e6783efdE.llvm.14297022766518589247 (20,202,020 samples, 0.11%)praxis_policy_core::extensions::filter::filter_extensions (60,606,060 samples, 0.32%)praxis_policy_core::extensions::filter::has_any_subject_capability (20,202,020 samples, 0.11%)core::str::<impl str>::trim_matches (10,101,010 samples, 0.05%)tokio::runtime::context::defer (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (4,727,272,680 samples, 24.78%)<alloc::vec::Vec<T> as alloc::vec::spec..<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (4,727,272,680 samples, 24.78%)<core::iter::adapters::map::Map<I,F> as..criterion::bencher::AsyncBencher<A,M>::iter (4,727,272,680 samples, 24.78%)criterion::bencher::AsyncBencher<A,M>::..<&tokio::runtime::runtime::Runtime as criterion::async_executor::AsyncExecutor>::block_on (4,727,272,680 samples, 24.78%)<&tokio::runtime::runtime::Runtime as c..tokio::runtime::park::CachedParkThread::block_on (4,727,272,680 samples, 24.78%)tokio::runtime::park::CachedParkThread:..ppe_benches::invoke_once::_{{closure}} (4,717,171,670 samples, 24.72%)ppe_benches::invoke_once::_{{closure}}praxis_policy_core::engine::PolicyEngine::invoke_named::_{{closure}} (4,686,868,640 samples, 24.56%)praxis_policy_core::engine::PolicyEngin..praxis_policy_core::executor::Executor::execute::_{{closure}} (4,656,565,610 samples, 24.40%)praxis_policy_core::executor::Executor:..praxis_policy_core::executor::Executor::run_serial_phase::_{{closure}} (4,626,262,580 samples, 24.25%)praxis_policy_core::executor::Executor:..tokio::sync::batch_semaphore::Semaphore::new (10,101,010 samples, 0.05%)<hashbrown::raw::RawTable<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)core::ptr::drop_in_place<praxis_policy_core::extensions::container::Extensions> (10,101,010 samples, 0.05%)praxis_policy_apl_cmf::BagBuilder::with_extensions (20,202,020 samples, 0.11%)praxis_policy_apl_cmf::extensions_bridge::extract_extensions (20,202,020 samples, 0.11%)praxis_policy_apl_cmf::security::extract_security (20,202,020 samples, 0.11%)praxis_policy_apl_core::attributes::AttributeBag::set (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (20,202,020 samples, 0.11%)core::hash::BuildHasher::hash_one (20,202,020 samples, 0.11%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h420ac23d91dd28c1E.llvm.10385711493366922269 (10,101,010 samples, 0.05%)<hashbrown::raw::RawTable<T,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)core::ptr::drop_in_place<cedar_policy_core::ast::entity::Entity> (10,101,010 samples, 0.05%)<alloc::collections::btree::map::IntoIter<K,V,A> as core::ops::drop::Drop>::drop (10,101,010 samples, 0.05%)_ZN4core3ptr72drop_in_place$LT$cedar_policy_core..ast..partial_value..PartialValue$GT$17h62ae7c54e9b5f4e2E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc14___rust_dealloc (10,101,010 samples, 0.05%)alloc::sync::Arc<T,A>::drop_slow (20,202,020 samples, 0.11%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (20,202,020 samples, 0.11%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h64a1133888ad7af3E.llvm.8835512530113933511 (20,202,020 samples, 0.11%)alloc::sync::Arc<T,A>::drop_slow (20,202,020 samples, 0.11%)<alloc::collections::btree::map::BTreeMap<K,V,A> as core::ops::drop::Drop>::drop (20,202,020 samples, 0.11%)_ZN5alloc11collections5btree4node173Handle$LT$alloc..collections..btree..node..NodeRef$LT$alloc..collections..btree..node..marker..Dying$C$K$C$V$C$NodeType$GT$$C$alloc..collections..btree..node..marker..KV$GT$12drop_key_val17h64a1133888ad7af3E.llvm.8835512530113933511 (20,202,020 samples, 0.11%)_ZN4core3ptr61drop_in_place$LT$cedar_policy_core..ast..value..ValueKind$GT$17h1fdf38f9871f2523E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)<cedar_policy::api::Diagnostics as core::convert::From<cedar_policy_core::authorizer::Diagnostics>>::from (10,101,010 samples, 0.05%)<hashbrown::set::IntoIter<K,A> as core::iter::traits::iterator::Iterator>::fold (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)cedar_policy_core::authorizer::partial_response::PartialResponse::new (10,101,010 samples, 0.05%)core::iter::traits::iterator::Iterator::collect (10,101,010 samples, 0.05%)_ZN9hashbrown3raw13RawTableInner22fallible_with_capacity17h2125c44b3490aa5bE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)cedar_policy_core::ast::policy::TemplateBody::condition (10,101,010 samples, 0.05%)cedar_policy_core::ast::policy::PrincipalOrResourceConstraint::as_expr (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret (10,101,010 samples, 0.05%)cedar_policy_core::evaluator::Evaluator::partial_interpret_internal (10,101,010 samples, 0.05%)cedar_policy_core::authorizer::Authorizer::is_authorized_core (50,505,050 samples, 0.26%)cedar_policy_core::evaluator::Evaluator::partial_evaluate (30,303,030 samples, 0.16%)cedar_policy_core::evaluator::Evaluator::partial_interpret (20,202,020 samples, 0.11%)stacker::remaining_stack (10,101,010 samples, 0.05%)cedar_policy::api::Authorizer::is_authorized (70,707,070 samples, 0.37%)cedar_policy_core::authorizer::Authorizer::is_authorized (60,606,060 samples, 0.32%)cedar_policy_core::authorizer::partial_response::<impl core::convert::From<cedar_policy_core::authorizer::partial_response::PartialResponse> for cedar_policy_core::authorizer::Response>::from (10,101,010 samples, 0.05%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::fold (10,101,010 samples, 0.05%)<cedar_policy_core::ast::policy::Template as core::convert::From<cedar_policy_core::ast::policy::TemplateBody>>::from (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)lalrpop_util::lexer::MatcherBuilder::matcher (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Cache::new (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Lazy::init_cache (20,202,020 samples, 0.11%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::reserve_rehash (10,101,010 samples, 0.05%)lalrpop_util::state_machine::Parser<D,I>::drive (10,101,010 samples, 0.05%)alloc::raw_vec::RawVec<T,A>::grow_one (10,101,010 samples, 0.05%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17hce8fbab3cd285942E.llvm.8835512530113933511 (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc13___rdl_realloc (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::decision::translate (40,404,040 samples, 0.21%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (40,404,040 samples, 0.21%)_ZN102_$LT$core..iter..adapters..map..Map$LT$I$C$F$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h959bb1abe41b3641E.llvm.10572370534696548218 (40,404,040 samples, 0.21%)cedar_policy::api::Policy::annotation (40,404,040 samples, 0.21%)<cedar_policy_core::ast::id::AnyId as core::str::traits::FromStr>::from_str (40,404,040 samples, 0.21%)cedar_policy_core::parser::text_to_cst::parse_ident (40,404,040 samples, 0.21%)regex_automata::hybrid::dfa::Lazy::cache_start_group (10,101,010 samples, 0.05%)<smol_str::SmolStr as core::cmp::PartialEq>::eq (10,101,010 samples, 0.05%)_ZN4core3ptr62drop_in_place$LT$cedar_policy_core..ast..entity..EntityUID$GT$17h8501491fab9647adE.llvm.15992844099443335777 (10,101,010 samples, 0.05%)_ZN4core3ptr55drop_in_place$LT$cedar_policy_core..ast..name..Name$GT$17h555e053c04e06633E.llvm.15992844099443335777 (10,101,010 samples, 0.05%)cedar_policy_core::transitive_closure::cyclic_tc_internal (10,101,010 samples, 0.05%)_ZN106_$LT$core..iter..adapters..chain..Chain$LT$A$C$B$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h69caa237f50a8fdfE.llvm.5249237883993513251 (10,101,010 samples, 0.05%)cedar_policy_core::entities::Entities::from_entities (60,606,060 samples, 0.32%)cedar_policy_core::transitive_closure::compute_tc (60,606,060 samples, 0.32%)cedar_policy_core::transitive_closure::enforce_dag_from_tc (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)cedar_policy_core::ast::value::Value::set (10,101,010 samples, 0.05%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)_ZN9hashbrown3raw13RawTableInner22fallible_with_capacity17h2125c44b3490aa5bE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)cedar_policy_core::ast::entity::Entity::new (30,303,030 samples, 0.16%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (30,303,030 samples, 0.16%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (30,303,030 samples, 0.16%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (20,202,020 samples, 0.11%)_ZN17cedar_policy_core3ast6entity6Entity3new28_$u7b$$u7b$closure$u7d$$u7d$17h036f6018522162a4E.llvm.8666744525983102236 (20,202,020 samples, 0.11%)cedar_policy_core::evaluator::RestrictedEvaluator::partial_interpret (20,202,020 samples, 0.11%)core::iter::adapters::try_process (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::EntityUidJson<C>::into_euid (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::<impl core::convert::TryFrom<cedar_policy_core::entities::json::value::TypeAndId> for cedar_policy_core::ast::entity::EntityUID>::try_from (10,101,010 samples, 0.05%)<cedar_policy_core::ast::name::Name as cedar_policy_core::from_normalized_str::FromNormalizedStr>::from_normalized_str (10,101,010 samples, 0.05%)_ZN14regex_automata4meta5regex5Regex11search_half17h630915ade6198269E.llvm.6869977330162537939 (10,101,010 samples, 0.05%)<regex_automata::meta::strategy::Core as regex_automata::meta::strategy::Strategy>::search_half (10,101,010 samples, 0.05%)regex_automata::hybrid::search::find_fwd (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as serde_core::de::Deserialize>::deserialize (20,202,020 samples, 0.11%)serde_json::value::de::visit_array (10,101,010 samples, 0.05%)<serde_json::error::JsonUnexpected as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (20,202,020 samples, 0.11%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (30,303,030 samples, 0.16%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (30,303,030 samples, 0.16%)serde_json::error::make_error (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::FnAndArgs>::deserialize (20,202,020 samples, 0.11%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (20,202,020 samples, 0.11%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (20,202,020 samples, 0.11%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (20,202,020 samples, 0.11%)serde_json::error::make_error (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::parse_ejson (141,414,140 samples, 0.74%)core::iter::adapters::try_process (101,010,100 samples, 0.53%)<std::collections::hash::map::HashMap<K,V,S> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (101,010,100 samples, 0.53%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (101,010,100 samples, 0.53%)cedar_policy_core::entities::json::value::ValueParser::val_into_restricted_expr (90,909,090 samples, 0.48%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::ExtnValueJson>::deserialize (70,707,070 samples, 0.37%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)_RNvMsu_NtNtCs27Vx93FoQ6z_4core3str7patternNtB5_11StrSearcher3new (10,101,010 samples, 0.05%)<<cedar_policy_core::entities::json::entities::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::entities::EntityJson>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::__DeserializeWith as serde_core::de::Deserialize>::deserialize (10,101,010 samples, 0.05%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)cedar_policy::api::Entity::from_json_value (161,616,160 samples, 0.85%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::single_from_json_value (161,616,160 samples, 0.85%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::value::Value>::deserialize_struct (20,202,020 samples, 0.11%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (20,202,020 samples, 0.11%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::EntityUidJson<Context>>::deserialize (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_any (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h5a1008851f4d3509E.llvm.13136002666651947288 (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::entities::build_principal (191,919,190 samples, 1.01%)indexmap::inner::Core<K,V>::insert_full (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::entities::build (262,626,260 samples, 1.38%)praxis_policy_pdp_cedar_direct::entities::build_resource (10,101,010 samples, 0.05%)cedar_policy::api::Entity::from_json_value (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::single_from_json_value (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::entities::EntityJsonParser<S>::parse_ejson (10,101,010 samples, 0.05%)core::iter::adapters::try_process (10,101,010 samples, 0.05%)<std::collections::hash::map::HashMap<K,V,S> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (10,101,010 samples, 0.05%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (10,101,010 samples, 0.05%)<cedar_policy_core::ast::entity::EntityUID as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvMNtCs27Vx93FoQ6z_4core3stre12escape_debug (10,101,010 samples, 0.05%)_RNvMNtNtCs27Vx93FoQ6z_4core4char7methodsc16escape_debug_ext (10,101,010 samples, 0.05%)_RNvNtNtCs27Vx93FoQ6z_4core7unicode9printable12is_printable (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Ref>>>::to_ref (10,101,010 samples, 0.05%)cedar_policy_core::parser::cst_to_ast::<impl cedar_policy_core::parser::node::Node<core::option::Option<cedar_policy_core::parser::cst::Name>>>::to_internal_name (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::init_cache (20,202,020 samples, 0.11%)lalrpop_util::lexer::MatcherBuilder::matcher (30,303,030 samples, 0.16%)regex_automata::hybrid::dfa::Cache::new (30,303,030 samples, 0.16%)regex_automata::util::sparse_set::SparseSets::new (10,101,010 samples, 0.05%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17h92a36688faeb4326E.llvm.8008096151108545417 (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hcd0b48a4c9adcd6dE.llvm.8008096151108545417 (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (80,808,080 samples, 0.42%)cedar_policy_core::from_normalized_str::default_from_normalized_str (80,808,080 samples, 0.42%)<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (70,707,070 samples, 0.37%)cedar_policy_core::parser::text_to_cst::parse_ref (60,606,060 samples, 0.32%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (60,606,060 samples, 0.32%)lalrpop_util::state_machine::Parser<D,I>::next_token (30,303,030 samples, 0.16%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (30,303,030 samples, 0.16%)regex_automata::hybrid::dfa::Lazy::cache_next_state (30,303,030 samples, 0.16%)regex_automata::util::determinize::next (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (10,101,010 samples, 0.05%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as serde_core::de::Deserialize>::deserialize (30,303,030 samples, 0.16%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (20,202,020 samples, 0.11%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (10,101,010 samples, 0.05%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)malloc (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)core::iter::adapters::try_process (10,101,010 samples, 0.05%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (10,101,010 samples, 0.05%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::CedarValueJson::into_expr (10,101,010 samples, 0.05%)cedar_policy_core::ast::restricted_expr::RestrictedExpr::record (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (20,202,020 samples, 0.11%)<alloc::collections::btree::map::BTreeMap<K,V> as core::iter::traits::collect::FromIterator<(K,V)>>::from_iter (20,202,020 samples, 0.11%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (20,202,020 samples, 0.11%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (20,202,020 samples, 0.11%)<cedar_policy_core::entities::json::value::CedarValueJson as core::convert::From<cedar_policy_core::entities::json::value::RawCedarValueJson>>::from (10,101,010 samples, 0.05%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h50095e4a382d4fabE.llvm.6725788770243816192 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::FnAndArgs>::deserialize (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::custom (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)<serde::private::de::FlatMapDeserializer<E> as serde_core::de::Deserializer>::deserialize_map (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_seq (10,101,010 samples, 0.05%)_ZN5serde7private2de7content31ContentRefDeserializer$LT$E$GT$12invalid_type17hc0c7a9c59a5ea5deE.llvm.17677234591028735509 (10,101,010 samples, 0.05%)<serde_json::error::Error as serde_core::de::Error>::invalid_type (10,101,010 samples, 0.05%)_ZN66_$LT$serde_json..error..Error$u20$as$u20$serde_core..de..Error$GT$6custom17h8aba93523cbfcd90E.llvm.917252158905592038 (10,101,010 samples, 0.05%)serde_json::error::make_error (10,101,010 samples, 0.05%)<serde::private::de::content::ContentRefDeserializer<E> as serde_core::de::Deserializer>::deserialize_str (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawCedarValueJson>::deserialize (30,303,030 samples, 0.16%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::RawJsonRecord>::deserialize (30,303,030 samples, 0.16%)serde::private::de::content::content_clone (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_map (10,101,010 samples, 0.05%)serde_json::value::de::visit_array (10,101,010 samples, 0.05%)<serde::private::de::content::ContentVisitor as serde_core::de::Visitor>::visit_seq (10,101,010 samples, 0.05%)cedar_policy_core::entities::json::value::_::<impl serde_core::de::Deserialize for cedar_policy_core::entities::json::value::ExtnValueJson>::deserialize (101,010,100 samples, 0.53%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc12___rust_alloc (10,101,010 samples, 0.05%)cedar_policy::api::Context::from_json_value (161,616,160 samples, 0.85%)cedar_policy_core::entities::json::context::ContextJsonParser<S>::from_json_value (161,616,160 samples, 0.85%)cedar_policy_core::entities::json::value::ValueParser::val_into_restricted_expr (161,616,160 samples, 0.85%)serde_json::value::de::<impl serde_core::de::Deserializer for serde_json::map::Map<alloc::string::String,serde_json::value::Value>>::deserialize_any (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::request::parse (252,525,250 samples, 1.32%)praxis_policy_apl_core::attributes::AttributeBag::get_string (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17hc5bddd0f77cb3c4cE.llvm.17731787008704995309 (10,101,010 samples, 0.05%)_ZN4core3ptr130drop_in_place$LT$cedar_policy_core..parser..node..Node$LT$core..option..Option$LT$cedar_policy_core..parser..cst..Name$GT$$GT$$GT$17he37ce8836ce3c8caE.llvm.5249237883993513251 (10,101,010 samples, 0.05%)core::ptr::drop_in_place<lalrpop_util::state_machine::Parser<cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::__StateMachine,lalrpop_util::lexer::Matcher<cedar_policy_core::parser::node::Node<alloc::string::String>>>> (10,101,010 samples, 0.05%)cfree@GLIBC_2.2.5 (10,101,010 samples, 0.05%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)lalrpop_util::lexer::MatcherBuilder::matcher (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Cache::new (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Lazy::init_cache (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Lazy::set_transition (10,101,010 samples, 0.05%)__memcmp_avx2_movbe (10,101,010 samples, 0.05%)praxis_policy_pdp_cedar_direct::resolver::build_principal_uid (60,606,060 samples, 0.32%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (60,606,060 samples, 0.32%)cedar_policy_core::from_normalized_str::default_from_normalized_str (60,606,060 samples, 0.32%)<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (60,606,060 samples, 0.32%)cedar_policy_core::parser::text_to_cst::parse_ref (50,505,050 samples, 0.26%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (50,505,050 samples, 0.26%)lalrpop_util::state_machine::Parser<D,I>::next_token (20,202,020 samples, 0.11%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Lazy::cache_next_state (10,101,010 samples, 0.05%)regex_automata::util::determinize::next (10,101,010 samples, 0.05%)<cedar_policy_core::ast::entity::EntityUID as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<&T as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)<cedar_policy_core::ast::id::AnyId as core::fmt::Display>::fmt (10,101,010 samples, 0.05%)_RNvNtCs27Vx93FoQ6z_4core3fmt5write (10,101,010 samples, 0.05%)_RNvXsZ_NtCsgW8esjfipvk_5alloc6stringNtB5_6StringNtNtCs27Vx93FoQ6z_4core3fmt5Write9write_str.llvm.15443442747573432051 (10,101,010 samples, 0.05%)_ZN4core3ptr129drop_in_place$LT$cedar_policy_core..parser..node..Node$LT$core..option..Option$LT$cedar_policy_core..parser..cst..Ref$GT$$GT$$GT$17hbf405865e78933f2E.llvm.5249237883993513251 (10,101,010 samples, 0.05%)_ZN4core3ptr131drop_in_place$LT$cedar_policy_core..parser..node..Node$LT$core..option..Option$LT$cedar_policy_core..parser..cst..Ident$GT$$GT$$GT$17hfe1c2e38c0e9bca5E.llvm.5249237883993513251 (10,101,010 samples, 0.05%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (10,101,010 samples, 0.05%)__memset_avx2_unaligned_erms (10,101,010 samples, 0.05%)regex_automata::hybrid::dfa::Cache::new (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Lazy::init_cache (10,101,010 samples, 0.05%)lalrpop_util::lexer::MatcherBuilder::matcher (30,303,030 samples, 0.16%)regex_automata::hybrid::dfa::Lazy::cache_start_group (10,101,010 samples, 0.05%)regex_automata::util::determinize::epsilon_closure (10,101,010 samples, 0.05%)alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (10,101,010 samples, 0.05%)_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$11finish_grow17h92a36688faeb4326E.llvm.8008096151108545417 (10,101,010 samples, 0.05%)<cedar_policy::api::id::EntityUid as core::str::traits::FromStr>::from_str (80,808,080 samples, 0.42%)cedar_policy_core::from_normalized_str::default_from_normalized_str (80,808,080 samples, 0.42%)<cedar_policy_core::ast::entity::EntityUID as core::str::traits::FromStr>::from_str (70,707,070 samples, 0.37%)cedar_policy_core::parser::text_to_cst::parse_ref (50,505,050 samples, 0.26%)cedar_policy_core::parser::text_to_cst::grammar::__parse__Ref::RefParser::parse (50,505,050 samples, 0.26%)lalrpop_util::state_machine::Parser<D,I>::next_token (20,202,020 samples, 0.11%)<lalrpop_util::lexer::Matcher<E> as core::iter::traits::iterator::Iterator>::next (20,202,020 samples, 0.11%)regex_automata::hybrid::dfa::Lazy::cache_next_state (10,101,010 samples, 0.05%)hashbrown::map::HashMap<K,V,S,A>::insert (10,101,010 samples, 0.05%)<praxis_policy_apl_runtime::route_handler::AplRouteHandler as praxis_policy_core::registry::AnyHookHandler>::invoke::_{{closure}} (898,989,890 samples, 4.71%)<prax..praxis_policy_apl_core::evaluator::evaluate_effects::_{{closure}} (828,282,820 samples, 4.34%)praxi..<core::pin::Pin<P> as core::future::future::Future>::poll (818,181,810 samples, 4.29%)<core..<praxis_policy_apl_runtime::pdp_router::PdpRouter as praxis_policy_apl_core::step::PdpResolver>::evaluate::_{{closure}} (818,181,810 samples, 4.29%)<prax..<praxis_policy_pdp_cedar_direct::resolver::CedarDirectResolver as praxis_policy_apl_core::step::PdpResolver>::evaluate::_{{closure}} (818,181,810 samples, 4.29%)<prax..praxis_policy_pdp_cedar_direct::resolver::build_resource_uid (90,909,090 samples, 0.48%)_RNvNvNtCsgW8esjfipvk_5alloc3fmt6format12format_inner (10,101,010 samples, 0.05%)_RNvMsa_NtCs27Vx93FoQ6z_4core3fmtNtB5_9Formatter3pad (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)core::hash::BuildHasher::hash_one (10,101,010 samples, 0.05%)_ZN71_$LT$core..hash..sip..Hasher$LT$S$GT$$u20$as$u20$core..hash..Hasher$GT$5write17h6ef0fc549765b2b2E.llvm.2024485206901949338 (10,101,010 samples, 0.05%)praxis_policy_core::context::PluginContextTable::take_context (10,101,010 samples, 0.05%)hashbrown::raw::RawTable<T,A>::remove_entry (10,101,010 samples, 0.05%)__libc_start_call_main (5,717,171,660 samples, 29.96%)__libc_start_call_mainmain (5,717,171,660 samples, 29.96%)main_RNvNtCs75vJTIYSa2J_3std2rt19lang_start_internal (5,717,171,660 samples, 29.96%)_RNvNtCs75vJTIYSa2J_3std2rt19lang_start_internal_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h839c0b7f2b83ae9fE.llvm.2024485206901949338 (5,717,171,660 samples, 29.96%)_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$..std::sys::backtrace::__rust_begin_short_backtrace (5,717,171,660 samples, 29.96%)std::sys::backtrace::__rust_begin_short_backtracefull_decision::main (5,717,171,660 samples, 29.96%)full_decision::maincriterion::benchmark_group::BenchmarkGroup<M>::bench_function (5,717,171,660 samples, 29.96%)criterion::benchmark_group::BenchmarkGroup<M>::b..criterion::analysis::common (5,717,171,660 samples, 29.96%)criterion::analysis::commoncriterion::routine::Routine::sample (5,676,767,620 samples, 29.75%)criterion::routine::Routine::sample<criterion::routine::Function<M,F,T> as criterion::routine::Routine<M,T>>::warm_up (949,494,940 samples, 4.98%)<crite..criterion::bencher::AsyncBencher<A,M>::iter (949,494,940 samples, 4.98%)criter..<&tokio::runtime::runtime::Runtime as criterion::async_executor::AsyncExecutor>::block_on (949,494,940 samples, 4.98%)<&toki..tokio::runtime::park::CachedParkThread::block_on (949,494,940 samples, 4.98%)tokio:..ppe_benches::invoke_once::_{{closure}} (949,494,940 samples, 4.98%)ppe_be..praxis_policy_core::engine::PolicyEngine::invoke_named::_{{closure}} (949,494,940 samples, 4.98%)praxis..praxis_policy_core::executor::Executor::execute::_{{closure}} (949,494,940 samples, 4.98%)praxis..praxis_policy_core::executor::Executor::run_serial_phase::_{{closure}} (949,494,940 samples, 4.98%)praxis..praxis_policy_core::extensions::filter::filter_extensions (20,202,020 samples, 0.11%)_RNvCsGIExRX8pES_7___rustc35___rust_no_alloc_shim_is_unstable_v2 (10,101,010 samples, 0.05%)__memmove_avx_unaligned_erms (40,404,040 samples, 0.21%)_int_free (252,525,250 samples, 1.32%)_int_malloc (80,808,080 samples, 0.42%)_int_realloc (10,101,010 samples, 0.05%)cfree@GLIBC_2.2.5 (60,606,060 samples, 0.32%)malloc (212,121,210 samples, 1.11%)malloc_consolidate (131,313,130 samples, 0.69%)memcpy@@GLIBC_2.14@plt (10,101,010 samples, 0.05%)realloc (80,808,080 samples, 0.42%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (60,606,060 samples, 0.32%)criterion::analysis::compare::estimates::stats (232,323,230 samples, 1.22%)criterion::stats::univariate::sample::Sample<A>::percentiles (212,121,210 samples, 1.11%)rayon::slice::sort::recurse (212,121,210 samples, 1.11%)rayon::slice::sort::recurse (131,313,130 samples, 0.69%)rayon::slice::sort::recurse (20,202,020 samples, 0.11%)rayon::slice::sort::insertion_sort_shift_left (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)<rayon::iter::reduce::ReduceFolder<R,T> as rayon::iter::plumbing::Folder<T>>::consume_iter (242,424,240 samples, 1.27%)criterion::stats::univariate::resamples::Resamples<A>::next (10,101,010 samples, 0.05%)__math_check_oflow (121,212,120 samples, 0.64%)__math_oflow (30,303,030 samples, 0.16%)exp@@GLIBC_2.29 (1,757,575,740 samples, 9.21%)exp@@GLIBC_2...rayon::iter::plumbing::Folder::consume_iter (3,575,757,540 samples, 18.74%)rayon::iter::plumbing::Folder..with_errno (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,505,050,450 samples, 28.85%)_ZN10rayon_core4join12join_context28_$u7b$$u7b..rayon::iter::plumbing::bridge_producer_consumer::helper (5,505,050,450 samples, 28.85%)rayon::iter::plumbing::bridge_producer_consume.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,505,050,450 samples, 28.85%)_ZN10rayon_core4join12join_context28_$u7b$$u7b..rayon::iter::plumbing::bridge_producer_consumer::helper (5,505,050,450 samples, 28.85%)rayon::iter::plumbing::bridge_producer_consume.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,505,050,450 samples, 28.85%)_ZN10rayon_core4join12join_context28_$u7b$$u7b..rayon::iter::plumbing::bridge_producer_consumer::helper (5,505,050,450 samples, 28.85%)rayon::iter::plumbing::bridge_producer_consume..xflow (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (40,404,040 samples, 0.21%)rayon::iter::plumbing::bridge_producer_consumer::helper (40,404,040 samples, 0.21%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (40,404,040 samples, 0.21%)rayon::iter::plumbing::bridge_producer_consumer::helper (40,404,040 samples, 0.21%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (40,404,040 samples, 0.21%)rayon::iter::plumbing::bridge_producer_consumer::helper (40,404,040 samples, 0.21%)<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (40,404,040 samples, 0.21%)criterion::stats::bivariate::resamples::Resamples<X,Y>::next (30,303,030 samples, 0.16%)rayon::slice::sort::insertion_sort_shift_left (30,303,030 samples, 0.16%)criterion::stats::univariate::sample::Sample<A>::median_abs_dev (151,515,150 samples, 0.79%)criterion::stats::univariate::sample::Sample<A>::percentiles (141,414,140 samples, 0.74%)rayon::slice::sort::recurse (141,414,140 samples, 0.74%)rayon::slice::sort::recurse (111,111,110 samples, 0.58%)rayon::slice::sort::recurse (30,303,030 samples, 0.16%)rayon::slice::sort::insertion_sort_shift_left (30,303,030 samples, 0.16%)rayon::slice::sort::insertion_sort_shift_left (40,404,040 samples, 0.21%)criterion::analysis::estimates::stats (292,929,290 samples, 1.54%)criterion::stats::univariate::sample::Sample<A>::percentiles (121,212,120 samples, 0.64%)rayon::slice::sort::recurse (121,212,120 samples, 0.64%)rayon::slice::sort::recurse (70,707,070 samples, 0.37%)rayon::slice::sort::recurse (20,202,020 samples, 0.11%)rayon::slice::sort::insertion_sort_shift_left (20,202,020 samples, 0.11%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (333,333,330 samples, 1.75%)rayon::iter::plumbing::bridge_producer_consumer::helper (333,333,330 samples, 1.75%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (333,333,330 samples, 1.75%)rayon::iter::plumbing::bridge_producer_consumer::helper (333,333,330 samples, 1.75%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (333,333,330 samples, 1.75%)rayon::iter::plumbing::bridge_producer_consumer::helper (333,333,330 samples, 1.75%)<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (333,333,330 samples, 1.75%)criterion::stats::univariate::resamples::Resamples<A>::next (30,303,030 samples, 0.16%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (70,707,070 samples, 0.37%)rayon::iter::plumbing::bridge_producer_consumer::helper (70,707,070 samples, 0.37%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (70,707,070 samples, 0.37%)rayon::iter::plumbing::bridge_producer_consumer::helper (70,707,070 samples, 0.37%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (70,707,070 samples, 0.37%)rayon::iter::plumbing::bridge_producer_consumer::helper (70,707,070 samples, 0.37%)<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (70,707,070 samples, 0.37%)core::ops::function::impls::<impl core::ops::function::Fn<A> for &F>::call (70,707,070 samples, 0.37%)criterion::stats::univariate::resamples::Resamples<A>::next (50,505,050 samples, 0.26%)rayon::slice::sort::insertion_sort_shift_left (30,303,030 samples, 0.16%)rayon::slice::sort::insertion_sort_shift_left (60,606,060 samples, 0.32%)criterion::analysis::compare::estimates::stats (222,222,220 samples, 1.16%)criterion::stats::univariate::sample::Sample<A>::percentiles (222,222,220 samples, 1.16%)rayon::slice::sort::recurse (222,222,220 samples, 1.16%)rayon::slice::sort::recurse (141,414,140 samples, 0.74%)rayon::slice::sort::recurse (40,404,040 samples, 0.21%)rayon::slice::sort::insertion_sort_shift_left (40,404,040 samples, 0.21%)<rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute (6,434,343,370 samples, 33.72%)<rayon_core::job::StackJob<L,F,R> as rayon_core::job::J..rayon::iter::plumbing::bridge_producer_consumer::helper (6,191,919,130 samples, 32.45%)rayon::iter::plumbing::bridge_producer_consumer::help..rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)rayon_core::registry::in_worker (242,424,240 samples, 1.27%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h83a41f46af64e2e9E.llvm.7236191761492425645 (242,424,240 samples, 1.27%)rayon::iter::plumbing::bridge_producer_consumer::helper (242,424,240 samples, 1.27%)<rayon::iter::reduce::ReduceFolder<R,T> as rayon::iter::plumbing::Folder<T>>::consume_iter (242,424,240 samples, 1.27%)criterion::stats::univariate::resamples::Resamples<A>::next (20,202,020 samples, 0.11%)__memmove_avx_unaligned_erms (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (20,202,020 samples, 0.11%)criterion::stats::univariate::sample::Sample<A>::median_abs_dev (121,212,120 samples, 0.64%)criterion::stats::univariate::sample::Sample<A>::percentiles (111,111,110 samples, 0.58%)rayon::slice::sort::recurse (111,111,110 samples, 0.58%)rayon::slice::sort::recurse (40,404,040 samples, 0.21%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (30,303,030 samples, 0.16%)rayon::slice::sort::insertion_sort_shift_left (50,505,050 samples, 0.26%)criterion::analysis::estimates::stats (303,030,300 samples, 1.59%)criterion::stats::univariate::sample::Sample<A>::percentiles (161,616,160 samples, 0.85%)rayon::slice::sort::recurse (151,515,150 samples, 0.79%)rayon::slice::sort::recurse (70,707,070 samples, 0.37%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)rayon::slice::sort::insertion_sort_shift_left (10,101,010 samples, 0.05%)_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$7execute17h1cfdbfbfa3bd316cE.llvm.7278740130043406189 (343,434,340 samples, 1.80%)_.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (343,434,340 samples, 1.80%)_..rayon::iter::plumbing::bridge_producer_consumer::helper (343,434,340 samples, 1.80%)r.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (343,434,340 samples, 1.80%)_..rayon::iter::plumbing::bridge_producer_consumer::helper (343,434,340 samples, 1.80%)r.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (343,434,340 samples, 1.80%)_..rayon::iter::plumbing::bridge_producer_consumer::helper (343,434,340 samples, 1.80%)r.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h8b2c422e6c4c5bd0E.llvm.7278740130043406189 (343,434,340 samples, 1.80%)_..rayon::iter::plumbing::bridge_producer_consumer::helper (343,434,340 samples, 1.80%)r..<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (343,434,340 samples, 1.80%)<..criterion::stats::univariate::resamples::Resamples<A>::next (30,303,030 samples, 0.16%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$7execute17h9794ccb1cbdf246bE.llvm.7278740130043406189 (30,303,030 samples, 0.16%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (30,303,030 samples, 0.16%)rayon_core::registry::WorkerThread::wait_until_cold (20,202,020 samples, 0.11%)<rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute (20,202,020 samples, 0.11%)rayon::slice::sort::recurse (20,202,020 samples, 0.11%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (20,202,020 samples, 0.11%)rayon_core::registry::WorkerThread::wait_until_cold (10,101,010 samples, 0.05%)<rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h5ae06dfdb75d4e51E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::slice::sort::recurse (10,101,010 samples, 0.05%)_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$7execute17ha2a2af69917445a4E.llvm.7278740130043406189 (80,808,080 samples, 0.42%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (80,808,080 samples, 0.42%)rayon::iter::plumbing::bridge_producer_consumer::helper (80,808,080 samples, 0.42%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (80,808,080 samples, 0.42%)rayon::iter::plumbing::bridge_producer_consumer::helper (80,808,080 samples, 0.42%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (80,808,080 samples, 0.42%)rayon::iter::plumbing::bridge_producer_consumer::helper (80,808,080 samples, 0.42%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17he823ff774d54caa1E.llvm.7278740130043406189 (80,808,080 samples, 0.42%)rayon::iter::plumbing::bridge_producer_consumer::helper (80,808,080 samples, 0.42%)<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (80,808,080 samples, 0.42%)core::ops::function::impls::<impl core::ops::function::Fn<A> for &F>::call (80,808,080 samples, 0.42%)criterion::stats::univariate::resamples::Resamples<A>::next (30,303,030 samples, 0.16%)_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$7execute17hb82a179818f9b1ddE.llvm.7278740130043406189 (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::iter::plumbing::bridge_producer_consumer::helper (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::iter::plumbing::bridge_producer_consumer::helper (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::iter::plumbing::bridge_producer_consumer::helper (10,101,010 samples, 0.05%)_ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h7f4ef42cb29ccad4E.llvm.7278740130043406189 (10,101,010 samples, 0.05%)rayon::iter::plumbing::bridge_producer_consumer::helper (10,101,010 samples, 0.05%)<rayon::iter::fold::FoldFolder<C,ID,F> as rayon::iter::plumbing::Folder<T>>::consume_iter (10,101,010 samples, 0.05%)criterion::stats::bivariate::resamples::Resamples<X,Y>::next (10,101,010 samples, 0.05%)__math_check_oflow (101,010,100 samples, 0.53%)__math_oflow (10,101,010 samples, 0.05%)exp@@GLIBC_2.29 (1,808,080,790 samples, 9.48%)exp@@GLIBC_2.29rayon::iter::plumbing::Folder::consume_iter (3,363,636,330 samples, 17.63%)rayon::iter::plumbing::Fold..with_errno (60,606,060 samples, 0.32%)start_thread (12,252,525,130 samples, 64.21%)start_thread_RNvNvMs0_NtNtNtCs75vJTIYSa2J_3std3sys6thread4unixNtB7_6Thread3new12thread_start (12,252,525,130 samples, 64.21%)_RNvNvMs0_NtNtNtCs75vJTIYSa2J_3std3sys6thread4unixNtB7_6Thread3new12thread_startcore::ops::function::FnOnce::call_once{{vtable.shim}} (12,252,525,130 samples, 64.21%)core::ops::function::FnOnce::call_once{{vtable.shim}}std::sys::backtrace::__rust_begin_short_backtrace (12,252,525,130 samples, 64.21%)std::sys::backtrace::__rust_begin_short_backtracerayon_core::registry::ThreadBuilder::run (12,252,525,130 samples, 64.21%)rayon_core::registry::ThreadBuilder::runrayon_core::registry::WorkerThread::wait_until_cold (12,252,525,130 samples, 64.21%)rayon_core::registry::WorkerThread::wait_until_cold_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$7execute17hbac2b971d83f6d09E.llvm.7278740130043406189 (5,353,535,300 samples, 28.06%)_ZN83_$LT$rayon_core..job..StackJob$LT$L$C$F$.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,353,535,300 samples, 28.06%)_ZN10rayon_core4join12join_context28_$u7b$$u7..rayon::iter::plumbing::bridge_producer_consumer::helper (5,353,535,300 samples, 28.06%)rayon::iter::plumbing::bridge_producer_consum.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,353,535,300 samples, 28.06%)_ZN10rayon_core4join12join_context28_$u7b$$u7..rayon::iter::plumbing::bridge_producer_consumer::helper (5,353,535,300 samples, 28.06%)rayon::iter::plumbing::bridge_producer_consum.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,353,535,300 samples, 28.06%)_ZN10rayon_core4join12join_context28_$u7b$$u7..rayon::iter::plumbing::bridge_producer_consumer::helper (5,353,535,300 samples, 28.06%)rayon::iter::plumbing::bridge_producer_consum.._ZN10rayon_core4join12join_context28_$u7b$$u7b$closure$u7d$$u7d$17h6528f227b5b60bdeE.llvm.7278740130043406189 (5,353,535,300 samples, 28.06%)_ZN10rayon_core4join12join_context28_$u7b$$u7..rayon::iter::plumbing::bridge_producer_consumer::helper (5,353,535,300 samples, 28.06%)rayon::iter::plumbing::bridge_producer_consum..xflow (10,101,010 samples, 0.05%)all (19,080,807,890 samples, 100%)full_decision-4 (19,080,807,890 samples, 100.00%)full_decision-4unlink_chunk.isra.0 (20,202,020 samples, 0.11%) \ No newline at end of file diff --git a/tools/bench_percentiles.py b/tools/bench_percentiles.py new file mode 100644 index 0000000..5bd28aa --- /dev/null +++ b/tools/bench_percentiles.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 Praxis Contributors +"""Compute p50/p95/p99 from Criterion sample.json files (issue #19). + +Criterion does not print p95/p99 by default. Per-iteration times are +sample_time_ns / iters for each sample; we take percentiles of that series. + +Usage (from repo root, after `make bench` or a targeted cargo bench): + + python3 tools/bench_percentiles.py + python3 tools/bench_percentiles.py --root target/criterion --filter full_decision +""" + +from __future__ import annotations + +import argparse +import json +import math +from pathlib import Path + + +def percentile(sorted_vals: list[float], p: float) -> float: + if not sorted_vals: + return float("nan") + if len(sorted_vals) == 1: + return sorted_vals[0] + k = (len(sorted_vals) - 1) * (p / 100.0) + f = math.floor(k) + c = math.ceil(k) + if f == c: + return sorted_vals[int(k)] + return sorted_vals[f] * (c - k) + sorted_vals[c] * (k - f) + + +def fmt_ns(ns: float) -> str: + if ns < 1_000: + return f"{ns:.1f} ns" + if ns < 1_000_000: + return f"{ns / 1_000:.2f} µs" + return f"{ns / 1_000_000:.2f} ms" + + +def per_iter_times(sample_path: Path) -> list[float]: + data = json.loads(sample_path.read_text(encoding="utf-8")) + iters = data["iters"] + times = data["times"] + out: list[float] = [] + for n, t in zip(iters, times, strict=True): + if n <= 0: + continue + out.append(float(t) / float(n)) + return out + + +def main() -> None: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument( + "--root", + type=Path, + default=Path("target/criterion"), + help="Criterion output root", + ) + ap.add_argument( + "--filter", + default="", + help="Only include benchmark ids containing this substring", + ) + args = ap.parse_args() + + rows: list[tuple[str, float, float, float, float]] = [] + for sample in sorted(args.root.glob("**/new/sample.json")): + # ...//.../new/sample.json → id relative to root without /new/sample.json + rel = sample.relative_to(args.root).parent.parent.as_posix() + if args.filter and args.filter not in rel: + continue + vals = per_iter_times(sample) + if len(vals) < 2: + continue + vals.sort() + rows.append( + ( + rel, + percentile(vals, 50), + percentile(vals, 95), + percentile(vals, 99), + sum(vals) / len(vals), + ) + ) + + if not rows: + print(f"no samples under {args.root} (run make bench first)") + return + + print("| Bench | p50 | p95 | p99 | mean |") + print("|-------|-----|-----|-----|------|") + for name, p50, p95, p99, mean in rows: + print( + f"| `{name}` | {fmt_ns(p50)} | {fmt_ns(p95)} | {fmt_ns(p99)} | {fmt_ns(mean)} |" + ) + + +if __name__ == "__main__": + main()