diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 38e7a77c..1951acc9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crate: [libertem_dectris, libertem_asi_tpx3, libertem_qd_mpx] + crate: [libertem_dectris, libertem_asi_tpx3, libertem_qd_mpx, libertem_k2is] steps: - uses: actions/checkout@v4 with: @@ -45,8 +45,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crate: [libertem_dectris, libertem_asi_tpx3, libertem_asi_mpx3, libertem_qd_mpx, ipc_test, common] - toolchain: ["stable", "1.71"] + crate: [libertem_dectris, libertem_asi_tpx3, libertem_asi_mpx3, libertem_qd_mpx, libertem_k2is, ipc_test, common] + toolchain: ["stable", "1.74"] steps: - uses: actions/checkout@v4 with: @@ -178,7 +178,7 @@ jobs: release: name: Release runs-on: ubuntu-latest - if: "startsWith(github.ref, 'refs/tags/')" + if: startsWith(github.ref, 'refs/tags/') needs: [ macos, windows, linux, linux-test, windows-test, macos-test ] steps: - uses: actions/download-artifact@v4 diff --git a/.gitignore b/.gitignore index f4051c4d..c7bd57cb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ __pycache__/ .Python .venv/ env/ -bin/ build/ develop-eggs/ dist/ diff --git a/Cargo.lock b/Cargo.lock index 24758552..cfa17e20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,6 +207,15 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +[[package]] +name = "approx" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +dependencies = [ + "num-traits", +] + [[package]] name = "arboard" version = "3.3.0" @@ -219,7 +228,7 @@ dependencies = [ "objc-foundation", "objc_id", "parking_lot", - "thiserror", + "thiserror 1.0.64", "winapi", "x11rb", ] @@ -380,7 +389,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -420,7 +429,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -437,7 +446,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -706,7 +715,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -731,7 +740,7 @@ dependencies = [ "log", "nix 0.25.1", "slotmap", - "thiserror", + "thiserror 1.0.64", "vec_map", ] @@ -833,7 +842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half", + "half 2.2.1", ] [[package]] @@ -849,82 +858,54 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.25" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "atty", "bitflags 1.3.2", - "clap_derive 3.2.25", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "once_cell", - "strsim", - "termcolor", "textwrap", + "unicode-width", ] [[package]] name = "clap" -version = "4.4.18" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", - "clap_derive 4.4.7", + "clap_derive", ] [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstream", "anstyle", - "clap_lex 0.6.0", + "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -994,7 +975,7 @@ name = "common" version = "0.2.14" dependencies = [ "bincode", - "criterion", + "criterion 0.5.1", "ipc-test", "log", "multiversion", @@ -1009,7 +990,7 @@ dependencies = [ "serde", "stats", "tempfile", - "thiserror", + "thiserror 1.0.64", "tokio", "zerocopy", ] @@ -1081,6 +1062,32 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap 2.34.0", + "criterion-plot 0.4.5", + "csv", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + [[package]] name = "criterion" version = "0.5.1" @@ -1090,8 +1097,8 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.4.18", - "criterion-plot", + "clap 4.5.18", + "criterion-plot 0.5.0", "is-terminal", "itertools 0.10.5", "num-traits", @@ -1107,6 +1114,26 @@ dependencies = [ "walkdir", ] +[[package]] +name = "criterion-linux-perf" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31541cfbf7e42d4192ede20152d365a928f41a00eccf3b6a7558209a215f6163" +dependencies = [ + "criterion 0.3.6", + "perf-event", +] + +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "criterion-plot" version = "0.5.0" @@ -1132,9 +1159,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1189,6 +1216,38 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1271,7 +1330,7 @@ dependencies = [ "objc", "percent-encoding", "raw-window-handle", - "thiserror", + "thiserror 1.0.64", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1377,7 +1436,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -1390,6 +1449,19 @@ dependencies = [ "regex", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.11.5" @@ -1492,7 +1564,7 @@ checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", "flume", - "half", + "half 2.2.1", "lebe", "miniz_oxide", "rayon-core", @@ -1641,7 +1713,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -1851,6 +1923,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "half" version = "2.2.1" @@ -1878,6 +1956,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1976,6 +2060,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "human_bytes" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a0d4dc39ec942e44c1c306aa196da67f2bd6a30dc7b4a475465c13ccf28817" + [[package]] name = "humantime" version = "2.1.0" @@ -2157,7 +2247,7 @@ dependencies = [ "anyhow", "bincode", "bytemuck", - "clap 4.4.18", + "clap 4.5.18", "crossbeam", "log", "memfd", @@ -2169,7 +2259,7 @@ dependencies = [ "serde", "shared_memory", "tempfile", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2213,6 +2303,26 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jemalloc-sys" +version = "0.5.4+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "jemallocator" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0de374a9f8e63150e6f5e8a60cc14c668226d7a347d8aee1a45766e3c4dd3bc" +dependencies = [ + "jemalloc-sys", + "libc", +] + [[package]] name = "jni" version = "0.21.1" @@ -2224,7 +2334,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.64", "walkdir", "windows-sys 0.45.0", ] @@ -2272,6 +2382,38 @@ dependencies = [ "rayon", ] +[[package]] +name = "k2o" +version = "0.2.9" +dependencies = [ + "bytemuck", + "clap 4.5.18", + "common", + "criterion 0.3.6", + "criterion-linux-perf", + "crossbeam", + "dbus", + "env_logger 0.10.2", + "human_bytes", + "ipc-test", + "itertools 0.10.5", + "jemallocator", + "libc", + "log", + "memmap2", + "multiversion", + "ndarray", + "ndarray-npy", + "nix 0.29.0", + "num", + "opentelemetry", + "partialdebug", + "shared_memory", + "tempfile", + "thiserror 2.0.12", + "tokio", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -2302,13 +2444,23 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "libertem-asi-mpx3" version = "0.2.14" dependencies = [ "bincode", "common", - "env_logger", + "env_logger 0.11.5", "ipc-test", "log", "num", @@ -2319,7 +2471,7 @@ dependencies = [ "serval-client", "stats", "tempfile", - "thiserror", + "thiserror 1.0.64", "zerocopy", ] @@ -2331,7 +2483,7 @@ dependencies = [ "common", "crossbeam", "crossbeam-channel", - "env_logger", + "env_logger 0.11.5", "ipc-test", "log", "numpy", @@ -2341,7 +2493,7 @@ dependencies = [ "serde", "stats", "tempfile", - "thiserror", + "thiserror 1.0.64", "uuid", "zerocopy", ] @@ -2352,9 +2504,9 @@ version = "0.2.14" dependencies = [ "bincode", "bs_sys", - "clap 3.2.25", + "clap 4.5.18", "common", - "env_logger", + "env_logger 0.11.5", "ipc-test", "log", "lz4", @@ -2370,21 +2522,44 @@ dependencies = [ "spin_sleep", "stats", "tempfile", - "thiserror", + "thiserror 1.0.64", "uuid", "zerocopy", "zmq", ] +[[package]] +name = "libertem_k2is" +version = "0.2.14" +dependencies = [ + "bincode", + "common", + "crossbeam", + "env_logger 0.10.2", + "ipc-test", + "k2o", + "log", + "num", + "numpy", + "opentelemetry", + "pyo3", + "sendfd", + "serde", + "stats", + "thiserror 1.0.64", + "tokio", + "zerocopy", +] + [[package]] name = "libertem_qd_mpx" version = "0.2.14" dependencies = [ "bincode", "common", - "criterion", + "criterion 0.5.1", "encoding_rs", - "env_logger", + "env_logger 0.11.5", "ipc-test", "itertools 0.13.0", "log", @@ -2396,7 +2571,7 @@ dependencies = [ "serde", "stats", "tempfile", - "thiserror", + "thiserror 1.0.64", "tokio", "zerocopy", ] @@ -2642,6 +2817,7 @@ version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" dependencies = [ + "approx", "matrixmultiply", "num-complex", "num-integer", @@ -2650,6 +2826,20 @@ dependencies = [ "rayon", ] +[[package]] +name = "ndarray-npy" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f85776816e34becd8bd9540818d7dc77bf28307f3b3dcc51cc82403c6931680c" +dependencies = [ + "byteorder", + "ndarray", + "num-complex", + "num-traits", + "py_literal", + "zip", +] + [[package]] name = "ndarray-stats" version = "0.5.1" @@ -2676,7 +2866,7 @@ dependencies = [ "ndk-sys", "num_enum 0.5.11", "raw-window-handle", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2744,17 +2934,6 @@ dependencies = [ "memoffset 0.7.1", ] -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.6.0", - "cfg-if 1.0.0", - "libc", -] - [[package]] name = "nix" version = "0.29.0" @@ -2924,7 +3103,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3041,7 +3220,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3073,7 +3252,7 @@ dependencies = [ "js-sys", "once_cell", "pin-project-lite", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -3089,7 +3268,7 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "thiserror", + "thiserror 1.0.64", "tokio", "tonic", ] @@ -3128,7 +3307,7 @@ dependencies = [ "percent-encoding", "rand", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", ] @@ -3152,12 +3331,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "overload" version = "0.1.1" @@ -3212,6 +3385,26 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "partialdebug" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589e1f540d19ee0565c1e05f6737b442d8d71e477c197acf368ddd89914dd1e8" +dependencies = [ + "partialdebug-derive", +] + +[[package]] +name = "partialdebug-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc64c42a1af5b98ba812b0b8ec10ff222b44fec0cc9637246fe231915a2d31bc" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "paste" version = "1.0.14" @@ -3230,6 +3423,70 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "perf-event" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d6393d9238342159080d79b78cb59c67399a8e7ecfa5d410bd614169e4e823" +dependencies = [ + "libc", + "perf-event-open-sys", +] + +[[package]] +name = "perf-event-open-sys" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c44fb1c7651a45a3652c4afc6e754e40b3d6e6556f1487e2b230bfc4f33c2a8" +dependencies = [ + "libc", +] + +[[package]] +name = "pest" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +dependencies = [ + "memchr", + "thiserror 1.0.64", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "pest_meta" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -3247,7 +3504,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3396,35 +3653,11 @@ dependencies = [ "toml_edit 0.19.15", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -3449,7 +3682,20 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", +] + +[[package]] +name = "py_literal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102df7a3d46db9d3891f178dcc826dc270a6746277a9ae6436f8d29fd490a8e1" +dependencies = [ + "num-bigint", + "num-complex", + "num-traits", + "pest", + "pest_derive", ] [[package]] @@ -3499,7 +3745,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3508,11 +3754,11 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3577,7 +3823,7 @@ checksum = "2a34bde3561f980a51c70495164200569a11662644fe5af017f0b5d7015688cc" dependencies = [ "cfg-if 0.1.10", "libc", - "nix 0.27.1", + "nix 0.29.0", "rand", "winapi", ] @@ -3839,6 +4085,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.3", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.210" @@ -3847,7 +4103,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3870,7 +4126,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -3901,7 +4157,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -3916,6 +4172,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4077,9 +4344,9 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -4094,9 +4361,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -4143,7 +4410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ "cfg-expr", - "heck", + "heck 0.4.1", "pkg-config", "toml", "version-compare", @@ -4184,9 +4451,12 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] [[package]] name = "thiserror" @@ -4194,7 +4464,16 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.64", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -4205,7 +4484,18 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -4290,7 +4580,9 @@ dependencies = [ "libc", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", @@ -4304,7 +4596,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -4480,7 +4772,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -4544,7 +4836,7 @@ dependencies = [ "log", "rand", "sha1", - "thiserror", + "thiserror 1.0.64", "url", "utf-8", ] @@ -4555,6 +4847,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "uds_windows" version = "1.1.0" @@ -4587,6 +4885,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unindent" version = "0.2.3" @@ -4709,7 +5013,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -4743,7 +5047,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5400,7 +5704,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.101", ] [[package]] @@ -5413,6 +5717,18 @@ dependencies = [ "dircpy", ] +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "crc32fast", + "flate2", + "thiserror 1.0.64", +] + [[package]] name = "zmq" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index e4020198..ec2d9bb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ members = [ "libertem_asi_tpx3", "libertem_asi_mpx3", "libertem_qd_mpx", + "libertem_k2is", + "k2o", "ipc_test", "playegui", "bs-sys", diff --git a/README.md b/README.md index ece8a6e7..f11cea63 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ code in submodules. After cloning, remember to enable pre-commit hooks using - `serval-client`: A rust crate for speaking to the ASI Serval API - `libertem_dectris`: This is a Python package for efficiently receiving data from DECTRIS detectors with the zeromq interface. - `libertem_qd_mpx`: A Rust+Python library for receiving data from Quantum Detectors MerlinEM detectors. +- `libertem_k2is`: A Python package for receiving data from K2IS cameras. +- `k2o`: A rust library for receiving data from K2IS cameras. +- `stats`: Small crate for keeping simple stats on shared memory usage. - `playegui`: `egui`-based prototype for efficient on-line visualization of 4D STEM reconstructions diff --git a/bs-sys/Cargo.toml b/bs-sys/Cargo.toml index f3e75ef1..21241dc6 100644 --- a/bs-sys/Cargo.toml +++ b/bs-sys/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.1.0" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/Cargo.toml b/common/Cargo.toml index 87e98e85..3230dd66 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.2.14" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,7 +12,7 @@ rust-version = "1.71" bincode = "1.3.3" ipc-test = { path = "../ipc_test" } stats = { path = "../stats" } -pyo3 = { version = "0.21.2", features = ["abi3-py37"] } +pyo3 = { version = "0.21.2", features = ["abi3-py39"] } numpy = "0.21" serde = "1.0.210" tempfile = "3.10.1" diff --git a/common/src/background_thread.rs b/common/src/background_thread.rs index 462612e0..3d4de31d 100644 --- a/common/src/background_thread.rs +++ b/common/src/background_thread.rs @@ -5,6 +5,7 @@ use std::{ }; use ipc_test::slab::SlabInitError; +use pyo3::{exceptions::PyRuntimeError, pyclass, pymethods, PyResult}; use crate::{ frame_stack::{FrameMeta, FrameStackHandle}, @@ -19,7 +20,9 @@ pub enum ReceiverMsg { /// The acquisition is finished, `frame_stack` contains the remaining frames /// that were received. - Finished { frame_stack: FrameStackHandle }, + Finished { + frame_stack: Option>, + }, /// The acquisition was cancelled, as requested /// by `ControlMsg::CancelAcquisition` @@ -41,18 +44,122 @@ pub enum ReceiverMsg { AcquisitionStart { pending_acquisition: P }, } +/// Like AcquisitionSize, but with the `Auto` resolved to either a number of frames or `Continuous` +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ConcreteAcquisitionSize { + /// Set the number of frames to the given value + NumFrames(usize), + + /// Acquire data until a cancel command is received from the user + Continuous, +} + +/// Configured acquisition size +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum AcquisitionSize { + /// Automatically determine number of frames from acquisition headers or similar + #[default] + Auto, + + /// Set the number of frames to the given value + NumFrames(usize), + + /// Acquire data until a cancel command is received from the user + Continuous, +} + +impl From for AcquisitionSize { + fn from(value: ConcreteAcquisitionSize) -> Self { + match value { + ConcreteAcquisitionSize::NumFrames(n) => Self::NumFrames(n), + ConcreteAcquisitionSize::Continuous => Self::Continuous, + } + } +} + +#[pyclass] +#[derive(Clone, Debug)] +pub struct PyAcquisitionSize { + inner: AcquisitionSize, +} + +impl PyAcquisitionSize { + pub fn inner(&self) -> AcquisitionSize { + self.inner + } + + pub fn from_acquisition_size(size: AcquisitionSize) -> Self { + Self { inner: size } + } +} + +#[pymethods] +impl PyAcquisitionSize { + #[staticmethod] + pub fn from_num_frames(num_frames: usize) -> Self { + Self { + inner: AcquisitionSize::NumFrames(num_frames), + } + } + + #[staticmethod] + pub fn auto() -> Self { + Self { + inner: AcquisitionSize::Auto, + } + } + + #[staticmethod] + pub fn continuous() -> Self { + Self { + inner: AcquisitionSize::Continuous, + } + } + + /// Get the number of frames in this acquisition, raising a RuntimeError if there is none + /// (i.e. the size is auto or continuous) + pub fn get_num_frames(&self) -> PyResult { + match &self.inner { + AcquisitionSize::NumFrames(n) => Ok(*n), + AcquisitionSize::Continuous | AcquisitionSize::Auto => { + Err(PyRuntimeError::new_err(format!( + "PyAcquisitionSize::get_num_frames called on {:?}", + &self.inner + ))) + } + } + } + + pub fn is_continuous(&self) -> bool { + self.inner == AcquisitionSize::Continuous + } + + pub fn is_auto(&self) -> bool { + self.inner == AcquisitionSize::Auto + } + + /// Do we know the number of frames in this acquisition? + pub fn num_frames_known(&self) -> bool { + matches!(self.inner, AcquisitionSize::NumFrames(_)) + } +} + /// Control messages from the foreground code to the background thread #[derive(Debug)] pub enum ControlMsg { + /// Start listening for any acquisitions starting. Depending on the + /// detector, the acquisition size needs to be passed in, or it can be + /// determined automatically. + StartAcquisitionPassive { acquisition_size: AcquisitionSize }, + + /// Cancel the currently running acquisition, if any, going back to idle. + /// Afterwards, another acquisition can be started, for example via + /// `StartAcquisitionPassive`. + CancelAcquisition, + /// Stop processing ASAP StopThread, - /// Start listening for any acquisitions starting - StartAcquisitionPassive, - - /// Cancel the currently running acquisition, if any - CancelAcquisition, - /// Detector-specific control message SpecializedControlMsg { msg: CM }, } diff --git a/common/src/frame_stack.rs b/common/src/frame_stack.rs index 258011f2..7b95ecc8 100644 --- a/common/src/frame_stack.rs +++ b/common/src/frame_stack.rs @@ -212,6 +212,8 @@ mod inner { pub(crate) slot: SlotInfo, meta: Vec, pub(crate) offsets: Vec, + + #[deprecated] pub(crate) bytes_per_frame: usize, } diff --git a/common/src/generic_connection.rs b/common/src/generic_connection.rs index f74f4516..9323db7d 100644 --- a/common/src/generic_connection.rs +++ b/common/src/generic_connection.rs @@ -14,7 +14,10 @@ use log::{debug, info, trace, warn}; use stats::Stats; use crate::{ - background_thread::{BackgroundThread, BackgroundThreadSpawnError, ControlMsg, ReceiverMsg}, + background_thread::{ + AcquisitionSize, BackgroundThread, BackgroundThreadSpawnError, ConcreteAcquisitionSize, + ControlMsg, ReceiverMsg, + }, frame_stack::{FrameMeta, FrameStackHandle, SplitError}, }; @@ -22,7 +25,7 @@ pub trait DetectorConnectionConfig: Clone { /// calculate number of SHM slots fn get_shm_num_slots(&self) -> usize; - /// calculate SHM slot size + /// calculate SHM slot size in bytes fn get_shm_slot_size(&self) -> usize; /// should huge pages be enabled, if available? @@ -33,8 +36,8 @@ pub trait DetectorConnectionConfig: Clone { } pub trait AcquisitionConfig: Debug { - /// total number of frames in the acquisition - fn num_frames(&self) -> usize; + /// Total number of frames in the acquisition, or Continuous + fn acquisition_size(&self) -> ConcreteAcquisitionSize; } #[derive(thiserror::Error, Debug)] @@ -212,7 +215,7 @@ where trace!("adjust_status: FrameStack {{ .. }}"); } ReceiverMsg::FatalError { error } => { - log::warn!("adjust_status: fatal error: {error:?}; going back to idle state"); + log::error!("adjust_status: fatal error: {error:?}; going back to idle state"); self.status = ConnectionStatus::Idle; } ReceiverMsg::Cancelled => { @@ -327,7 +330,9 @@ where )); } ReceiverMsg::Finished { frame_stack } => { - frame_stack.free_slot(&mut self.shm)?; + if let Some(frame_stack) = frame_stack { + frame_stack.free_slot(&mut self.shm)?; + } return Err(ConnectionError::UnexpectedMessage( "ReceiverMsg::Finished in wait_for_arm".to_owned(), )); @@ -417,7 +422,9 @@ where } ReceiverMsg::Finished { frame_stack } => { warn!("wait_for_status: ignoring FrameStackHandle received in ReceiverMsg::Finished message"); - frame_stack.free_slot(&mut self.shm)?; + if let Some(frame_stack) = frame_stack { + frame_stack.free_slot(&mut self.shm)?; + } } ReceiverMsg::FatalError { error } => { return Err(ConnectionError::FatalError(error)); @@ -446,6 +453,7 @@ where &mut self, periodic_callback: impl Fn() -> Result<(), E>, timeout: &Option, + acquisition_size: AcquisitionSize, ) -> Result<(), ConnectionError> where E: std::error::Error + 'static + Send + Sync, @@ -458,7 +466,7 @@ where self.bg_thread .channel_to_thread() - .send(ControlMsg::StartAcquisitionPassive) + .send(ControlMsg::StartAcquisitionPassive { acquisition_size }) .map_err(|_e| ConnectionError::Disconnected)?; self.wait_for_status(ConnectionStatus::Armed, *timeout, periodic_callback) @@ -509,11 +517,13 @@ where // it does _not_ mean that the data consumer has processed them all. // do stats update here to make sure we count the last frame stack! - self.stats.count_stats_item(&frame_stack); + if let Some(frame_stack) = &frame_stack { + self.stats.count_stats_item(frame_stack); + } self.stats.log_stats(); self.stats.reset(); - return Ok(Some(frame_stack)); + return Ok(frame_stack); } ReceiverMsg::FrameStack { frame_stack } => { self.stats.count_stats_item(&frame_stack); @@ -559,6 +569,10 @@ where self.get_status() == ConnectionStatus::Running } + pub fn passive_is_running(&self) -> bool { + todo!(); // properly track states! + } + pub fn cancel( &mut self, timeout: &Option, diff --git a/common/src/py_connection.rs b/common/src/py_connection.rs index 7ad0cb2d..9a1b30be 100644 --- a/common/src/py_connection.rs +++ b/common/src/py_connection.rs @@ -16,7 +16,7 @@ macro_rules! impl_py_connection { mod impl_connection { use bincode::serialize; use common::{ - background_thread::BackgroundThread, + background_thread::{BackgroundThread, PyAcquisitionSize}, decoder::Decoder, frame_stack::{FrameMeta, FrameStackHandle}, generic_cam_client::GenericCamClient, @@ -207,6 +207,11 @@ macro_rules! impl_py_connection { Ok(conn_impl.is_running()) } + pub fn passive_is_running(&self) -> PyResult { + let conn_impl = self.get_conn()?; + Ok(conn_impl.passive_is_running()) + } + pub fn cancel(&mut self, timeout: Option, py: Python<'_>) -> PyResult<()> { let _trace_guard = span_from_py(py, &format!("{}::cancel", stringify!($name)))?; let conn_impl = self.get_conn_mut()?; @@ -229,11 +234,13 @@ macro_rules! impl_py_connection { pub fn start_passive( &mut self, timeout: Option, + acquisition_size: Option, py: Python<'_>, ) -> PyResult<()> { let _trace_guard = span_from_py(py, &format!("{}::start_passive", stringify!($name)))?; let timeout = timeout.map(Duration::from_secs_f32); + let acquisition_size = acquisition_size.unwrap_or(PyAcquisitionSize::auto()); py.allow_threads(|| { let conn_impl = self.get_conn_mut()?; @@ -244,6 +251,7 @@ macro_rules! impl_py_connection { Ok::<_, PyErr>(()) }, &timeout, + acquisition_size.inner(), ) .map_err(|e| { PyConnectionError::new_err(format!("start_passive failed: {e}")) diff --git a/common/src/tracing.rs b/common/src/tracing.rs index 3f522de3..f6a153bc 100644 --- a/common/src/tracing.rs +++ b/common/src/tracing.rs @@ -1,6 +1,7 @@ use std::sync::{Arc, Barrier}; use std::time::Duration; +use log::info; use opentelemetry::global::BoxedTracer; use opentelemetry::trace::{ self, SpanContext, SpanId, TraceContextExt, TraceError, TraceFlags, TraceId, TraceState, Tracer, @@ -34,12 +35,16 @@ pub fn get_tracer() -> BoxedTracer { } pub fn tracing_from_env(service_name: String) { + // FIXME: add an atexit handler calling `global::shutdown_tracer_provider` + // so we don't lose any spans at shutdown + // example OTEL config via environment variables: // OTEL_ENABLE=1 // OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 if std::env::var("OTEL_ENABLE") == Ok("1".to_owned()) { let endpoint = std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT") .unwrap_or_else(|_| "http://localhost:4317".to_owned()); + info!("setting up tracing with endpoint {endpoint}"); spawn_tracing_thread(service_name, endpoint); } } diff --git a/ipc_test/Cargo.toml b/ipc_test/Cargo.toml index 82073015..c2fb5539 100644 --- a/ipc_test/Cargo.toml +++ b/ipc_test/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.1.0" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,7 +13,7 @@ anyhow = "1.0.66" thiserror = "1.0.64" bincode = "1.3.3" bytemuck = "1.12.3" -clap = { version = "4.0.29", features = ["derive"] } +clap = { version = "4.5.18", features = ["derive"] } crossbeam = { version ="0.8.2", features = ["crossbeam-channel"] } memmap2 = "0.5.8" page_size = "0.5.0" diff --git a/ipc_test/src/backend_memfd.rs b/ipc_test/src/backend_memfd.rs index 6759a50b..6a9ad808 100644 --- a/ipc_test/src/backend_memfd.rs +++ b/ipc_test/src/backend_memfd.rs @@ -92,41 +92,44 @@ where .set_nonblocking(true) .expect("set to nonblocking accept"); - let join_handle = std::thread::spawn(move || { - // Stolen from the example on `UnixListener`: - // accept connections and process them, spawning a new thread for each one - loop { - if stop_event.load(Ordering::Relaxed) { - debug!("stopping `serve_shm_handle` thread"); - break; - } - let stream = listener.accept(); - match stream { - Ok((stream, _addr)) => { - /* connection succeeded */ - let my_init = init_data_serialized.clone(); - std::thread::spawn(move || { - handle_connection(stream, fd, &my_init) - .expect("could not let other side connect") - }); + let join_handle = std::thread::Builder::new() + .name("MemfdShmThread".to_string()) + .spawn(move || { + // Stolen from the example on `UnixListener`: + // accept connections and process them, spawning a new thread for each one + loop { + if stop_event.load(Ordering::Relaxed) { + debug!("stopping `serve_shm_handle` thread"); + break; } - Err(err) => { - /* EAGAIN / EWOULDBLOCK */ - if err.kind() == io::ErrorKind::WouldBlock { - let flags = PollFlags::POLLIN; - let pollfd = PollFd::new(listener.as_fd(), flags); - if let Err(e) = nix::poll::poll(&mut [pollfd], 100u16) { - log::error!("poll failed: {e}"); + let stream = listener.accept(); + match stream { + Ok((stream, _addr)) => { + /* connection succeeded */ + let my_init = init_data_serialized.clone(); + std::thread::spawn(move || { + handle_connection(stream, fd, &my_init) + .expect("could not let other side connect") + }); + } + Err(err) => { + /* EAGAIN / EWOULDBLOCK */ + if err.kind() == io::ErrorKind::WouldBlock { + let flags = PollFlags::POLLIN; + let pollfd = PollFd::new(listener.as_fd(), flags); + if let Err(e) = nix::poll::poll(&mut [pollfd], 100u16) { + log::error!("poll failed: {e}"); + } + continue; } - continue; + /* connection failed */ + log::error!("connection failed: {err}"); + break; } - /* connection failed */ - log::error!("connection failed: {err}"); - break; } } - } - }); + }) + .unwrap(); Ok((outer_stop, join_handle)) } diff --git a/k2o/.gitignore b/k2o/.gitignore new file mode 100644 index 00000000..e96af690 --- /dev/null +++ b/k2o/.gitignore @@ -0,0 +1,3 @@ +target +flame.svg +perf.data* diff --git a/k2o/Cargo.toml b/k2o/Cargo.toml new file mode 100644 index 00000000..bd531dbb --- /dev/null +++ b/k2o/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "k2o" +version = "0.2.9" +edition = "2021" + +[dependencies] +nix = { version = "0.29.0", features = ["fs", "sched", "process"] } +num = "0.4.0" +itertools = "0.10.1" +tokio = { version = "1", features = ["full"] } +# futures = "0.3.15" +memmap2 = "0.5.2" +ndarray = { version="0.15.4", features = ["approx"]} +ndarray-npy = "0.8.1" +jemallocator = "0.5.0" +human_bytes = { version="0.3.1", features=["bibytes"] } +clap = { version="4.5.18", features=["derive"]} +opentelemetry = { version="0.25.0" } +ipc-test = { path = "../ipc_test" } +common = { path = "../common" } +shared_memory = "0.12.4" +bytemuck = "1.12.3" +tempfile = "3.5.0" +log = "0.4.18" +dbus = { version = "0.9.7", features=["vendored"] } +libc = "0.2.147" +env_logger = "0.10.0" +partialdebug = "0.2.0" +multiversion = "0.7.3" +crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] } +thiserror = "2.0.12" + +[dev-dependencies] +criterion = "0.3.4" +criterion-linux-perf = "0.1.0" +tempfile = "3.5.0" + +[[bench]] +name = "decode_benchmarks" +harness = false + +[[bench]] +name = "assemble_benchmarks" +harness = false diff --git a/k2o/NOTES.md b/k2o/NOTES.md new file mode 100644 index 00000000..1127a33f --- /dev/null +++ b/k2o/NOTES.md @@ -0,0 +1,56 @@ +# SIMD + +- bounds check + - use of `chunks_exact` elides bounds checks! +- need to explicitly enable the right CPU target (for example: `RUSTFLAGS="-C target-cpu=native"` + - see also `.cargo/config.toml` +- for unrolling, might need to nest the loops + +# Writing to disk + +- first attempt, just to get something working + - mpsc queue, have a single thread writing to disk + - => slow, because this single thread limits the throughput +- second attempt, one writer thread per receiver thread + - still slow (or even slower!) - most of the time is spent in the page + fault handler of the kernel +- experiments with pre-allocating the disk space + - using fallocate, also re-using the npy file from a previous run + - => no change in performance, still spending 88% of our time in the page fault handler +- assembly of full frames is required to get a good access pattern! + +# Notes on reworking the life cycles + +To make sure we can quickly start acquisitions after another, +we need to make sure of some boundary conditions: + +- The SHM area needs to be kept alive over multiple acquisitions, as well as + the "recycling" system for blocks, such that we don't have malloc/pagefault + caused jitter +- The sockets need to be kept open, otherwise the multicast traffic may only be + received after an initial delay (IIRC) +- That also means that switching between more fundamental settings may take longer + - changing network settings + - changing camera mode (IS/Summit) + - SHM socket path + - enabling / disabling the frame iterator +- What changes must be fast: + - file writer destination (filename) -> we may need to disable pre-allocation of files! + - number of frames per acquisition + - probably: camera sync mode (immediately vs. wait for sync flag) + +## Action items +- [ ] Refactor... + - [x] The `AcquisitionRuntime` should be the object that lives over multiple acquisitions + - [x] On the Python side, the `Cam` already needs to start the `AcquisitionRuntime` + - [ ] For error handling, we should have the option to completely tear down + and re-create the `AcquisitionRuntime`, perform this step automatically such that + we don't have "restart the {script,notebook,app,server}" situations as often as currently + - [x] `WriterBuilder` must be set per acquisition, not when starting the runtime +- [x] Figure out where the acquisition ID should be generated + - probably in the `AcquisitionRuntime`, as that is the long-living object + which manages the background thread(s) etc. + +# TODO +- [ ] fix busy waiting (one of the `try_recv` loops, I guess) +- [ ] fix subframe shtuff diff --git a/k2o/benches/assemble_benchmarks.rs b/k2o/benches/assemble_benchmarks.rs new file mode 100644 index 00000000..9bd3361e --- /dev/null +++ b/k2o/benches/assemble_benchmarks.rs @@ -0,0 +1,60 @@ +use std::time::Duration; +use std::time::Instant; + +use criterion::BenchmarkId; +use criterion::Throughput; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +use ipc_test::SharedSlabAllocator; +use k2o::block::K2Block; +use k2o::block_is::K2ISBlock; +use k2o::frame::FrameForWriting; +use k2o::frame::K2Frame; +use k2o::frame_is::K2ISFrame; +use k2o::frame_is::K2ISFrameForWriting; +use tempfile::tempdir; + +fn criterion_benchmark(c: &mut Criterion) { + const PACKET_SIZE: usize = 0x5758; + + const TOTAL_INPUT_SIZE: usize = PACKET_SIZE; + + let block = K2ISBlock::empty(42, 0); + + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("stuff.socket"); + + const FRAME_ID: u32 = 42; + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + let mut frame: K2ISFrameForWriting = K2ISFrameForWriting::empty(FRAME_ID, &mut ssa, 0); + + let mut assign_block = c.benchmark_group("assign_block* functions"); + assign_block.measurement_time(Duration::new(10, 0)); + assign_block.throughput(Throughput::Bytes(TOTAL_INPUT_SIZE as u64)); + assign_block.bench_with_input( + BenchmarkId::new("assign_block", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + frame.assign_block(&block); + }) + }, + ); + assign_block.finish(); +} + +// criterion_group!( +// name = benches; +// config = Criterion::default().with_measurement( +// PerfMeasurement::new(PerfMode::Cycles) +// ); +// targets = criterion_benchmark +// ); +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/k2o/benches/decode_benchmarks.rs b/k2o/benches/decode_benchmarks.rs new file mode 100644 index 00000000..0912f1c9 --- /dev/null +++ b/k2o/benches/decode_benchmarks.rs @@ -0,0 +1,163 @@ +use std::time::Duration; + +use criterion::BenchmarkId; +use criterion::Throughput; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +use k2o::block::K2Block; +use k2o::block_is::K2ISBlock; +use k2o::decode::*; + +fn criterion_benchmark(c: &mut Criterion) { + const NUM_SECTORS: usize = 8; + const BLOCKS_PER_SECTOR_PER_FRAME: usize = 32; + const NUM_FRAMES: usize = 100; + const NUM_PACKETS: usize = NUM_FRAMES * NUM_SECTORS * BLOCKS_PER_SECTOR_PER_FRAME; + const PACKET_SIZE: usize = 0x5758; + const DECODED_SIZE: usize = (PACKET_SIZE - HEADER_SIZE) * 2 / 3; + + // these are too big for the stack: + // let input: [u8; PACKET_SIZE * NUM_PACKETS] = [0; PACKET_SIZE * NUM_PACKETS]; + // let mut out: [u16; DECODED_SIZE * NUM_PACKETS] = [0; DECODED_SIZE * NUM_PACKETS]; + // let mut out_f32: [f32; DECODED_SIZE * NUM_PACKETS] = [0.0; DECODED_SIZE * NUM_PACKETS]; + // (in production code, we don't need to make these large allocations, as we only look at ~single packets at a time) + + let input = vec![0_u8; PACKET_SIZE * NUM_PACKETS].into_boxed_slice(); + let mut out = vec![0_u16; DECODED_SIZE * NUM_PACKETS].into_boxed_slice(); + let mut out_f32 = vec![0.0_f32; DECODED_SIZE * NUM_PACKETS].into_boxed_slice(); + + const TOTAL_INPUT_SIZE: usize = NUM_PACKETS * PACKET_SIZE; + + let mut group12bit = c.benchmark_group("Decode 12bit"); + group12bit.measurement_time(Duration::new(10, 0)); + group12bit.throughput(Throughput::Bytes(TOTAL_INPUT_SIZE as u64)); + group12bit.bench_with_input( + BenchmarkId::new("decode", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out.chunks_exact_mut(DECODED_SIZE); + + for (chunk, o_chunk) in in_chunks.zip(out_chunks) { + decode::(black_box(chunk), black_box(o_chunk)); + } + }) + }, + ); + + group12bit.bench_with_input( + BenchmarkId::new("decode_unrolled", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out.chunks_exact_mut(DECODED_SIZE); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + decode_unrolled::( + black_box(in_chunk), + black_box(out_chunk), + ); + } + }) + }, + ); + + group12bit.bench_with_input( + BenchmarkId::new("decode_map_identity", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out.chunks_exact_mut(DECODED_SIZE); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + decode_map::<_, _, PACKET_SIZE, DECODED_SIZE>( + black_box(in_chunk), + black_box(out_chunk), + |x| x, + ); + } + }) + }, + ); + + group12bit.bench_with_input( + BenchmarkId::new("decode_map_to_f32", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out_f32.chunks_exact_mut(DECODED_SIZE); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + decode_map::<_, _, PACKET_SIZE, DECODED_SIZE>( + black_box(in_chunk), + black_box(out_chunk), + |x| x as f32, + ); + } + }) + }, + ); + + group12bit.bench_with_input( + BenchmarkId::new("decode_converted_to_f32", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out_f32.chunks_exact_mut(DECODED_SIZE); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + decode_converted::<_, PACKET_SIZE, DECODED_SIZE>( + black_box(in_chunk), + black_box(out_chunk), + ); + } + }) + }, + ); + + group12bit.bench_with_input( + BenchmarkId::new("decode_converted_to_u16", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + let out_chunks = out.chunks_exact_mut(DECODED_SIZE); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + decode_converted::<_, PACKET_SIZE, DECODED_SIZE>( + black_box(in_chunk), + black_box(out_chunk), + ); + } + }) + }, + ); + + group12bit.finish(); + + let mut group_from_bytes = c.benchmark_group("K2ISBlock.from_bytes"); + group_from_bytes.measurement_time(Duration::new(10, 0)); + group_from_bytes.throughput(Throughput::Bytes(TOTAL_INPUT_SIZE as u64)); + + group_from_bytes.bench_with_input( + BenchmarkId::new("from_bytes", TOTAL_INPUT_SIZE), + &TOTAL_INPUT_SIZE, + |b, &_s| { + b.iter(|| { + let in_chunks = input.chunks_exact(PACKET_SIZE); + + for chunk in in_chunks { + K2ISBlock::from_bytes(black_box(chunk), 0, 0); + } + }) + }, + ); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/k2o/flamegraph_history/flamegraph-old-mmap.svg b/k2o/flamegraph_history/flamegraph-old-mmap.svg new file mode 100644 index 00000000..bf6b1fe5 --- /dev/null +++ b/k2o/flamegraph_history/flamegraph-old-mmap.svg @@ -0,0 +1,414 @@ +Flame Graph Reset ZoomSearch k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)cpuset_cpus_allowed (6 samples, 0.03%)_raw_spin_lock_irqsave (6 samples, 0.03%)mark_page_lazyfree (3 samples, 0.01%)_rjem_je_arena_decay (7 samples, 0.03%)arena_decay_dirty (7 samples, 0.03%)arena_decay_impl (7 samples, 0.03%)arena_maybe_decay (7 samples, 0.03%)arena_maybe_decay (7 samples, 0.03%)arena_decay_try_purge (7 samples, 0.03%)arena_decay_try_purge (7 samples, 0.03%)arena_decay_to_limit (7 samples, 0.03%)arena_decay_stashed (7 samples, 0.03%)_rjem_je_extent_purge_lazy_wrapper (7 samples, 0.03%)extent_purge_lazy_impl (7 samples, 0.03%)_rjem_je_pages_purge_lazy (7 samples, 0.03%)_rjem_je_pages_purge_lazy (7 samples, 0.03%)madvise (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_madvise (7 samples, 0.03%)do_madvise.part.0 (7 samples, 0.03%)madvise_free_single_vma (7 samples, 0.03%)walk_page_range (7 samples, 0.03%)__walk_page_range (7 samples, 0.03%)madvise_free_pte_range (7 samples, 0.03%)split_huge_page_to_list (3 samples, 0.01%)_rjem_sdallocx (13 samples, 0.06%)isfree (12 samples, 0.06%)isdalloct (12 samples, 0.06%)arena_sdalloc (12 samples, 0.06%)tcache_dalloc_small (12 samples, 0.06%)_rjem_je_tcache_bin_flush_small (11 samples, 0.05%)arena_decay_ticks (8 samples, 0.04%)core::slice::<impl [T]>::get_unchecked (9 samples, 0.04%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked (9 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::add (9 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::offset (9 samples, 0.04%)crossbeam_channel::flavors::list::Channel<T>::read (27 samples, 0.13%)crossbeam_channel::channel::Receiver<T>::recv (42 samples, 0.20%)crossbeam_channel::flavors::list::Channel<T>::recv (38 samples, 0.18%)crossbeam_channel::flavors::list::Channel<T>::start_recv (7 samples, 0.03%)_rjem_je_arena_extent_dalloc_large_prep (15 samples, 0.07%)arena_nactive_sub (13 samples, 0.06%)atomic_fetch_sub_zu (13 samples, 0.06%)extent_list_append (5 samples, 0.02%)extent_deactivate_locked (10 samples, 0.05%)extents_insert_locked (10 samples, 0.05%)sz_psz2ind (3 samples, 0.01%)extent_can_coalesce (9 samples, 0.04%)extent_arena_get (9 samples, 0.04%)atomic_load_p (9 samples, 0.04%)_rjem_je_extent_heap_remove (10 samples, 0.05%)extent_activate_locked (13 samples, 0.06%)extents_remove_locked (13 samples, 0.06%)_rjem_je_extent_avail_insert (3 samples, 0.01%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)_rjem_je_extent_dalloc (7 samples, 0.03%)malloc_mutex_lock (11 samples, 0.05%)malloc_mutex_trylock_final (11 samples, 0.05%)__GI___pthread_mutex_trylock (8 samples, 0.04%)extent_lock2 (15 samples, 0.07%)mutex_pool_lock2 (15 samples, 0.07%)mutex_pool_mutex (4 samples, 0.02%)hash (4 samples, 0.02%)hash_x64_128 (4 samples, 0.02%)extent_merge_impl (49 samples, 0.23%)extent_unlock2 (19 samples, 0.09%)mutex_pool_unlock2 (19 samples, 0.09%)malloc_mutex_unlock (19 samples, 0.09%)__pthread_mutex_unlock_usercnt (19 samples, 0.09%)extent_coalesce (65 samples, 0.30%)malloc_mutex_lock (73 samples, 0.34%)malloc_mutex_trylock_final (73 samples, 0.34%)__GI___pthread_mutex_trylock (71 samples, 0.33%)hash_fmix_64 (4 samples, 0.02%)extent_lock (84 samples, 0.39%)mutex_pool_lock (84 samples, 0.39%)mutex_pool_mutex (11 samples, 0.05%)hash (8 samples, 0.04%)hash_x64_128 (8 samples, 0.04%)extent_rtree_leaf_elm_try_lock (97 samples, 0.45%)rtree_leaf_elm_extent_read (12 samples, 0.06%)rtree_leaf_elm_bits_extent_get (12 samples, 0.06%)extent_lock_from_addr (102 samples, 0.48%)malloc_mutex_unlock (16 samples, 0.07%)__pthread_mutex_unlock_usercnt (12 samples, 0.06%)extent_try_coalesce (201 samples, 0.94%)extent_unlock (23 samples, 0.11%)mutex_pool_unlock (23 samples, 0.11%)mutex_pool_mutex (7 samples, 0.03%)hash (7 samples, 0.03%)hash_x64_128 (7 samples, 0.03%)malloc_mutex_lock (11 samples, 0.05%)malloc_mutex_trylock_final (10 samples, 0.05%)__GI___pthread_mutex_trylock (9 samples, 0.04%)_rjem_je_large_dalloc_finish (230 samples, 1.08%)large_dalloc_finish_impl (229 samples, 1.07%)_rjem_je_arena_extents_dirty_dalloc (229 samples, 1.07%)extent_record (229 samples, 1.07%)_rjem_je_large_dalloc_prep_junked_locked (4 samples, 0.02%)large_dalloc_prep_impl (4 samples, 0.02%)remap_page (3 samples, 0.01%)remove_migration_ptes (3 samples, 0.01%)rmap_walk_anon (3 samples, 0.01%)split_huge_page_to_list (5 samples, 0.02%)madvise_free_huge_pmd (14 samples, 0.07%)total_mapcount.part.0 (6 samples, 0.03%)__list_del_entry_valid (17 samples, 0.08%)__mod_memcg_lruvec_state (5 samples, 0.02%)__mod_memcg_state.part.0 (3 samples, 0.01%)__mod_zone_page_state (6 samples, 0.03%)lru_lazyfree_fn (48 samples, 0.22%)mark_page_lazyfree (59 samples, 0.28%)pagevec_lru_move_fn (56 samples, 0.26%)release_pages (4 samples, 0.02%)__mod_memcg_lruvec_state (3 samples, 0.01%)_raw_spin_lock_irqsave (100 samples, 0.47%)native_queued_spin_lock_slowpath (99 samples, 0.46%)__page_cache_release (107 samples, 0.50%)__put_page (120 samples, 0.56%)mem_cgroup_uncharge (12 samples, 0.06%)uncharge_batch (11 samples, 0.05%)page_counter_uncharge (9 samples, 0.04%)__free_one_page (3 samples, 0.01%)free_unref_page (6 samples, 0.03%)free_pcppages_bulk (5 samples, 0.02%)remap_page (7 samples, 0.03%)remove_migration_ptes (7 samples, 0.03%)rmap_walk_anon (7 samples, 0.03%)remove_migration_pte (4 samples, 0.02%)try_to_unmap (5 samples, 0.02%)rmap_walk_anon (5 samples, 0.02%)try_to_unmap_one (5 samples, 0.02%)ptep_clear_flush (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)split_huge_page_to_list (141 samples, 0.66%)_rjem_je_extent_purge_lazy_wrapper (231 samples, 1.08%)extent_purge_lazy_impl (231 samples, 1.08%)_rjem_je_pages_purge_lazy (231 samples, 1.08%)_rjem_je_pages_purge_lazy (231 samples, 1.08%)madvise (231 samples, 1.08%)entry_SYSCALL_64_after_hwframe (231 samples, 1.08%)do_syscall_64 (231 samples, 1.08%)__x64_sys_madvise (231 samples, 1.08%)do_madvise.part.0 (231 samples, 1.08%)madvise_free_single_vma (231 samples, 1.08%)walk_page_range (230 samples, 1.08%)__walk_page_range (230 samples, 1.08%)madvise_free_pte_range (229 samples, 1.07%)arena_decay_stashed (232 samples, 1.08%)_rjem_je_arena_decay (233 samples, 1.09%)arena_decay_dirty (233 samples, 1.09%)arena_decay_impl (233 samples, 1.09%)arena_maybe_decay (233 samples, 1.09%)arena_maybe_decay (233 samples, 1.09%)arena_decay_try_purge (233 samples, 1.09%)arena_decay_try_purge (233 samples, 1.09%)arena_decay_to_limit (233 samples, 1.09%)__free_one_page (5 samples, 0.02%)free_pcppages_bulk (11 samples, 0.05%)__list_del_entry_valid (4 samples, 0.02%)tlb_finish_mmu (25 samples, 0.12%)release_pages (24 samples, 0.11%)free_unref_page_list (15 samples, 0.07%)arena_decay_impl (36 samples, 0.17%)arena_maybe_decay (36 samples, 0.17%)arena_maybe_decay (36 samples, 0.17%)arena_decay_try_purge (35 samples, 0.16%)arena_decay_try_purge (35 samples, 0.16%)arena_decay_to_limit (35 samples, 0.16%)arena_decay_stashed (35 samples, 0.16%)_rjem_je_extent_dalloc_wrapper (35 samples, 0.16%)_rjem_je_extent_dalloc_wrapper (35 samples, 0.16%)_rjem_je_pages_purge_forced (35 samples, 0.16%)madvise (35 samples, 0.16%)entry_SYSCALL_64_after_hwframe (35 samples, 0.16%)do_syscall_64 (35 samples, 0.16%)__x64_sys_madvise (35 samples, 0.16%)do_madvise.part.0 (35 samples, 0.16%)zap_page_range (35 samples, 0.16%)unmap_page_range (10 samples, 0.05%)arena_decay_ticks (272 samples, 1.27%)ticker_ticks (3 samples, 0.01%)malloc_mutex_lock (13 samples, 0.06%)malloc_mutex_trylock_final (13 samples, 0.06%)__GI___pthread_mutex_trylock (12 samples, 0.06%)isfree (567 samples, 2.65%)is..isdalloct (567 samples, 2.65%)is..arena_sdalloc (567 samples, 2.65%)ar..tcache_dalloc_large (566 samples, 2.65%)tc.._rjem_je_tcache_bin_flush_large (560 samples, 2.62%)_r..core::ptr::drop_in_place<k2o::decode::K2ISBlock> (572 samples, 2.67%)co..core::ptr::drop_in_place<alloc::vec::Vec<u16>> (572 samples, 2.67%)co..core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16>> (572 samples, 2.67%)co..<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (572 samples, 2.67%)<a..<alloc::alloc::Global as core::alloc::Allocator>::deallocate (572 samples, 2.67%)<a..alloc::alloc::dealloc (572 samples, 2.67%)al.._rjem_sdallocx (571 samples, 2.67%)_r..__vdso_clock_gettime (10 samples, 0.05%)[[vdso]] (8 samples, 0.04%)k2o::assemble::K2Frame<_,_>::track_block (23 samples, 0.11%)std::time::Instant::now (19 samples, 0.09%)std::sys::unix::time::inner::Instant::now (16 samples, 0.07%)std::sys::unix::time::inner::now (16 samples, 0.07%)__clock_gettime (14 samples, 0.07%)core::cmp::impls::<impl core::cmp::PartialEq<&B> for &A>::eq (3 samples, 0.01%)core::slice::cmp::<impl core::cmp::PartialEq<[B]> for [A]>::eq (3 samples, 0.01%)<[A] as core::slice::cmp::SlicePartialEq<B>>::equal (3 samples, 0.01%)ndarray::dimension::dimension_trait::Dimension::strides_equivalent (4 samples, 0.02%)core::iter::traits::iterator::Iterator::all (4 samples, 0.02%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (4 samples, 0.02%)core::iter::traits::iterator::Iterator::try_fold (4 samples, 0.02%)core::iter::adapters::map::map_try_fold::{{closure}} (4 samples, 0.02%)core::iter::traits::iterator::Iterator::all::check::{{closure}} (4 samples, 0.02%)ndarray::dimension::dimension_trait::Dimension::strides_equivalent::{{closure}} (4 samples, 0.02%)<(A,B) as ndarray::zip::OffsetTuple>::stride_offset (155 samples, 0.72%)<*mut T as ndarray::zip::ndproducer::Offset>::stride_offset (155 samples, 0.72%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)flush_tlb_func_remote (3 samples, 0.01%)asm_sysvec_call_function (8 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)asm_exc_page_fault (3 samples, 0.01%)exc_page_fault (3 samples, 0.01%)do_user_addr_fault (3 samples, 0.01%)handle_mm_fault (3 samples, 0.01%)huge_pmd_set_accessed (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)__sysvec_apic_timer_interrupt (3 samples, 0.01%)hrtimer_interrupt (3 samples, 0.01%)find_iova (3 samples, 0.01%)fq_ring_free (4 samples, 0.02%)asm_sysvec_apic_timer_interrupt (8 samples, 0.04%)sysvec_apic_timer_interrupt (8 samples, 0.04%)irq_exit_rcu (5 samples, 0.02%)do_softirq_own_stack (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__softirqentry_text_start (5 samples, 0.02%)run_timer_softirq (5 samples, 0.02%)__run_timers.part.0 (5 samples, 0.02%)call_timer_fn (5 samples, 0.02%)fq_flush_timeout (5 samples, 0.02%)flush_tlb_func_common.constprop.0 (9 samples, 0.04%)native_flush_tlb_one_user (5 samples, 0.02%)flush_tlb_func_remote (8 samples, 0.04%)flush_smp_call_function_queue (33 samples, 0.15%)llist_reverse_order (8 samples, 0.04%)__sysvec_call_function (34 samples, 0.16%)asm_sysvec_call_function (49 samples, 0.23%)sysvec_call_function (35 samples, 0.16%)asm_sysvec_apic_timer_interrupt (3 samples, 0.01%)sysvec_apic_timer_interrupt (3 samples, 0.01%)irq_exit_rcu (3 samples, 0.01%)do_softirq_own_stack (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__softirqentry_text_start (3 samples, 0.01%)run_timer_softirq (3 samples, 0.01%)__run_timers.part.0 (3 samples, 0.01%)call_timer_fn (3 samples, 0.01%)fq_flush_timeout (3 samples, 0.01%)fq_ring_free (3 samples, 0.01%)find_iova (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (7 samples, 0.03%)__sysvec_call_function (18 samples, 0.08%)flush_smp_call_function_queue (18 samples, 0.08%)asm_sysvec_call_function (28 samples, 0.13%)sysvec_call_function (19 samples, 0.09%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (3,530 samples, 16.50%)ndarray::impl_methods::<i..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (3,529 samples, 16.50%)ndarray::impl_methods::<i..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (3,526 samples, 16.48%)ndarray::impl_methods::<i..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (3,522 samples, 16.46%)ndarray::impl_methods::<i..ndarray::zip::Zip<(P1,P2),D>::for_each (3,518 samples, 16.44%)ndarray::zip::Zip<(P1,P2)..ndarray::zip::Zip<P,D>::for_each_core (3,518 samples, 16.44%)ndarray::zip::Zip<P,D>::f..ndarray::zip::Zip<P,D>::for_each_core_strided (3,518 samples, 16.44%)ndarray::zip::Zip<P,D>::f..ndarray::zip::Zip<P,D>::for_each_core_strided_c (3,518 samples, 16.44%)ndarray::zip::Zip<P,D>::f..ndarray::zip::Zip<P,D>::inner (3,517 samples, 16.44%)ndarray::zip::Zip<P,D>::i..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (3,191 samples, 14.92%)ndarray::zip::Zip<(P1,P..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (3,191 samples, 14.92%)ndarray::impl_methods::..ndarray::zip::Zip<(P1,P2),D>::for_each (3,191 samples, 14.92%)ndarray::zip::Zip<(P1,P..ndarray::zip::Zip<P,D>::for_each_core (3,191 samples, 14.92%)ndarray::zip::Zip<P,D>:..ndarray::zip::Zip<P,D>::for_each_core_contiguous (3,191 samples, 14.92%)ndarray::zip::Zip<P,D>:..ndarray::zip::Zip<P,D>::inner (3,191 samples, 14.92%)ndarray::zip::Zip<P,D>:..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (939 samples, 4.39%)ndarr..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}}::{{closure}} (939 samples, 4.39%)ndarr..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign::{{closure}} (939 samples, 4.39%)ndarr..<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::for_each (5 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move::{{closure}} (5 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_axis_inplace (5 samples, 0.02%)ndarray::dimension::do_slice (4 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_mut (8 samples, 0.04%)ndarray::impl_views::constructors::<impl ndarray::ArrayBase<ndarray::ViewRepr<&mut A>,D>>::from_shape (3 samples, 0.01%)ndarray::impl_views::constructors::<impl ndarray::ArrayBase<ndarray::ViewRepr<&mut A>,D>>::from_shape_impl (3 samples, 0.01%)k2o::assemble::K2Frame<_,_>::assign_block (3,574 samples, 16.71%)k2o::assemble::K2Frame<_,_..ndarray::slice::SliceInfo<T,Din,Dout>::new_unchecked (3 samples, 0.01%)alloc_pages_vma (71 samples, 0.33%)__alloc_pages_nodemask (71 samples, 0.33%)get_page_from_freelist (71 samples, 0.33%)prep_new_page (70 samples, 0.33%)kernel_init_free_pages (70 samples, 0.33%)clear_page_rep (68 samples, 0.32%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)clear_huge_page (23 samples, 0.11%)clear_subpage (23 samples, 0.11%)clear_page_rep (23 samples, 0.11%)asm_exc_page_fault (97 samples, 0.45%)exc_page_fault (97 samples, 0.45%)do_user_addr_fault (97 samples, 0.45%)handle_mm_fault (97 samples, 0.45%)do_huge_pmd_anonymous_page (97 samples, 0.45%)asm_sysvec_apic_timer_interrupt (4 samples, 0.02%)sysvec_apic_timer_interrupt (4 samples, 0.02%)flush_tlb_func_remote (3 samples, 0.01%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (1,016 samples, 4.75%)<alloc..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1,016 samples, 4.75%)<alloc..core::iter::traits::iterator::Iterator::for_each (1,016 samples, 4.75%)core::..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold (1,016 samples, 4.75%)<core:..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold (1,016 samples, 4.75%)<core:..core::iter::traits::iterator::Iterator::try_fold (1,016 samples, 4.75%)core::..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold::check::{{closure}} (1,016 samples, 4.75%)<core:..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold::ok::{{closure}} (1,016 samples, 4.75%)<core:..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1,016 samples, 4.75%)core::..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend::{{closure}} (1,016 samples, 4.75%)<alloc..core::ptr::write (1,016 samples, 4.75%)core::..[libc-2.31.so] (1,016 samples, 4.75%)[libc-..asm_sysvec_call_function (11 samples, 0.05%)sysvec_call_function (10 samples, 0.05%)__sysvec_call_function (10 samples, 0.05%)flush_smp_call_function_queue (10 samples, 0.05%)_rjem_je_arena_extent_alloc_large (7 samples, 0.03%)extent_recycle (6 samples, 0.03%)extent_recycle_split (3 samples, 0.01%)extent_split_interior (3 samples, 0.01%)alloc::vec::Vec<T,A>::with_capacity_in (9 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (9 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::allocate_in (9 samples, 0.04%)<k2o::assemble::PageAlignedAllocator as core::alloc::Allocator>::allocate (9 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (9 samples, 0.04%)alloc::alloc::Global::alloc_impl (9 samples, 0.04%)alloc::alloc::alloc (9 samples, 0.04%)_rjem_mallocx (9 samples, 0.04%)imalloc (9 samples, 0.04%)imalloc_body (9 samples, 0.04%)imalloc_no_sample (9 samples, 0.04%)ipalloct (9 samples, 0.04%)ipallocztm (9 samples, 0.04%)_rjem_je_large_palloc (9 samples, 0.04%)k2o::assemble::K2Frame<_,_>::empty (1,027 samples, 4.80%)k2o::a..hashbrown::map::make_hash (4 samples, 0.02%)core::hash::BuildHasher::hash_one (4 samples, 0.02%)std::collections::hash::map::HashMap<K,V,S>::get_mut (7 samples, 0.03%)hashbrown::map::HashMap<K,V,S,A>::get_mut (7 samples, 0.03%)hashbrown::map::HashMap<K,V,S,A>::get_inner_mut (7 samples, 0.03%)hashbrown::raw::RawTable<T,A>::get_mut (3 samples, 0.01%)hashbrown::raw::RawTable<T,A>::find (3 samples, 0.01%)hashbrown::raw::RawTableInner<A>::find_inner (3 samples, 0.01%)k2o::assemble::PendingFrames<_,_>::assign_block (5,181 samples, 24.22%)k2o::assemble::PendingFrames<_,_>::assi..<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (9 samples, 0.04%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (9 samples, 0.04%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.02%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.01%)alloc::vec::Vec<T,A>::as_ptr (4 samples, 0.02%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (27 samples, 0.13%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (33 samples, 0.15%)k2o::assemble::K2Frame<_,_>::is_finished (141 samples, 0.66%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (114 samples, 0.53%)main::frame_assembler::{{closure}} (3 samples, 0.01%)crossbeam_channel::channel::Sender<T>::send (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::send (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::write (3 samples, 0.01%)k2o::assemble::PendingFrames<_,_>::handle_finished (182 samples, 0.85%)assembly (5,416 samples, 25.32%)assemblyclone (5,413 samples, 25.30%)clonestart_thread (5,413 samples, 25.30%)start_threadstd::sys::unix::thread::Thread::new::thread_start (5,413 samples, 25.30%)std::sys::unix::thread::Thread::new::thr..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (5,413 samples, 25.30%)<alloc::boxed::Box<F,A> as core::ops::fu..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (5,413 samples, 25.30%)<alloc::boxed::Box<F,A> as core::ops::fu..core::ops::function::FnOnce::call_once{{vtable.shim}} (5,413 samples, 25.30%)core::ops::function::FnOnce::call_once{{..std::thread::Builder::spawn_unchecked_::{{closure}} (5,413 samples, 25.30%)std::thread::Builder::spawn_unchecked_::..std::panic::catch_unwind (5,413 samples, 25.30%)std::panic::catch_unwindstd::panicking::try (5,413 samples, 25.30%)std::panicking::trystd::panicking::try::do_call (5,413 samples, 25.30%)std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (5,413 samples, 25.30%)<core::panic::unwind_safe::AssertUnwindS..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (5,413 samples, 25.30%)std::thread::Builder::spawn_unchecked_::..std::sys_common::backtrace::__rust_begin_short_backtrace (5,413 samples, 25.30%)std::sys_common::backtrace::__rust_begin..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (5,413 samples, 25.30%)crossbeam_utils::thread::ScopedThreadBui..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (5,413 samples, 25.30%)<alloc::boxed::Box<F,A> as core::ops::fu..core::ops::function::FnOnce::call_once{{vtable.shim}} (5,413 samples, 25.30%)core::ops::function::FnOnce::call_once{{..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (5,413 samples, 25.30%)crossbeam_utils::thread::ScopedThreadBui..main::start_recv_threads::{{closure}}::{{closure}} (5,413 samples, 25.30%)main::start_recv_threads::{{closure}}::{..main::frame_assembler (5,407 samples, 25.27%)main::frame_assemblerk2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)__set_cpus_allowed_ptr (6 samples, 0.03%)stop_one_cpu (6 samples, 0.03%)_cond_resched (6 samples, 0.03%)__schedule (6 samples, 0.03%)finish_task_switch (6 samples, 0.03%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)llist_reverse_order (6 samples, 0.03%)__fdget_pos (3 samples, 0.01%)__fget_light (3 samples, 0.01%)<std::fs::File as std::io::Seek>::seek (5 samples, 0.02%)std::sys::unix::fs::File::seek (5 samples, 0.02%)__libc_lseek (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (5 samples, 0.02%)do_syscall_64 (5 samples, 0.02%)ksys_lseek (5 samples, 0.02%)core::ptr::drop_in_place<alloc::vec::Vec<bool>> (4 samples, 0.02%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<bool>> (4 samples, 0.02%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (4 samples, 0.02%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (4 samples, 0.02%)alloc::alloc::dealloc (4 samples, 0.02%)_rjem_sdallocx (4 samples, 0.02%)isfree (4 samples, 0.02%)isdalloct (4 samples, 0.02%)arena_sdalloc (4 samples, 0.02%)tcache_dalloc_small (3 samples, 0.01%)_rjem_je_tcache_bin_flush_small (3 samples, 0.01%)extent_coalesce (3 samples, 0.01%)extent_merge_impl (3 samples, 0.01%)large_dalloc_finish_impl (7 samples, 0.03%)_rjem_je_arena_extents_dirty_dalloc (7 samples, 0.03%)extent_record (7 samples, 0.03%)extent_try_coalesce (5 samples, 0.02%)_rjem_je_large_dalloc (9 samples, 0.04%)core::ptr::drop_in_place<k2o::assemble::K2Frame<2048_usize,1860_usize>> (14 samples, 0.07%)core::ptr::drop_in_place<alloc::vec::Vec<u16,k2o::assemble::PageAlignedAllocator>> (10 samples, 0.05%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16,k2o::assemble::PageAlignedAllocator>> (10 samples, 0.05%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (10 samples, 0.05%)__sched_yield (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_sched_yield (3 samples, 0.01%)schedule (3 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (16 samples, 0.07%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (13 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (13 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (13 samples, 0.06%)amd_pmu_wait_on_overflow (4 samples, 0.02%)native_read_msr (3 samples, 0.01%)__perf_event_task_sched_out (15 samples, 0.07%)amd_pmu_disable_all (15 samples, 0.07%)x86_pmu_disable_all (11 samples, 0.05%)native_write_msr (6 samples, 0.03%)crossbeam_channel::context::Context::with (36 samples, 0.17%)std::thread::local::LocalKey<T>::try_with (36 samples, 0.17%)crossbeam_channel::context::Context::with::{{closure}} (36 samples, 0.17%)crossbeam_channel::context::Context::with::{{closure}} (36 samples, 0.17%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (36 samples, 0.17%)crossbeam_channel::context::Context::wait_until (36 samples, 0.17%)std::thread::park (20 samples, 0.09%)std::sys_common::thread_parker::futex::Parker::park (20 samples, 0.09%)std::sys::unix::futex::futex_wait (20 samples, 0.09%)syscall (20 samples, 0.09%)entry_SYSCALL_64_after_hwframe (19 samples, 0.09%)do_syscall_64 (19 samples, 0.09%)__x64_sys_futex (19 samples, 0.09%)do_futex (19 samples, 0.09%)futex_wait (18 samples, 0.08%)futex_wait_queue_me (18 samples, 0.08%)schedule (18 samples, 0.08%)__schedule (18 samples, 0.08%)crossbeam_channel::flavors::list::Channel<T>::start_recv (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (4 samples, 0.02%)do_syscall_64 (4 samples, 0.02%)__x64_sys_sched_yield (3 samples, 0.01%)__sched_yield (6 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (13 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (13 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (13 samples, 0.06%)crossbeam_channel::channel::Receiver<T>::recv (61 samples, 0.29%)crossbeam_channel::flavors::list::Channel<T>::recv (61 samples, 0.29%)crossbeam_utils::backoff::Backoff::snooze (21 samples, 0.10%)ext4_generic_write_checks (4 samples, 0.02%)__check_block_validity.constprop.0 (8 samples, 0.04%)ext4_inode_block_valid (8 samples, 0.04%)ext4_map_blocks (11 samples, 0.05%)ext4_es_lookup_extent (3 samples, 0.01%)__ext4_journal_stop (3 samples, 0.01%)jbd2_journal_stop (3 samples, 0.01%)stop_this_handle (3 samples, 0.01%)ext4_journal_check_start (3 samples, 0.01%)kmem_cache_alloc (5 samples, 0.02%)slab_pre_alloc_hook.constprop.0 (3 samples, 0.01%)__ext4_journal_start_sb (9 samples, 0.04%)jbd2__journal_start (6 samples, 0.03%)ext4_mark_iloc_dirty (8 samples, 0.04%)ext4_inode_csum_set (4 samples, 0.02%)ext4_inode_csum (3 samples, 0.01%)file_update_time (34 samples, 0.16%)generic_update_time (30 samples, 0.14%)__mark_inode_dirty (30 samples, 0.14%)ext4_dirty_inode (27 samples, 0.13%)__ext4_mark_inode_dirty (18 samples, 0.08%)ext4_reserve_inode_write (9 samples, 0.04%)ext4_get_inode_loc (6 samples, 0.03%)__ext4_get_inode_loc (4 samples, 0.02%)amd_pmu_wait_on_overflow (5 samples, 0.02%)__perf_event_task_sched_out (11 samples, 0.05%)amd_pmu_disable_all (11 samples, 0.05%)x86_pmu_disable_all (6 samples, 0.03%)__sched_text_start (18 samples, 0.08%)schedule_timeout (18 samples, 0.08%)schedule (18 samples, 0.08%)__schedule (18 samples, 0.08%)iommu_dma_alloc_iova (16 samples, 0.07%)alloc_iova_fast (16 samples, 0.07%)alloc_iova (14 samples, 0.07%)rb_prev (14 samples, 0.07%)__iommu_dma_map (29 samples, 0.14%)iommu_map_atomic (13 samples, 0.06%)__iommu_map (13 samples, 0.06%)amd_iommu_map (13 samples, 0.06%)blk_mq_start_request (4 samples, 0.02%)amd_iommu_map (58 samples, 0.27%)__iommu_map_sg (69 samples, 0.32%)__iommu_map (69 samples, 0.32%)iommu_pgsize (8 samples, 0.04%)_raw_spin_unlock_irqrestore (7 samples, 0.03%)dma_map_sg_attrs (202 samples, 0.94%)iommu_dma_map_sg (202 samples, 0.94%)iommu_dma_alloc_iova (132 samples, 0.62%)alloc_iova_fast (131 samples, 0.61%)alloc_iova (130 samples, 0.61%)rb_prev (120 samples, 0.56%)__slab_alloc (5 samples, 0.02%)___slab_alloc (5 samples, 0.02%)blk_mq_sched_insert_requests (257 samples, 1.20%)blk_mq_try_issue_list_directly (257 samples, 1.20%)__blk_mq_try_issue_directly (256 samples, 1.20%)nvme_queue_rq (254 samples, 1.19%)mempool_alloc (15 samples, 0.07%)__kmalloc (15 samples, 0.07%)memset (7 samples, 0.03%)blk_finish_plug (264 samples, 1.23%)blk_mq_flush_plug_list (264 samples, 1.23%)list_sort (4 samples, 0.02%)ext4_iomap_overwrite_begin (5 samples, 0.02%)ext4_iomap_begin (5 samples, 0.02%)ext4_set_iomap (5 samples, 0.02%)bvec_alloc (7 samples, 0.03%)mempool_alloc (5 samples, 0.02%)kmem_cache_alloc (5 samples, 0.02%)memset (5 samples, 0.02%)bio_alloc_bioset (11 samples, 0.05%)__bio_try_merge_page (95 samples, 0.44%)bio_iov_iter_get_pages (158 samples, 0.74%)iov_iter_get_pages (28 samples, 0.13%)internal_get_user_pages_fast (27 samples, 0.13%)try_grab_compound_head (9 samples, 0.04%)__blk_mq_alloc_request (13 samples, 0.06%)blk_mq_get_tag (13 samples, 0.06%)__sbitmap_queue_get (9 samples, 0.04%)sbitmap_get (6 samples, 0.03%)__sbitmap_get_word (4 samples, 0.02%)__blk_queue_split (8 samples, 0.04%)bvec_split_segs (4 samples, 0.02%)__rq_qos_track (11 samples, 0.05%)wbt_track (9 samples, 0.04%)bio_attempt_front_merge (3 samples, 0.01%)blk_attempt_plug_merge (8 samples, 0.04%)blk_mq_get_driver_tag (3 samples, 0.01%)__iommu_dma_unmap (11 samples, 0.05%)__iommu_unmap (11 samples, 0.05%)amd_iommu_unmap (11 samples, 0.05%)fetch_pte (8 samples, 0.04%)__handle_irq_event_percpu (13 samples, 0.06%)nvme_irq (13 samples, 0.06%)nvme_process_cq (13 samples, 0.06%)nvme_pci_complete_rq (13 samples, 0.06%)asm_common_interrupt (16 samples, 0.07%)common_interrupt (16 samples, 0.07%)asm_call_sysvec_on_stack (15 samples, 0.07%)handle_edge_irq (15 samples, 0.07%)handle_irq_event (15 samples, 0.07%)_raw_spin_unlock_irqrestore (33 samples, 0.15%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)kmem_cache_alloc (5 samples, 0.02%)iommu_dma_alloc_iova (310 samples, 1.45%)alloc_iova_fast (307 samples, 1.43%)alloc_iova (305 samples, 1.43%)rb_prev (255 samples, 1.19%)asm_common_interrupt (8 samples, 0.04%)common_interrupt (8 samples, 0.04%)asm_call_sysvec_on_stack (8 samples, 0.04%)handle_edge_irq (8 samples, 0.04%)handle_irq_event (8 samples, 0.04%)__handle_irq_event_percpu (8 samples, 0.04%)nvme_irq (8 samples, 0.04%)nvme_process_cq (8 samples, 0.04%)nvme_pci_complete_rq (7 samples, 0.03%)__iommu_dma_unmap (7 samples, 0.03%)__iommu_unmap (5 samples, 0.02%)amd_iommu_unmap (5 samples, 0.02%)fetch_pte (3 samples, 0.01%)amd_iommu_map (178 samples, 0.83%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__iommu_dma_map (527 samples, 2.46%)__..iommu_map_atomic (215 samples, 1.00%)__iommu_map (213 samples, 1.00%)iommu_pgsize (27 samples, 0.13%)asm_call_sysvec_on_stack (3 samples, 0.01%)handle_edge_irq (3 samples, 0.01%)handle_irq_event (3 samples, 0.01%)asm_common_interrupt (4 samples, 0.02%)common_interrupt (4 samples, 0.02%)blk_add_timer (3 samples, 0.01%)blk_mq_start_request (13 samples, 0.06%)ktime_get (7 samples, 0.03%)read_tsc (6 samples, 0.03%)amd_iommu_map (30 samples, 0.14%)__iommu_map_sg (34 samples, 0.16%)__iommu_map (34 samples, 0.16%)_raw_spin_unlock_irqrestore (3 samples, 0.01%)iommu_dma_alloc_iova (37 samples, 0.17%)alloc_iova_fast (37 samples, 0.17%)alloc_iova (37 samples, 0.17%)rb_prev (30 samples, 0.14%)dma_map_sg_attrs (72 samples, 0.34%)iommu_dma_map_sg (72 samples, 0.34%)memset (3 samples, 0.01%)mempool_alloc (7 samples, 0.03%)__kmalloc (7 samples, 0.03%)nvme_setup_cmd (3 samples, 0.01%)blk_mq_flush_plug_list (651 samples, 3.04%)blk..blk_mq_sched_insert_requests (649 samples, 3.03%)blk..blk_mq_try_issue_list_directly (646 samples, 3.02%)blk..__blk_mq_try_issue_directly (644 samples, 3.01%)__b..nvme_queue_rq (640 samples, 2.99%)nvm..blk_mq_rq_ctx_init (6 samples, 0.03%)ktime_get (3 samples, 0.01%)blk_mq_submit_bio (708 samples, 3.31%)blk..blk_queue_enter (4 samples, 0.02%)__bio_clone_fast (5 samples, 0.02%)ktime_get (3 samples, 0.01%)kmem_cache_alloc (4 samples, 0.02%)bio_split (17 samples, 0.08%)bio_clone_fast (16 samples, 0.07%)bio_alloc_bioset (10 samples, 0.05%)mempool_alloc (6 samples, 0.03%)__blk_queue_split (61 samples, 0.29%)submit_bio_noacct (6 samples, 0.03%)submit_bio_checks (6 samples, 0.03%)blk_queue_split (62 samples, 0.29%)__bio_clone_fast (3 samples, 0.01%)kmem_cache_alloc (4 samples, 0.02%)bio_split (12 samples, 0.06%)bio_clone_fast (12 samples, 0.06%)bio_alloc_bioset (9 samples, 0.04%)mempool_alloc (5 samples, 0.02%)map_sector.isra.0 (6 samples, 0.03%)md_submit_bio (112 samples, 0.52%)md_handle_request (47 samples, 0.22%)raid0_make_request (44 samples, 0.21%)submit_bio_noacct (15 samples, 0.07%)submit_bio_checks (15 samples, 0.07%)ktime_get (9 samples, 0.04%)read_tsc (7 samples, 0.03%)iomap_apply (1,018 samples, 4.76%)iomap_..iomap_dio_bio_actor (1,010 samples, 4.72%)iomap_..iomap_dio_submit_bio (836 samples, 3.91%)ioma..submit_bio_noacct (834 samples, 3.90%)subm..submit_bio_checks (4 samples, 0.02%)new_sync_write (1,358 samples, 6.35%)new_sync..ext4_file_write_iter (1,358 samples, 6.35%)ext4_fil..iomap_dio_rw (1,305 samples, 6.10%)iomap_di..__iomap_dio_rw (1,305 samples, 6.10%)__iomap_..entry_SYSCALL_64_after_hwframe (1,365 samples, 6.38%)entry_SY..do_syscall_64 (1,365 samples, 6.38%)do_sysca..ksys_write (1,363 samples, 6.37%)ksys_wri..vfs_write (1,362 samples, 6.37%)vfs_writesecurity_file_permission (4 samples, 0.02%)apparmor_file_permission (4 samples, 0.02%)std::panic::catch_unwind (1,455 samples, 6.80%)std::pani..std::panicking::try (1,455 samples, 6.80%)std::pani..std::panicking::try::do_call (1,455 samples, 6.80%)std::pani..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (1,455 samples, 6.80%)<core::pa..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (1,455 samples, 6.80%)std::thre..std::sys_common::backtrace::__rust_begin_short_backtrace (1,455 samples, 6.80%)std::sys_..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (1,455 samples, 6.80%)crossbeam..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,455 samples, 6.80%)<alloc::b..core::ops::function::FnOnce::call_once{{vtable.shim}} (1,455 samples, 6.80%)core::ops..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (1,455 samples, 6.80%)crossbeam..main::start_recv_threads::{{closure}}::{{closure}} (1,455 samples, 6.80%)main::sta..main::full_frame_writer_direct (1,449 samples, 6.77%)main::ful..std::io::Write::write_all (1,368 samples, 6.39%)std::io:..std::os::unix::net::datagram::UnixDatagram::send (1,368 samples, 6.39%)std::os:..std::sys::unix::net::Socket::write (1,368 samples, 6.39%)std::sys..std::sys::unix::fd::FileDesc::write (1,368 samples, 6.39%)std::sys..__libc_write (1,368 samples, 6.39%)__libc_w..ff_writer (1,456 samples, 6.81%)ff_writerclone (1,456 samples, 6.81%)clonestart_thread (1,456 samples, 6.81%)start_thr..std::sys::unix::thread::Thread::new::thread_start (1,456 samples, 6.81%)std::sys:..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,456 samples, 6.81%)<alloc::b..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,456 samples, 6.81%)<alloc::b..core::ops::function::FnOnce::call_once{{vtable.shim}} (1,456 samples, 6.81%)core::ops..std::thread::Builder::spawn_unchecked_::{{closure}} (1,456 samples, 6.81%)std::thre.._raw_spin_lock_irq (19 samples, 0.09%)calculate_sigpending (39 samples, 0.18%)recalc_sigpending (13 samples, 0.06%)schedule_tail (21 samples, 0.10%)finish_task_switch (21 samples, 0.10%)__mmdrop (21 samples, 0.10%)pgd_free (20 samples, 0.09%)__list_del_entry_valid (20 samples, 0.09%)ret_from_fork (67 samples, 0.31%)syscall_exit_to_user_mode (7 samples, 0.03%)exit_to_user_mode_prepare (7 samples, 0.03%)clone (69 samples, 0.32%)main (71 samples, 0.33%)perf_5.10 (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_execve (6 samples, 0.03%)do_execveat_common (6 samples, 0.03%)bprm_execve (6 samples, 0.03%)load_elf_binary (6 samples, 0.03%)begin_new_exec (6 samples, 0.03%)__set_task_comm (6 samples, 0.03%)strlcpy (6 samples, 0.03%)memcpy (6 samples, 0.03%)_rjem_je_extent_heap_remove_first (4 samples, 0.02%)base_alloc_impl (9 samples, 0.04%)_rjem_je_base_alloc_extent (15 samples, 0.07%)extent_esn_set (6 samples, 0.03%)asm_exc_page_fault (6 samples, 0.03%)exc_page_fault (6 samples, 0.03%)do_user_addr_fault (6 samples, 0.03%)handle_mm_fault (6 samples, 0.03%)wp_page_copy (6 samples, 0.03%)ptep_clear_flush (5 samples, 0.02%)flush_tlb_mm_range (5 samples, 0.02%)on_each_cpu_cond_mask (5 samples, 0.02%)smp_call_function_many_cond (5 samples, 0.02%)_rjem_je_extent_alloc (16 samples, 0.07%)_rjem_je_extent_alloc (16 samples, 0.07%)malloc_mutex_trylock_final (6 samples, 0.03%)__GI___pthread_mutex_trylock (6 samples, 0.03%)malloc_mutex_lock (7 samples, 0.03%)extent_lock2 (8 samples, 0.04%)mutex_pool_lock2 (8 samples, 0.04%)extent_recycle (32 samples, 0.15%)extent_recycle_split (31 samples, 0.14%)extent_split_interior (29 samples, 0.14%)extent_split_impl (29 samples, 0.14%)_rjem_je_extent_alloc_wrapper (34 samples, 0.16%)extent_alloc_retained (33 samples, 0.15%)down_read (4 samples, 0.02%)__list_add_valid (3 samples, 0.01%)__mod_memcg_lruvec_state (3 samples, 0.01%)__mod_memcg_state.part.0 (3 samples, 0.01%)__pagevec_lru_add_fn (16 samples, 0.07%)_raw_spin_lock_irqsave (8 samples, 0.04%)native_queued_spin_lock_slowpath (4 samples, 0.02%)lru_add_drain (28 samples, 0.13%)lru_add_drain_cpu (28 samples, 0.13%)pagevec_lru_move_fn (28 samples, 0.13%)flush_tlb_func_common.constprop.0 (7 samples, 0.03%)default_send_IPI_mask_sequence_phys (14 samples, 0.07%)__default_send_IPI_dest_field (13 samples, 0.06%)on_each_cpu_cond_mask (81 samples, 0.38%)smp_call_function_many_cond (80 samples, 0.37%)tlb_is_not_lazy (8 samples, 0.04%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)__default_send_IPI_dest_field (9 samples, 0.04%)default_send_IPI_mask_sequence_phys (10 samples, 0.05%)flush_tlb_mm_range (196 samples, 0.92%)smp_call_function_many_cond (106 samples, 0.50%)llist_add_batch (4 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)_raw_spin_lock_irqsave (4 samples, 0.02%)native_queued_spin_lock_slowpath (3 samples, 0.01%)__free_one_page (4 samples, 0.02%)free_unref_page_list (9 samples, 0.04%)free_pcppages_bulk (8 samples, 0.04%)tlb_finish_mmu (228 samples, 1.07%)release_pages (29 samples, 0.14%)mem_cgroup_uncharge_list (3 samples, 0.01%)uncharge_batch (3 samples, 0.01%)page_counter_uncharge (3 samples, 0.01%)__split_huge_pmd (13 samples, 0.06%)pmdp_invalidate (7 samples, 0.03%)flush_tlb_mm_range (7 samples, 0.03%)on_each_cpu_cond_mask (7 samples, 0.03%)smp_call_function_many_cond (7 samples, 0.03%)tlb_is_not_lazy (3 samples, 0.01%)__alloc_pages_nodemask (11 samples, 0.05%)get_page_from_freelist (11 samples, 0.05%)prep_new_page (6 samples, 0.03%)kernel_init_free_pages (6 samples, 0.03%)clear_page_rep (6 samples, 0.03%)__tlb_remove_page_size (13 samples, 0.06%)__get_free_pages (13 samples, 0.06%)page_remove_rmap (9 samples, 0.04%)deferred_split_huge_page (3 samples, 0.01%)sync_mm_rss (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (313 samples, 1.46%)do_syscall_64 (313 samples, 1.46%)__x64_sys_madvise (313 samples, 1.46%)do_madvise.part.0 (313 samples, 1.46%)zap_page_range (309 samples, 1.44%)unmap_page_range (51 samples, 0.24%)_rjem_je_pages_purge_forced (316 samples, 1.48%)madvise (316 samples, 1.48%)extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)_rjem_je_extent_heap_first (7 samples, 0.03%)extents_best_fit_locked (11 samples, 0.05%)extents_fit_locked (12 samples, 0.06%)extent_recycle_extract (21 samples, 0.10%)malloc_mutex_lock (6 samples, 0.03%)malloc_mutex_trylock_final (6 samples, 0.03%)__GI___pthread_mutex_trylock (6 samples, 0.03%)extent_lock2 (3 samples, 0.01%)mutex_pool_lock2 (3 samples, 0.01%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)alloc::vec::from_elem (379 samples, 1.77%)a..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (379 samples, 1.77%)<..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (379 samples, 1.77%)a..alloc::raw_vec::RawVec<T,A>::allocate_in (379 samples, 1.77%)a..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (379 samples, 1.77%)<..alloc::alloc::Global::alloc_impl (379 samples, 1.77%)a..alloc::alloc::alloc_zeroed (379 samples, 1.77%)a.._rjem_calloc (379 samples, 1.77%)_..imalloc (379 samples, 1.77%)i..imalloc_body (379 samples, 1.77%)i..imalloc_no_sample (379 samples, 1.77%)i..iallocztm (379 samples, 1.77%)i..arena_malloc (379 samples, 1.77%)a..tcache_alloc_large (379 samples, 1.77%)t.._rjem_je_large_palloc (379 samples, 1.77%)_.._rjem_je_arena_extent_alloc_large (378 samples, 1.77%)extent_recycle (342 samples, 1.60%)extent_recycle_split (5 samples, 0.02%)extent_split_interior (5 samples, 0.02%)extent_split_impl (5 samples, 0.02%)down_read_trylock (37 samples, 0.17%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)__list_del_entry_valid (12 samples, 0.06%)_raw_spin_lock (22 samples, 0.10%)native_queued_spin_lock_slowpath (22 samples, 0.10%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)__alloc_pages_nodemask (169 samples, 0.79%)get_page_from_freelist (169 samples, 0.79%)prep_new_page (103 samples, 0.48%)kernel_init_free_pages (102 samples, 0.48%)clear_page_rep (99 samples, 0.46%)asm_sysvec_call_function (8 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)alloc_pages_vma (170 samples, 0.79%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (5 samples, 0.02%)native_flush_tlb_one_user (4 samples, 0.02%)kernel_init_free_pages (159 samples, 0.74%)clear_page_rep (159 samples, 0.74%)asm_sysvec_call_function (11 samples, 0.05%)sysvec_call_function (9 samples, 0.04%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)alloc_pages_vma (167 samples, 0.78%)__alloc_pages_nodemask (167 samples, 0.78%)get_page_from_freelist (167 samples, 0.78%)prep_new_page (161 samples, 0.75%)clear_huge_page (36 samples, 0.17%)clear_subpage (33 samples, 0.15%)clear_page_rep (32 samples, 0.15%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)do_huge_pmd_anonymous_page (207 samples, 0.97%)mem_cgroup_charge (13 samples, 0.06%)try_charge (5 samples, 0.02%)page_counter_try_charge (4 samples, 0.02%)handle_mm_fault (417 samples, 1.95%)h..asm_exc_page_fault (483 samples, 2.26%)a..exc_page_fault (469 samples, 2.19%)e..do_user_addr_fault (467 samples, 2.18%)d..up_read (10 samples, 0.05%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)k2o::decode::decode (644 samples, 3.01%)k2o..error_entry (4 samples, 0.02%)sync_regs (4 samples, 0.02%)<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (1,026 samples, 4.80%)<k2o::..std::time::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::now (3 samples, 0.01%)__clock_gettime (3 samples, 0.01%)alloc::boxed::Box<T>::new (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (10 samples, 0.05%)core::sync::atomic::AtomicPtr<T>::load (7 samples, 0.03%)core::sync::atomic::atomic_load (7 samples, 0.03%)crossbeam_channel::channel::Sender<T>::send (22 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::send (22 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::write (11 samples, 0.05%)core::ptr::mut_ptr::<impl *mut T>::write (4 samples, 0.02%)core::ptr::write (4 samples, 0.02%)k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)__set_cpus_allowed_ptr (6 samples, 0.03%)stop_one_cpu (6 samples, 0.03%)_cond_resched (6 samples, 0.03%)__schedule (6 samples, 0.03%)finish_task_switch (6 samples, 0.03%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)llist_reverse_order (6 samples, 0.03%)kfree (31 samples, 0.14%)asm_sysvec_call_function (11 samples, 0.05%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (5 samples, 0.02%)__free_one_page (42 samples, 0.20%)__mod_zone_page_state (3 samples, 0.01%)__list_del_entry_valid (37 samples, 0.17%)free_pcppages_bulk (152 samples, 0.71%)_raw_spin_lock (57 samples, 0.27%)native_queued_spin_lock_slowpath (56 samples, 0.26%)__consume_stateless_skb (244 samples, 1.14%)skb_release_data (213 samples, 1.00%)free_unref_page (183 samples, 0.86%)free_unref_page_commit (5 samples, 0.02%)__list_add_valid (3 samples, 0.01%)__perf_event_task_sched_out (4 samples, 0.02%)amd_pmu_disable_all (4 samples, 0.02%)__skb_wait_for_more_packets (6 samples, 0.03%)schedule_timeout (6 samples, 0.03%)schedule (6 samples, 0.03%)__schedule (6 samples, 0.03%)__skb_recv_udp (14 samples, 0.07%)udp_rmem_release (5 samples, 0.02%)__sk_mem_reduce_allocated (3 samples, 0.01%)__slab_free (8 samples, 0.04%)__free_pages_ok (7 samples, 0.03%)free_one_page (7 samples, 0.03%)_raw_spin_lock (7 samples, 0.03%)native_queued_spin_lock_slowpath (7 samples, 0.03%)kmem_cache_free (21 samples, 0.10%)put_cpu_partial (10 samples, 0.05%)unfreeze_partials (9 samples, 0.04%)flush_tlb_func_common.constprop.0 (6 samples, 0.03%)flush_tlb_func_remote (3 samples, 0.01%)_copy_to_iter (285 samples, 1.33%)copy_user_generic_string (281 samples, 1.31%)asm_sysvec_call_function (24 samples, 0.11%)sysvec_call_function (19 samples, 0.09%)asm_call_sysvec_on_stack (19 samples, 0.09%)__sysvec_call_function (19 samples, 0.09%)flush_smp_call_function_queue (18 samples, 0.08%)llist_reverse_order (4 samples, 0.02%)__virt_addr_valid (18 samples, 0.08%)inet_recvmsg (726 samples, 3.39%)ine..udp_recvmsg (726 samples, 3.39%)udp..skb_copy_datagram_iter (429 samples, 2.01%)s..__skb_datagram_iter (429 samples, 2.01%)_..simple_copy_to_iter (106 samples, 0.50%)__check_object_size (106 samples, 0.50%)__get_user_4 (6 samples, 0.03%)move_addr_to_user (8 samples, 0.04%)do_syscall_64 (740 samples, 3.46%)do_..__x64_sys_recvfrom (739 samples, 3.45%)__x..__sys_recvfrom (739 samples, 3.45%)__s..entry_SYSCALL_64_after_hwframe (742 samples, 3.47%)ent..[unknown] (1,799 samples, 8.41%)[unknown]main::recv_decode_assemble_loop (1,799 samples, 8.41%)main::recv_d..std::net::udp::UdpSocket::recv_from (744 samples, 3.48%)std..std::sys_common::net::UdpSocket::recv_from (744 samples, 3.48%)std..std::sys::unix::net::Socket::recv_from (744 samples, 3.48%)std..std::sys::unix::net::Socket::recv_from_with_flags (744 samples, 3.48%)std..__libc_recvfrom (744 samples, 3.48%)__l..recv-decode-0 (1,802 samples, 8.42%)recv-decode-0[anon] (3 samples, 0.01%)std::sys::unix::net::Socket::recv_from_with_flags (3 samples, 0.01%)__libc_recvfrom (3 samples, 0.01%)extent_recycle_extract (4 samples, 0.02%)base_alloc_impl (7 samples, 0.03%)_rjem_je_base_alloc_extent (12 samples, 0.06%)extent_esn_set (5 samples, 0.02%)asm_exc_page_fault (4 samples, 0.02%)exc_page_fault (4 samples, 0.02%)do_user_addr_fault (4 samples, 0.02%)handle_mm_fault (4 samples, 0.02%)wp_page_copy (4 samples, 0.02%)_rjem_je_extent_alloc (13 samples, 0.06%)_rjem_je_extent_alloc (13 samples, 0.06%)malloc_mutex_trylock_final (9 samples, 0.04%)__GI___pthread_mutex_trylock (9 samples, 0.04%)malloc_mutex_lock (10 samples, 0.05%)extent_lock2 (11 samples, 0.05%)mutex_pool_lock2 (11 samples, 0.05%)_rjem_je_extent_alloc_wrapper (36 samples, 0.17%)extent_alloc_retained (36 samples, 0.17%)extent_recycle (36 samples, 0.17%)extent_recycle_split (32 samples, 0.15%)extent_split_interior (31 samples, 0.14%)extent_split_impl (31 samples, 0.14%)asm_exc_page_fault (3 samples, 0.01%)up_read (4 samples, 0.02%)__list_add_valid (3 samples, 0.01%)__pagevec_lru_add_fn (11 samples, 0.05%)lru_add_drain (19 samples, 0.09%)lru_add_drain_cpu (19 samples, 0.09%)pagevec_lru_move_fn (19 samples, 0.09%)flush_tlb_func_common.constprop.0 (6 samples, 0.03%)native_flush_tlb_one_user (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (11 samples, 0.05%)__default_send_IPI_dest_field (11 samples, 0.05%)on_each_cpu_cond_mask (77 samples, 0.36%)smp_call_function_many_cond (77 samples, 0.36%)tlb_is_not_lazy (9 samples, 0.04%)asm_sysvec_call_function (4 samples, 0.02%)__default_send_IPI_dest_field (9 samples, 0.04%)default_send_IPI_mask_sequence_phys (12 samples, 0.06%)flush_tlb_mm_range (181 samples, 0.85%)smp_call_function_many_cond (96 samples, 0.45%)llist_add_batch (10 samples, 0.05%)free_pages_and_swap_cache (3 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)__free_one_page (4 samples, 0.02%)__list_del_entry_valid (3 samples, 0.01%)free_unref_page_list (14 samples, 0.07%)free_pcppages_bulk (10 samples, 0.05%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)uncharge_batch (3 samples, 0.01%)page_counter_uncharge (3 samples, 0.01%)mem_cgroup_uncharge_list (4 samples, 0.02%)tlb_finish_mmu (217 samples, 1.01%)release_pages (29 samples, 0.14%)tlb_gather_mmu (3 samples, 0.01%)__split_huge_pmd (5 samples, 0.02%)pmdp_invalidate (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)__tlb_remove_page_size (14 samples, 0.07%)__get_free_pages (13 samples, 0.06%)__alloc_pages_nodemask (13 samples, 0.06%)get_page_from_freelist (13 samples, 0.06%)prep_new_page (9 samples, 0.04%)kernel_init_free_pages (9 samples, 0.04%)clear_page_rep (9 samples, 0.04%)page_remove_rmap (5 samples, 0.02%)_rjem_je_pages_purge_forced (289 samples, 1.35%)madvise (289 samples, 1.35%)entry_SYSCALL_64_after_hwframe (286 samples, 1.34%)do_syscall_64 (286 samples, 1.34%)__x64_sys_madvise (286 samples, 1.34%)do_madvise.part.0 (286 samples, 1.34%)zap_page_range (280 samples, 1.31%)unmap_page_range (41 samples, 0.19%)sync_mm_rss (3 samples, 0.01%)_rjem_je_extent_heap_first (8 samples, 0.04%)extents_best_fit_locked (10 samples, 0.05%)extents_fit_locked (12 samples, 0.06%)malloc_mutex_lock (6 samples, 0.03%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_recycle_extract (20 samples, 0.09%)_rjem_je_extent_alloc (4 samples, 0.02%)extent_split_impl (10 samples, 0.05%)extent_lock2 (5 samples, 0.02%)mutex_pool_lock2 (5 samples, 0.02%)malloc_mutex_lock (5 samples, 0.02%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)_rjem_je_arena_extent_alloc_large (364 samples, 1.70%)extent_recycle (321 samples, 1.50%)extent_recycle_split (11 samples, 0.05%)extent_split_interior (11 samples, 0.05%)alloc::vec::from_elem (367 samples, 1.72%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (367 samples, 1.72%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (367 samples, 1.72%)alloc::raw_vec::RawVec<T,A>::allocate_in (367 samples, 1.72%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (367 samples, 1.72%)alloc::alloc::Global::alloc_impl (367 samples, 1.72%)alloc::alloc::alloc_zeroed (367 samples, 1.72%)_rjem_calloc (367 samples, 1.72%)imalloc (366 samples, 1.71%)imalloc_body (366 samples, 1.71%)imalloc_no_sample (366 samples, 1.71%)iallocztm (366 samples, 1.71%)arena_malloc (366 samples, 1.71%)tcache_alloc_large (366 samples, 1.71%)_rjem_je_large_palloc (366 samples, 1.71%)down_read_trylock (19 samples, 0.09%)__list_del_entry_valid (5 samples, 0.02%)_raw_spin_lock (21 samples, 0.10%)native_queued_spin_lock_slowpath (21 samples, 0.10%)flush_smp_call_function_queue (3 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)alloc_pages_vma (159 samples, 0.74%)__alloc_pages_nodemask (156 samples, 0.73%)get_page_from_freelist (155 samples, 0.72%)prep_new_page (88 samples, 0.41%)kernel_init_free_pages (85 samples, 0.40%)clear_page_rep (85 samples, 0.40%)flush_tlb_func_remote (3 samples, 0.01%)kernel_init_free_pages (140 samples, 0.65%)clear_page_rep (140 samples, 0.65%)asm_sysvec_call_function (11 samples, 0.05%)sysvec_call_function (8 samples, 0.04%)asm_call_sysvec_on_stack (8 samples, 0.04%)__sysvec_call_function (8 samples, 0.04%)flush_smp_call_function_queue (8 samples, 0.04%)alloc_pages_vma (148 samples, 0.69%)__alloc_pages_nodemask (148 samples, 0.69%)get_page_from_freelist (148 samples, 0.69%)prep_new_page (143 samples, 0.67%)prep_compound_page (3 samples, 0.01%)clear_huge_page (27 samples, 0.13%)clear_subpage (27 samples, 0.13%)clear_page_rep (27 samples, 0.13%)do_huge_pmd_anonymous_page (180 samples, 0.84%)mem_cgroup_charge_statistics.constprop.0 (5 samples, 0.02%)__count_memcg_events.part.0 (5 samples, 0.02%)mem_cgroup_charge (22 samples, 0.10%)try_charge (13 samples, 0.06%)page_counter_try_charge (7 samples, 0.03%)handle_mm_fault (382 samples, 1.79%)h..page_add_new_anon_rmap (5 samples, 0.02%)asm_exc_page_fault (442 samples, 2.07%)a..exc_page_fault (421 samples, 1.97%)e..do_user_addr_fault (421 samples, 1.97%)d..up_read (16 samples, 0.07%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)k2o::decode::decode (601 samples, 2.81%)k2..error_entry (4 samples, 0.02%)<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (973 samples, 4.55%)<k2o:..std::time::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::now (3 samples, 0.01%)alloc::boxed::Box<T>::new (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (13 samples, 0.06%)core::sync::atomic::AtomicPtr<T>::load (9 samples, 0.04%)core::sync::atomic::atomic_load (9 samples, 0.04%)crossbeam_channel::channel::Sender<T>::send (22 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::send (20 samples, 0.09%)crossbeam_channel::flavors::list::Channel<T>::write (7 samples, 0.03%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)cpuset_cpus_allowed (6 samples, 0.03%)kfree (29 samples, 0.14%)flush_tlb_func_common.constprop.0 (4 samples, 0.02%)asm_sysvec_call_function (10 samples, 0.05%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (6 samples, 0.03%)__free_one_page (53 samples, 0.25%)__mod_zone_page_state (4 samples, 0.02%)__list_del_entry_valid (44 samples, 0.21%)free_pcppages_bulk (187 samples, 0.87%)_raw_spin_lock (66 samples, 0.31%)native_queued_spin_lock_slowpath (65 samples, 0.30%)__consume_stateless_skb (268 samples, 1.25%)skb_release_data (239 samples, 1.12%)free_unref_page (211 samples, 0.99%)free_unref_page_commit (5 samples, 0.02%)__skb_try_recv_from_queue (5 samples, 0.02%)__const_udelay (3 samples, 0.01%)amd_pmu_wait_on_overflow (4 samples, 0.02%)__perf_event_task_sched_out (8 samples, 0.04%)amd_pmu_disable_all (7 samples, 0.03%)x86_pmu_disable_all (3 samples, 0.01%)__skb_wait_for_more_packets (11 samples, 0.05%)schedule_timeout (11 samples, 0.05%)schedule (11 samples, 0.05%)__schedule (11 samples, 0.05%)__skb_recv_udp (28 samples, 0.13%)udp_rmem_release (8 samples, 0.04%)__sk_mem_reduce_allocated (6 samples, 0.03%)__slab_free (7 samples, 0.03%)kmem_cache_free (16 samples, 0.07%)put_cpu_partial (6 samples, 0.03%)unfreeze_partials (5 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)lock_sock_nested (3 samples, 0.01%)_raw_spin_lock_bh (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)_copy_to_iter (295 samples, 1.38%)copy_user_generic_string (287 samples, 1.34%)asm_sysvec_call_function (15 samples, 0.07%)sysvec_call_function (10 samples, 0.05%)__virt_addr_valid (19 samples, 0.09%)asm_sysvec_call_function (4 samples, 0.02%)inet_recvmsg (772 samples, 3.61%)inet..udp_recvmsg (771 samples, 3.60%)udp_..skb_copy_datagram_iter (438 samples, 2.05%)s..__skb_datagram_iter (438 samples, 2.05%)_..simple_copy_to_iter (103 samples, 0.48%)__check_object_size (103 samples, 0.48%)move_addr_to_user (4 samples, 0.02%)do_syscall_64 (781 samples, 3.65%)do_s..__x64_sys_recvfrom (781 samples, 3.65%)__x6..__sys_recvfrom (781 samples, 3.65%)__sy..[unknown] (1,793 samples, 8.38%)[unknown]main::recv_decode_assemble_loop (1,792 samples, 8.38%)main::recv_d..std::net::udp::UdpSocket::recv_from (788 samples, 3.68%)std:..std::sys_common::net::UdpSocket::recv_from (788 samples, 3.68%)std:..std::sys::unix::net::Socket::recv_from (788 samples, 3.68%)std:..std::sys::unix::net::Socket::recv_from_with_flags (788 samples, 3.68%)std:..__libc_recvfrom (787 samples, 3.68%)__li..entry_SYSCALL_64_after_hwframe (782 samples, 3.66%)entr..recv-decode-1 (1,799 samples, 8.41%)recv-decode-1[anon] (4 samples, 0.02%)std::sys::unix::net::Socket::recv_from_with_flags (4 samples, 0.02%)__libc_recvfrom (4 samples, 0.02%)base_alloc_impl (10 samples, 0.05%)_rjem_je_extent_alloc (16 samples, 0.07%)_rjem_je_extent_alloc (16 samples, 0.07%)_rjem_je_base_alloc_extent (16 samples, 0.07%)extent_esn_set (5 samples, 0.02%)asm_exc_page_fault (5 samples, 0.02%)exc_page_fault (5 samples, 0.02%)do_user_addr_fault (5 samples, 0.02%)handle_mm_fault (5 samples, 0.02%)wp_page_copy (5 samples, 0.02%)ptep_clear_flush (5 samples, 0.02%)flush_tlb_mm_range (5 samples, 0.02%)on_each_cpu_cond_mask (5 samples, 0.02%)smp_call_function_many_cond (5 samples, 0.02%)extent_lock2 (10 samples, 0.05%)mutex_pool_lock2 (10 samples, 0.05%)malloc_mutex_lock (10 samples, 0.05%)malloc_mutex_trylock_final (10 samples, 0.05%)__GI___pthread_mutex_trylock (10 samples, 0.05%)extent_recycle (34 samples, 0.16%)extent_recycle_split (33 samples, 0.15%)extent_split_interior (32 samples, 0.15%)extent_split_impl (32 samples, 0.15%)_rjem_je_extent_alloc_wrapper (36 samples, 0.17%)extent_alloc_retained (36 samples, 0.17%)asm_exc_page_fault (3 samples, 0.01%)__mod_lruvec_state (3 samples, 0.01%)__pagevec_lru_add_fn (12 samples, 0.06%)_raw_spin_lock_irqsave (7 samples, 0.03%)_raw_spin_unlock_irqrestore (7 samples, 0.03%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)lru_add_drain (30 samples, 0.14%)lru_add_drain_cpu (30 samples, 0.14%)pagevec_lru_move_fn (30 samples, 0.14%)flush_tlb_func_common.constprop.0 (9 samples, 0.04%)native_flush_tlb_one_user (5 samples, 0.02%)default_send_IPI_mask_sequence_phys (12 samples, 0.06%)__default_send_IPI_dest_field (12 samples, 0.06%)on_each_cpu_cond_mask (68 samples, 0.32%)smp_call_function_many_cond (68 samples, 0.32%)tlb_is_not_lazy (7 samples, 0.03%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__default_send_IPI_dest_field (11 samples, 0.05%)default_send_IPI_mask_sequence_phys (14 samples, 0.07%)asm_sysvec_call_function (3 samples, 0.01%)flush_tlb_mm_range (173 samples, 0.81%)smp_call_function_many_cond (95 samples, 0.44%)llist_add_batch (8 samples, 0.04%)__free_one_page (3 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)free_unref_page_list (10 samples, 0.05%)free_pcppages_bulk (7 samples, 0.03%)tlb_finish_mmu (198 samples, 0.93%)release_pages (20 samples, 0.09%)mem_cgroup_uncharge_list (4 samples, 0.02%)tlb_gather_mmu (3 samples, 0.01%)__tlb_remove_page_size (16 samples, 0.07%)__get_free_pages (16 samples, 0.07%)__alloc_pages_nodemask (16 samples, 0.07%)get_page_from_freelist (16 samples, 0.07%)prep_new_page (13 samples, 0.06%)kernel_init_free_pages (13 samples, 0.06%)clear_page_rep (13 samples, 0.06%)__mod_lruvec_state (3 samples, 0.01%)page_remove_rmap (6 samples, 0.03%)sync_mm_rss (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (278 samples, 1.30%)do_syscall_64 (278 samples, 1.30%)__x64_sys_madvise (277 samples, 1.29%)do_madvise.part.0 (277 samples, 1.29%)zap_page_range (272 samples, 1.27%)unmap_page_range (38 samples, 0.18%)_rjem_je_pages_purge_forced (285 samples, 1.33%)madvise (285 samples, 1.33%)extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)extent_list_remove (3 samples, 0.01%)extents_best_fit_locked (5 samples, 0.02%)extents_fit_locked (6 samples, 0.03%)extent_recycle_extract (13 samples, 0.06%)malloc_mutex_lock (4 samples, 0.02%)malloc_mutex_trylock_final (4 samples, 0.02%)__GI___pthread_mutex_trylock (4 samples, 0.02%)_rjem_je_extent_avail_first (5 samples, 0.02%)_rjem_je_extent_alloc (7 samples, 0.03%)extent_split_impl (13 samples, 0.06%)alloc::vec::from_elem (362 samples, 1.69%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (362 samples, 1.69%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (362 samples, 1.69%)alloc::raw_vec::RawVec<T,A>::allocate_in (362 samples, 1.69%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (362 samples, 1.69%)alloc::alloc::Global::alloc_impl (362 samples, 1.69%)alloc::alloc::alloc_zeroed (362 samples, 1.69%)_rjem_calloc (362 samples, 1.69%)imalloc (362 samples, 1.69%)imalloc_body (361 samples, 1.69%)imalloc_no_sample (361 samples, 1.69%)iallocztm (361 samples, 1.69%)arena_malloc (361 samples, 1.69%)tcache_alloc_large (357 samples, 1.67%)_rjem_je_large_palloc (357 samples, 1.67%)_rjem_je_arena_extent_alloc_large (355 samples, 1.66%)extent_recycle (315 samples, 1.47%)extent_recycle_split (15 samples, 0.07%)extent_split_interior (14 samples, 0.07%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)down_read_trylock (22 samples, 0.10%)__list_del_entry_valid (11 samples, 0.05%)_raw_spin_lock (32 samples, 0.15%)native_queued_spin_lock_slowpath (31 samples, 0.14%)__alloc_pages_nodemask (167 samples, 0.78%)get_page_from_freelist (164 samples, 0.77%)prep_new_page (94 samples, 0.44%)kernel_init_free_pages (93 samples, 0.43%)clear_page_rep (89 samples, 0.42%)asm_sysvec_call_function (4 samples, 0.02%)alloc_pages_vma (170 samples, 0.79%)alloc_pages_vma (143 samples, 0.67%)__alloc_pages_nodemask (143 samples, 0.67%)get_page_from_freelist (143 samples, 0.67%)prep_new_page (135 samples, 0.63%)kernel_init_free_pages (135 samples, 0.63%)clear_page_rep (135 samples, 0.63%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)flush_tlb_func_remote (3 samples, 0.01%)clear_huge_page (36 samples, 0.17%)clear_subpage (36 samples, 0.17%)clear_page_rep (35 samples, 0.16%)do_huge_pmd_anonymous_page (180 samples, 0.84%)mem_cgroup_charge_statistics.constprop.0 (6 samples, 0.03%)__count_memcg_events.part.0 (6 samples, 0.03%)mem_cgroup_charge (14 samples, 0.07%)try_charge (5 samples, 0.02%)handle_mm_fault (385 samples, 1.80%)h..page_add_new_anon_rmap (7 samples, 0.03%)__mod_lruvec_state (3 samples, 0.01%)exc_page_fault (443 samples, 2.07%)e..do_user_addr_fault (442 samples, 2.07%)d..up_read (26 samples, 0.12%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_exc_page_fault (458 samples, 2.14%)a..asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)error_entry (7 samples, 0.03%)sync_regs (5 samples, 0.02%)k2o::decode::decode (633 samples, 2.96%)k2o..<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (999 samples, 4.67%)<k2o:..std::time::Instant::now (4 samples, 0.02%)std::sys::unix::time::inner::Instant::now (4 samples, 0.02%)std::sys::unix::time::inner::now (4 samples, 0.02%)__clock_gettime (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (11 samples, 0.05%)core::sync::atomic::AtomicPtr<T>::load (9 samples, 0.04%)core::sync::atomic::atomic_load (9 samples, 0.04%)crossbeam_channel::channel::Sender<T>::send (20 samples, 0.09%)crossbeam_channel::flavors::list::Channel<T>::send (19 samples, 0.09%)crossbeam_channel::flavors::list::Channel<T>::write (7 samples, 0.03%)k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)__set_cpus_allowed_ptr (6 samples, 0.03%)kfree (28 samples, 0.13%)asm_sysvec_call_function (10 samples, 0.05%)sysvec_call_function (9 samples, 0.04%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (9 samples, 0.04%)__list_del_entry_valid (4 samples, 0.02%)__free_one_page (51 samples, 0.24%)__list_del_entry_valid (29 samples, 0.14%)free_pcppages_bulk (151 samples, 0.71%)_raw_spin_lock (60 samples, 0.28%)native_queued_spin_lock_slowpath (58 samples, 0.27%)__consume_stateless_skb (227 samples, 1.06%)skb_release_data (199 samples, 0.93%)free_unref_page (179 samples, 0.84%)free_unref_page_commit (3 samples, 0.01%)__skb_wait_for_more_packets (3 samples, 0.01%)schedule_timeout (3 samples, 0.01%)schedule (3 samples, 0.01%)__schedule (3 samples, 0.01%)__skb_recv_udp (13 samples, 0.06%)udp_rmem_release (7 samples, 0.03%)__sk_mem_reduce_allocated (5 samples, 0.02%)__slab_free (6 samples, 0.03%)put_cpu_partial (7 samples, 0.03%)unfreeze_partials (6 samples, 0.03%)__free_pages_ok (6 samples, 0.03%)free_one_page (6 samples, 0.03%)_raw_spin_lock (6 samples, 0.03%)native_queued_spin_lock_slowpath (6 samples, 0.03%)kmem_cache_free (17 samples, 0.08%)lock_sock_nested (4 samples, 0.02%)_raw_spin_lock_bh (4 samples, 0.02%)release_sock (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (5 samples, 0.02%)native_flush_tlb_one_user (4 samples, 0.02%)flush_tlb_func_remote (3 samples, 0.01%)_copy_to_iter (325 samples, 1.52%)copy_user_generic_string (321 samples, 1.50%)asm_sysvec_call_function (20 samples, 0.09%)sysvec_call_function (14 samples, 0.07%)asm_call_sysvec_on_stack (14 samples, 0.07%)__sysvec_call_function (14 samples, 0.07%)flush_smp_call_function_queue (14 samples, 0.07%)__virt_addr_valid (10 samples, 0.05%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)inet_recvmsg (750 samples, 3.51%)ine..udp_recvmsg (750 samples, 3.51%)udp..skb_copy_datagram_iter (474 samples, 2.22%)s..__skb_datagram_iter (474 samples, 2.22%)_..simple_copy_to_iter (115 samples, 0.54%)__check_object_size (115 samples, 0.54%)__get_user_4 (3 samples, 0.01%)move_addr_to_user (8 samples, 0.04%)_copy_to_user (4 samples, 0.02%)copy_user_generic_string (4 samples, 0.02%)aa_sk_perm (3 samples, 0.01%)sock_recvmsg (4 samples, 0.02%)security_socket_recvmsg (4 samples, 0.02%)entry_SYSCALL_64_after_hwframe (765 samples, 3.58%)entr..do_syscall_64 (765 samples, 3.58%)do_s..__x64_sys_recvfrom (765 samples, 3.58%)__x6..__sys_recvfrom (765 samples, 3.58%)__sy..sockfd_lookup_light (3 samples, 0.01%)__fget_light (3 samples, 0.01%)recv-decode-2 (1,800 samples, 8.41%)recv-decode-2[unknown] (1,796 samples, 8.39%)[unknown]main::recv_decode_assemble_loop (1,796 samples, 8.39%)main::recv_d..std::net::udp::UdpSocket::recv_from (770 samples, 3.60%)std:..std::sys_common::net::UdpSocket::recv_from (769 samples, 3.59%)std:..std::sys::unix::net::Socket::recv_from (769 samples, 3.59%)std:..std::sys::unix::net::Socket::recv_from_with_flags (769 samples, 3.59%)std:..__libc_recvfrom (769 samples, 3.59%)__li..[anon] (3 samples, 0.01%)std::sys::unix::net::Socket::recv_from_with_flags (3 samples, 0.01%)__libc_recvfrom (3 samples, 0.01%)extent_grow_retained (3 samples, 0.01%)extent_alloc_default_impl (3 samples, 0.01%)extent_alloc_core (3 samples, 0.01%)_rjem_je_extent_alloc_mmap (3 samples, 0.01%)_rjem_je_pages_map (3 samples, 0.01%)os_pages_map (3 samples, 0.01%)mmap64 (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)vm_mmap_pgoff (3 samples, 0.01%)base_alloc_impl (6 samples, 0.03%)alloc_pages_vma (3 samples, 0.01%)__alloc_pages_nodemask (3 samples, 0.01%)get_page_from_freelist (3 samples, 0.01%)_rjem_je_base_alloc_extent (14 samples, 0.07%)extent_esn_set (8 samples, 0.04%)asm_exc_page_fault (8 samples, 0.04%)exc_page_fault (8 samples, 0.04%)do_user_addr_fault (8 samples, 0.04%)handle_mm_fault (8 samples, 0.04%)wp_page_copy (8 samples, 0.04%)ptep_clear_flush (5 samples, 0.02%)flush_tlb_mm_range (5 samples, 0.02%)on_each_cpu_cond_mask (5 samples, 0.02%)smp_call_function_many_cond (5 samples, 0.02%)_rjem_je_extent_alloc (15 samples, 0.07%)_rjem_je_extent_alloc (15 samples, 0.07%)malloc_mutex_lock (13 samples, 0.06%)malloc_mutex_trylock_final (13 samples, 0.06%)__GI___pthread_mutex_trylock (13 samples, 0.06%)extent_lock2 (14 samples, 0.07%)mutex_pool_lock2 (14 samples, 0.07%)extent_recycle (34 samples, 0.16%)extent_recycle_split (32 samples, 0.15%)extent_split_interior (31 samples, 0.14%)extent_split_impl (31 samples, 0.14%)extent_alloc_retained (39 samples, 0.18%)_rjem_je_extent_alloc_wrapper (40 samples, 0.19%)asm_exc_page_fault (4 samples, 0.02%)__list_add_valid (3 samples, 0.01%)__pagevec_lru_add_fn (11 samples, 0.05%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)lru_add_drain (23 samples, 0.11%)lru_add_drain_cpu (23 samples, 0.11%)pagevec_lru_move_fn (23 samples, 0.11%)release_pages (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (15 samples, 0.07%)__default_send_IPI_dest_field (15 samples, 0.07%)on_each_cpu_cond_mask (67 samples, 0.31%)smp_call_function_many_cond (65 samples, 0.30%)tlb_is_not_lazy (5 samples, 0.02%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)llist_reverse_order (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (14 samples, 0.07%)__default_send_IPI_dest_field (14 samples, 0.07%)flush_tlb_mm_range (182 samples, 0.85%)smp_call_function_many_cond (111 samples, 0.52%)llist_add_batch (4 samples, 0.02%)_raw_spin_lock_irqsave (4 samples, 0.02%)__free_one_page (5 samples, 0.02%)free_pcppages_bulk (9 samples, 0.04%)free_unref_page_list (10 samples, 0.05%)tlb_finish_mmu (209 samples, 0.98%)release_pages (23 samples, 0.11%)mem_cgroup_uncharge_list (4 samples, 0.02%)uncharge_batch (4 samples, 0.02%)page_counter_uncharge (4 samples, 0.02%)__tlb_remove_page_size (12 samples, 0.06%)__get_free_pages (12 samples, 0.06%)__alloc_pages_nodemask (12 samples, 0.06%)get_page_from_freelist (12 samples, 0.06%)prep_new_page (8 samples, 0.04%)kernel_init_free_pages (8 samples, 0.04%)clear_page_rep (8 samples, 0.04%)page_remove_rmap (4 samples, 0.02%)sync_mm_rss (5 samples, 0.02%)__x64_sys_madvise (274 samples, 1.28%)do_madvise.part.0 (274 samples, 1.28%)zap_page_range (270 samples, 1.26%)unmap_page_range (35 samples, 0.16%)do_syscall_64 (275 samples, 1.29%)entry_SYSCALL_64_after_hwframe (276 samples, 1.29%)_rjem_je_pages_purge_forced (281 samples, 1.31%)madvise (281 samples, 1.31%)extents_best_fit_locked (5 samples, 0.02%)_rjem_je_extent_heap_first (5 samples, 0.02%)extents_fit_locked (7 samples, 0.03%)malloc_mutex_lock (4 samples, 0.02%)malloc_mutex_trylock_final (4 samples, 0.02%)__GI___pthread_mutex_trylock (4 samples, 0.02%)extent_recycle_extract (12 samples, 0.06%)_rjem_je_arena_extent_alloc_large (344 samples, 1.61%)extent_recycle (299 samples, 1.40%)extent_recycle_split (6 samples, 0.03%)extent_split_interior (6 samples, 0.03%)extent_split_impl (6 samples, 0.03%)_rjem_je_large_palloc (352 samples, 1.65%)arena_decay_tick (8 samples, 0.04%)arena_decay_ticks (8 samples, 0.04%)_rjem_je_arena_decay (8 samples, 0.04%)arena_decay_dirty (8 samples, 0.04%)arena_decay_impl (8 samples, 0.04%)arena_maybe_decay (8 samples, 0.04%)arena_maybe_decay (8 samples, 0.04%)arena_decay_try_purge (8 samples, 0.04%)arena_decay_try_purge (8 samples, 0.04%)arena_decay_to_limit (8 samples, 0.04%)arena_decay_stashed (8 samples, 0.04%)_rjem_je_extent_purge_lazy_wrapper (8 samples, 0.04%)extent_purge_lazy_impl (8 samples, 0.04%)_rjem_je_pages_purge_lazy (8 samples, 0.04%)_rjem_je_pages_purge_lazy (8 samples, 0.04%)madvise (8 samples, 0.04%)entry_SYSCALL_64_after_hwframe (8 samples, 0.04%)do_syscall_64 (8 samples, 0.04%)__x64_sys_madvise (8 samples, 0.04%)do_madvise.part.0 (8 samples, 0.04%)madvise_free_single_vma (8 samples, 0.04%)walk_page_range (8 samples, 0.04%)__walk_page_range (8 samples, 0.04%)madvise_free_pte_range (8 samples, 0.04%)split_huge_page_to_list (8 samples, 0.04%)try_to_unmap (6 samples, 0.03%)rmap_walk_anon (6 samples, 0.03%)try_to_unmap_one (6 samples, 0.03%)ptep_clear_flush (6 samples, 0.03%)flush_tlb_mm_range (6 samples, 0.03%)on_each_cpu_cond_mask (6 samples, 0.03%)smp_call_function_many_cond (6 samples, 0.03%)alloc::vec::from_elem (357 samples, 1.67%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (357 samples, 1.67%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (357 samples, 1.67%)alloc::raw_vec::RawVec<T,A>::allocate_in (357 samples, 1.67%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (357 samples, 1.67%)alloc::alloc::Global::alloc_impl (357 samples, 1.67%)alloc::alloc::alloc_zeroed (357 samples, 1.67%)_rjem_calloc (354 samples, 1.65%)imalloc (354 samples, 1.65%)imalloc_body (354 samples, 1.65%)imalloc_no_sample (354 samples, 1.65%)iallocztm (354 samples, 1.65%)arena_malloc (354 samples, 1.65%)tcache_alloc_large (353 samples, 1.65%)down_read_trylock (20 samples, 0.09%)__count_memcg_events.part.0 (4 samples, 0.02%)__list_del_entry_valid (10 samples, 0.05%)_raw_spin_lock (16 samples, 0.07%)native_queued_spin_lock_slowpath (13 samples, 0.06%)__alloc_pages_nodemask (149 samples, 0.70%)get_page_from_freelist (147 samples, 0.69%)prep_new_page (77 samples, 0.36%)kernel_init_free_pages (76 samples, 0.36%)clear_page_rep (74 samples, 0.35%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)alloc_pages_vma (153 samples, 0.72%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)kernel_init_free_pages (147 samples, 0.69%)clear_page_rep (146 samples, 0.68%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)alloc_pages_vma (154 samples, 0.72%)__alloc_pages_nodemask (154 samples, 0.72%)get_page_from_freelist (154 samples, 0.72%)prep_new_page (148 samples, 0.69%)clear_huge_page (52 samples, 0.24%)clear_subpage (52 samples, 0.24%)clear_page_rep (52 samples, 0.24%)asm_sysvec_call_function (4 samples, 0.02%)do_huge_pmd_anonymous_page (210 samples, 0.98%)mem_cgroup_charge_statistics.constprop.0 (5 samples, 0.02%)__count_memcg_events.part.0 (5 samples, 0.02%)mem_cgroup_charge (20 samples, 0.09%)try_charge (8 samples, 0.04%)page_counter_try_charge (4 samples, 0.02%)handle_mm_fault (410 samples, 1.92%)h..page_add_new_anon_rmap (6 samples, 0.03%)__mod_memcg_lruvec_state (3 samples, 0.01%)exc_page_fault (457 samples, 2.14%)e..do_user_addr_fault (457 samples, 2.14%)d..up_read (22 samples, 0.10%)asm_exc_page_fault (482 samples, 2.25%)a..flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)error_entry (9 samples, 0.04%)sync_regs (7 samples, 0.03%)k2o::decode::decode (669 samples, 3.13%)k2o..<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (1,028 samples, 4.81%)<k2o::..alloc::boxed::Box<T>::new (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (14 samples, 0.07%)core::sync::atomic::AtomicPtr<T>::load (10 samples, 0.05%)core::sync::atomic::atomic_load (10 samples, 0.05%)crossbeam_channel::channel::Sender<T>::send (26 samples, 0.12%)crossbeam_channel::flavors::list::Channel<T>::send (26 samples, 0.12%)crossbeam_channel::flavors::list::Channel<T>::write (12 samples, 0.06%)k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)cpuset_cpus_allowed (6 samples, 0.03%)_raw_spin_lock_irqsave (6 samples, 0.03%)kfree (21 samples, 0.10%)asm_sysvec_call_function (8 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (6 samples, 0.03%)__free_one_page (36 samples, 0.17%)__mod_zone_page_state (3 samples, 0.01%)__list_del_entry_valid (32 samples, 0.15%)free_pcppages_bulk (135 samples, 0.63%)_raw_spin_lock (58 samples, 0.27%)native_queued_spin_lock_slowpath (53 samples, 0.25%)__consume_stateless_skb (211 samples, 0.99%)skb_release_data (190 samples, 0.89%)free_unref_page (158 samples, 0.74%)__perf_event_task_sched_out (5 samples, 0.02%)amd_pmu_disable_all (5 samples, 0.02%)x86_pmu_disable_all (3 samples, 0.01%)__skb_wait_for_more_packets (9 samples, 0.04%)schedule_timeout (8 samples, 0.04%)schedule (8 samples, 0.04%)__schedule (8 samples, 0.04%)__skb_recv_udp (16 samples, 0.07%)udp_rmem_release (4 samples, 0.02%)__sk_mem_reduce_allocated (4 samples, 0.02%)mem_cgroup_uncharge_skmem (3 samples, 0.01%)__mod_memcg_state.part.0 (3 samples, 0.01%)__slab_free (3 samples, 0.01%)kmem_cache_free (12 samples, 0.06%)put_cpu_partial (6 samples, 0.03%)unfreeze_partials (4 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (7 samples, 0.03%)native_flush_tlb_one_user (5 samples, 0.02%)flush_smp_call_function_queue (15 samples, 0.07%)llist_reverse_order (3 samples, 0.01%)asm_call_sysvec_on_stack (16 samples, 0.07%)__sysvec_call_function (16 samples, 0.07%)_copy_to_iter (329 samples, 1.54%)copy_user_generic_string (329 samples, 1.54%)asm_sysvec_call_function (23 samples, 0.11%)sysvec_call_function (17 samples, 0.08%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__virt_addr_valid (8 samples, 0.04%)inet_recvmsg (716 samples, 3.35%)ine..udp_recvmsg (716 samples, 3.35%)udp..skb_copy_datagram_iter (467 samples, 2.18%)s..__skb_datagram_iter (466 samples, 2.18%)_..simple_copy_to_iter (107 samples, 0.50%)__check_object_size (106 samples, 0.50%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)move_addr_to_user (4 samples, 0.02%)__x64_sys_recvfrom (727 samples, 3.40%)__x..__sys_recvfrom (726 samples, 3.39%)__s..entry_SYSCALL_64_after_hwframe (728 samples, 3.40%)ent..do_syscall_64 (728 samples, 3.40%)do_..__libc_recvfrom (733 samples, 3.43%)__l..[unknown] (1,794 samples, 8.39%)[unknown]main::recv_decode_assemble_loop (1,794 samples, 8.39%)main::recv_d..std::net::udp::UdpSocket::recv_from (734 samples, 3.43%)std..std::sys_common::net::UdpSocket::recv_from (734 samples, 3.43%)std..std::sys::unix::net::Socket::recv_from (734 samples, 3.43%)std..std::sys::unix::net::Socket::recv_from_with_flags (734 samples, 3.43%)std..recv-decode-3 (1,798 samples, 8.40%)recv-decode-3[anon] (5 samples, 0.02%)std::sys::unix::net::Socket::recv_from_with_flags (5 samples, 0.02%)__libc_recvfrom (5 samples, 0.02%)asm_sysvec_call_function (3 samples, 0.01%)base_alloc_impl (5 samples, 0.02%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)alloc_pages_vma (6 samples, 0.03%)__alloc_pages_nodemask (6 samples, 0.03%)get_page_from_freelist (6 samples, 0.03%)handle_mm_fault (9 samples, 0.04%)wp_page_copy (8 samples, 0.04%)_rjem_je_extent_alloc (16 samples, 0.07%)_rjem_je_extent_alloc (16 samples, 0.07%)_rjem_je_base_alloc_extent (16 samples, 0.07%)extent_esn_set (11 samples, 0.05%)asm_exc_page_fault (10 samples, 0.05%)exc_page_fault (10 samples, 0.05%)do_user_addr_fault (10 samples, 0.05%)extent_lock2 (9 samples, 0.04%)mutex_pool_lock2 (9 samples, 0.04%)malloc_mutex_lock (9 samples, 0.04%)malloc_mutex_trylock_final (9 samples, 0.04%)__GI___pthread_mutex_trylock (8 samples, 0.04%)_rjem_je_extent_alloc_wrapper (31 samples, 0.14%)extent_alloc_retained (31 samples, 0.14%)extent_recycle (29 samples, 0.14%)extent_recycle_split (28 samples, 0.13%)extent_split_interior (28 samples, 0.13%)extent_split_impl (28 samples, 0.13%)down_read (3 samples, 0.01%)up_read (3 samples, 0.01%)__mod_memcg_lruvec_state (4 samples, 0.02%)__mod_memcg_state.part.0 (3 samples, 0.01%)__pagevec_lru_add_fn (8 samples, 0.04%)_raw_spin_lock_irqsave (5 samples, 0.02%)native_queued_spin_lock_slowpath (4 samples, 0.02%)lru_add_drain (15 samples, 0.07%)lru_add_drain_cpu (15 samples, 0.07%)pagevec_lru_move_fn (14 samples, 0.07%)flush_tlb_func_common.constprop.0 (6 samples, 0.03%)native_flush_tlb_one_user (5 samples, 0.02%)default_send_IPI_mask_sequence_phys (9 samples, 0.04%)__default_send_IPI_dest_field (9 samples, 0.04%)on_each_cpu_cond_mask (78 samples, 0.36%)smp_call_function_many_cond (77 samples, 0.36%)tlb_is_not_lazy (7 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)__default_send_IPI_dest_field (10 samples, 0.05%)default_send_IPI_mask_sequence_phys (11 samples, 0.05%)flush_tlb_mm_range (184 samples, 0.86%)smp_call_function_many_cond (99 samples, 0.46%)llist_add_batch (8 samples, 0.04%)_raw_spin_lock_irqsave (4 samples, 0.02%)__free_one_page (3 samples, 0.01%)free_unref_page_list (11 samples, 0.05%)free_pcppages_bulk (8 samples, 0.04%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)tlb_finish_mmu (215 samples, 1.00%)release_pages (24 samples, 0.11%)mem_cgroup_uncharge_list (5 samples, 0.02%)uncharge_batch (5 samples, 0.02%)page_counter_uncharge (5 samples, 0.02%)tlb_gather_mmu (3 samples, 0.01%)pmdp_invalidate (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)__split_huge_pmd (6 samples, 0.03%)__alloc_pages_nodemask (18 samples, 0.08%)get_page_from_freelist (18 samples, 0.08%)prep_new_page (11 samples, 0.05%)kernel_init_free_pages (11 samples, 0.05%)clear_page_rep (11 samples, 0.05%)__tlb_remove_page_size (21 samples, 0.10%)__get_free_pages (20 samples, 0.09%)page_remove_rmap (6 samples, 0.03%)_rjem_je_pages_purge_forced (287 samples, 1.34%)madvise (287 samples, 1.34%)entry_SYSCALL_64_after_hwframe (284 samples, 1.33%)do_syscall_64 (284 samples, 1.33%)__x64_sys_madvise (284 samples, 1.33%)do_madvise.part.0 (284 samples, 1.33%)zap_page_range (278 samples, 1.30%)unmap_page_range (45 samples, 0.21%)extent_size_quantize_ceil (3 samples, 0.01%)extent_size_quantize_floor (3 samples, 0.01%)extents_best_fit_locked (6 samples, 0.03%)extents_fit_locked (7 samples, 0.03%)malloc_mutex_lock (7 samples, 0.03%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_recycle_extract (15 samples, 0.07%)_rjem_je_extent_alloc (3 samples, 0.01%)_rjem_je_arena_extent_alloc_large (342 samples, 1.60%)extent_recycle (308 samples, 1.44%)extent_recycle_split (5 samples, 0.02%)extent_split_interior (5 samples, 0.02%)extent_split_impl (5 samples, 0.02%)imalloc_body (346 samples, 1.62%)imalloc_no_sample (346 samples, 1.62%)iallocztm (346 samples, 1.62%)arena_malloc (346 samples, 1.62%)tcache_alloc_large (345 samples, 1.61%)_rjem_je_large_palloc (345 samples, 1.61%)arena_decay_tick (3 samples, 0.01%)arena_decay_ticks (3 samples, 0.01%)_rjem_je_arena_decay (3 samples, 0.01%)arena_decay_dirty (3 samples, 0.01%)arena_decay_impl (3 samples, 0.01%)arena_maybe_decay (3 samples, 0.01%)arena_maybe_decay (3 samples, 0.01%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_to_limit (3 samples, 0.01%)arena_decay_stashed (3 samples, 0.01%)_rjem_je_extent_purge_lazy_wrapper (3 samples, 0.01%)extent_purge_lazy_impl (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)madvise (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_madvise (3 samples, 0.01%)do_madvise.part.0 (3 samples, 0.01%)madvise_free_single_vma (3 samples, 0.01%)walk_page_range (3 samples, 0.01%)__walk_page_range (3 samples, 0.01%)alloc::vec::from_elem (350 samples, 1.64%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (350 samples, 1.64%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (349 samples, 1.63%)alloc::raw_vec::RawVec<T,A>::allocate_in (349 samples, 1.63%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (349 samples, 1.63%)alloc::alloc::Global::alloc_impl (349 samples, 1.63%)alloc::alloc::alloc_zeroed (349 samples, 1.63%)_rjem_calloc (347 samples, 1.62%)imalloc (347 samples, 1.62%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)down_read_trylock (24 samples, 0.11%)__count_memcg_events.part.0 (3 samples, 0.01%)__list_del_entry_valid (7 samples, 0.03%)_raw_spin_lock (22 samples, 0.10%)native_queued_spin_lock_slowpath (22 samples, 0.10%)flush_tlb_func_remote (3 samples, 0.01%)alloc_pages_vma (149 samples, 0.70%)__alloc_pages_nodemask (148 samples, 0.69%)get_page_from_freelist (143 samples, 0.67%)prep_new_page (80 samples, 0.37%)kernel_init_free_pages (80 samples, 0.37%)clear_page_rep (77 samples, 0.36%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)_raw_spin_lock_irqsave (5 samples, 0.02%)native_queued_spin_lock_slowpath (5 samples, 0.02%)kernel_init_free_pages (169 samples, 0.79%)clear_page_rep (169 samples, 0.79%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)llist_reverse_order (3 samples, 0.01%)alloc_pages_vma (180 samples, 0.84%)__alloc_pages_nodemask (180 samples, 0.84%)get_page_from_freelist (180 samples, 0.84%)prep_new_page (170 samples, 0.79%)clear_huge_page (49 samples, 0.23%)clear_subpage (46 samples, 0.22%)clear_page_rep (45 samples, 0.21%)do_huge_pmd_anonymous_page (233 samples, 1.09%)get_mem_cgroup_from_mm (3 samples, 0.01%)mem_cgroup_charge_statistics.constprop.0 (5 samples, 0.02%)__count_memcg_events.part.0 (4 samples, 0.02%)mem_cgroup_charge (23 samples, 0.11%)try_charge (10 samples, 0.05%)page_counter_try_charge (4 samples, 0.02%)handle_mm_fault (433 samples, 2.02%)h..page_add_new_anon_rmap (8 samples, 0.04%)asm_exc_page_fault (496 samples, 2.32%)a..exc_page_fault (485 samples, 2.27%)e..do_user_addr_fault (483 samples, 2.26%)d..up_read (19 samples, 0.09%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)k2o::decode::decode (652 samples, 3.05%)k2o..<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (1,007 samples, 4.71%)<k2o:..std::time::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::now (3 samples, 0.01%)__clock_gettime (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (9 samples, 0.04%)core::sync::atomic::AtomicPtr<T>::load (7 samples, 0.03%)core::sync::atomic::atomic_load (7 samples, 0.03%)crossbeam_channel::channel::Sender<T>::send (25 samples, 0.12%)crossbeam_channel::flavors::list::Channel<T>::send (24 samples, 0.11%)crossbeam_channel::flavors::list::Channel<T>::write (15 samples, 0.07%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)__set_cpus_allowed_ptr (6 samples, 0.03%)stop_one_cpu (6 samples, 0.03%)_cond_resched (6 samples, 0.03%)__schedule (6 samples, 0.03%)finish_task_switch (6 samples, 0.03%)__mmdrop (6 samples, 0.03%)pgd_free (6 samples, 0.03%)__list_del_entry_valid (6 samples, 0.03%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)kfree (30 samples, 0.14%)asm_sysvec_call_function (11 samples, 0.05%)sysvec_call_function (10 samples, 0.05%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (10 samples, 0.05%)__free_one_page (56 samples, 0.26%)__mod_zone_page_state (3 samples, 0.01%)__list_del_entry_valid (29 samples, 0.14%)free_pcppages_bulk (170 samples, 0.79%)_raw_spin_lock (71 samples, 0.33%)native_queued_spin_lock_slowpath (67 samples, 0.31%)__consume_stateless_skb (263 samples, 1.23%)skb_release_data (233 samples, 1.09%)free_unref_page (197 samples, 0.92%)__const_udelay (3 samples, 0.01%)amd_pmu_wait_on_overflow (6 samples, 0.03%)__perf_event_task_sched_out (9 samples, 0.04%)amd_pmu_disable_all (8 samples, 0.04%)__skb_wait_for_more_packets (11 samples, 0.05%)schedule_timeout (11 samples, 0.05%)schedule (11 samples, 0.05%)__schedule (11 samples, 0.05%)__sk_mem_reduce_allocated (4 samples, 0.02%)__skb_recv_udp (22 samples, 0.10%)udp_rmem_release (7 samples, 0.03%)__slab_free (6 samples, 0.03%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)kmem_cache_free (17 samples, 0.08%)put_cpu_partial (6 samples, 0.03%)unfreeze_partials (5 samples, 0.02%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)native_flush_tlb_one_user (3 samples, 0.01%)flush_tlb_func_remote (7 samples, 0.03%)_copy_to_iter (287 samples, 1.34%)copy_user_generic_string (284 samples, 1.33%)asm_sysvec_call_function (20 samples, 0.09%)sysvec_call_function (18 samples, 0.08%)asm_call_sysvec_on_stack (18 samples, 0.08%)__sysvec_call_function (18 samples, 0.08%)flush_smp_call_function_queue (17 samples, 0.08%)__virt_addr_valid (9 samples, 0.04%)inet_recvmsg (744 samples, 3.48%)ine..udp_recvmsg (744 samples, 3.48%)udp..skb_copy_datagram_iter (431 samples, 2.01%)s..__skb_datagram_iter (431 samples, 2.01%)_..simple_copy_to_iter (107 samples, 0.50%)__check_object_size (107 samples, 0.50%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)move_addr_to_user (6 samples, 0.03%)sock_recvmsg (3 samples, 0.01%)security_socket_recvmsg (3 samples, 0.01%)aa_sk_perm (3 samples, 0.01%)[unknown] (1,803 samples, 8.43%)[unknown]main::recv_decode_assemble_loop (1,802 samples, 8.42%)main::recv_d..std::net::udp::UdpSocket::recv_from (762 samples, 3.56%)std:..std::sys_common::net::UdpSocket::recv_from (762 samples, 3.56%)std:..std::sys::unix::net::Socket::recv_from (762 samples, 3.56%)std:..std::sys::unix::net::Socket::recv_from_with_flags (762 samples, 3.56%)std:..__libc_recvfrom (761 samples, 3.56%)__li..entry_SYSCALL_64_after_hwframe (757 samples, 3.54%)ent..do_syscall_64 (756 samples, 3.53%)do_..__x64_sys_recvfrom (756 samples, 3.53%)__x..__sys_recvfrom (756 samples, 3.53%)__s..recv-decode-4 (1,809 samples, 8.46%)recv-decode-4extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)extent_recycle_extract (4 samples, 0.02%)base_alloc_impl (7 samples, 0.03%)alloc_pages_vma (6 samples, 0.03%)__alloc_pages_nodemask (6 samples, 0.03%)get_page_from_freelist (6 samples, 0.03%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)_rjem_je_extent_alloc (18 samples, 0.08%)_rjem_je_base_alloc_extent (18 samples, 0.08%)extent_esn_set (11 samples, 0.05%)asm_exc_page_fault (10 samples, 0.05%)exc_page_fault (10 samples, 0.05%)do_user_addr_fault (10 samples, 0.05%)handle_mm_fault (10 samples, 0.05%)wp_page_copy (10 samples, 0.05%)ptep_clear_flush (4 samples, 0.02%)flush_tlb_mm_range (4 samples, 0.02%)on_each_cpu_cond_mask (4 samples, 0.02%)smp_call_function_many_cond (4 samples, 0.02%)_rjem_je_extent_alloc (19 samples, 0.09%)malloc_mutex_trylock_final (4 samples, 0.02%)__GI___pthread_mutex_trylock (4 samples, 0.02%)malloc_mutex_lock (5 samples, 0.02%)extent_lock2 (6 samples, 0.03%)mutex_pool_lock2 (6 samples, 0.03%)extent_recycle (34 samples, 0.16%)extent_recycle_split (30 samples, 0.14%)extent_split_interior (30 samples, 0.14%)extent_split_impl (30 samples, 0.14%)_rjem_je_extent_alloc_wrapper (39 samples, 0.18%)extent_alloc_retained (38 samples, 0.18%)down_read (4 samples, 0.02%)__pagevec_lru_add_fn (10 samples, 0.05%)_raw_spin_lock_irqsave (6 samples, 0.03%)lru_add_drain (23 samples, 0.11%)lru_add_drain_cpu (23 samples, 0.11%)pagevec_lru_move_fn (23 samples, 0.11%)flush_tlb_func_common.constprop.0 (8 samples, 0.04%)native_flush_tlb_one_user (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (13 samples, 0.06%)__default_send_IPI_dest_field (12 samples, 0.06%)on_each_cpu_cond_mask (64 samples, 0.30%)smp_call_function_many_cond (62 samples, 0.29%)tlb_is_not_lazy (6 samples, 0.03%)asm_sysvec_call_function (4 samples, 0.02%)__default_send_IPI_dest_field (12 samples, 0.06%)default_send_IPI_mask_sequence_phys (13 samples, 0.06%)flush_tlb_mm_range (167 samples, 0.78%)smp_call_function_many_cond (95 samples, 0.44%)llist_add_batch (6 samples, 0.03%)free_unref_page (5 samples, 0.02%)free_pcppages_bulk (3 samples, 0.01%)__free_one_page (3 samples, 0.01%)free_unref_page_list (12 samples, 0.06%)free_pcppages_bulk (7 samples, 0.03%)_raw_spin_lock (4 samples, 0.02%)native_queued_spin_lock_slowpath (4 samples, 0.02%)tlb_finish_mmu (200 samples, 0.93%)release_pages (24 samples, 0.11%)mem_cgroup_uncharge_list (4 samples, 0.02%)uncharge_batch (4 samples, 0.02%)page_counter_uncharge (3 samples, 0.01%)__split_huge_pmd (4 samples, 0.02%)pmdp_invalidate (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)__tlb_remove_page_size (11 samples, 0.05%)__get_free_pages (11 samples, 0.05%)__alloc_pages_nodemask (11 samples, 0.05%)get_page_from_freelist (10 samples, 0.05%)prep_new_page (5 samples, 0.02%)kernel_init_free_pages (5 samples, 0.02%)clear_page_rep (5 samples, 0.02%)page_remove_rmap (10 samples, 0.05%)_rjem_je_pages_purge_forced (267 samples, 1.25%)madvise (267 samples, 1.25%)entry_SYSCALL_64_after_hwframe (265 samples, 1.24%)do_syscall_64 (265 samples, 1.24%)__x64_sys_madvise (265 samples, 1.24%)do_madvise.part.0 (265 samples, 1.24%)zap_page_range (260 samples, 1.22%)unmap_page_range (35 samples, 0.16%)extents_fit_locked (5 samples, 0.02%)extents_best_fit_locked (5 samples, 0.02%)extent_recycle_extract (12 samples, 0.06%)malloc_mutex_lock (6 samples, 0.03%)malloc_mutex_trylock_final (6 samples, 0.03%)__GI___pthread_mutex_trylock (4 samples, 0.02%)_rjem_je_arena_extent_alloc_large (332 samples, 1.55%)extent_recycle (285 samples, 1.33%)extent_recycle_split (6 samples, 0.03%)extent_split_interior (4 samples, 0.02%)extent_split_impl (4 samples, 0.02%)arena_decay_tick (4 samples, 0.02%)arena_decay_ticks (4 samples, 0.02%)_rjem_je_arena_decay (4 samples, 0.02%)arena_decay_dirty (4 samples, 0.02%)arena_decay_impl (4 samples, 0.02%)arena_maybe_decay (4 samples, 0.02%)arena_maybe_decay (4 samples, 0.02%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_to_limit (3 samples, 0.01%)arena_decay_stashed (3 samples, 0.01%)_rjem_je_extent_purge_lazy_wrapper (3 samples, 0.01%)extent_purge_lazy_impl (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)madvise (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_madvise (3 samples, 0.01%)do_madvise.part.0 (3 samples, 0.01%)madvise_free_single_vma (3 samples, 0.01%)walk_page_range (3 samples, 0.01%)__walk_page_range (3 samples, 0.01%)madvise_free_pte_range (3 samples, 0.01%)split_huge_page_to_list (3 samples, 0.01%)imalloc_body (338 samples, 1.58%)imalloc_no_sample (338 samples, 1.58%)iallocztm (338 samples, 1.58%)arena_malloc (338 samples, 1.58%)tcache_alloc_large (337 samples, 1.58%)_rjem_je_large_palloc (337 samples, 1.58%)alloc::vec::from_elem (341 samples, 1.59%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (341 samples, 1.59%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (341 samples, 1.59%)alloc::raw_vec::RawVec<T,A>::allocate_in (341 samples, 1.59%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (341 samples, 1.59%)alloc::alloc::Global::alloc_impl (341 samples, 1.59%)alloc::alloc::alloc_zeroed (341 samples, 1.59%)_rjem_calloc (340 samples, 1.59%)imalloc (339 samples, 1.58%)asm_sysvec_call_function (3 samples, 0.01%)down_read_trylock (19 samples, 0.09%)__list_del_entry_valid (10 samples, 0.05%)_raw_spin_lock (13 samples, 0.06%)native_queued_spin_lock_slowpath (13 samples, 0.06%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_func_remote (5 samples, 0.02%)alloc_pages_vma (165 samples, 0.77%)__alloc_pages_nodemask (162 samples, 0.76%)get_page_from_freelist (158 samples, 0.74%)prep_new_page (97 samples, 0.45%)kernel_init_free_pages (96 samples, 0.45%)clear_page_rep (95 samples, 0.44%)asm_sysvec_call_function (10 samples, 0.05%)sysvec_call_function (9 samples, 0.04%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)kernel_init_free_pages (166 samples, 0.78%)clear_page_rep (164 samples, 0.77%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)native_flush_tlb_one_user (3 samples, 0.01%)alloc_pages_vma (173 samples, 0.81%)__alloc_pages_nodemask (173 samples, 0.81%)get_page_from_freelist (172 samples, 0.80%)prep_new_page (168 samples, 0.79%)clear_huge_page (51 samples, 0.24%)clear_subpage (50 samples, 0.23%)clear_page_rep (50 samples, 0.23%)do_huge_pmd_anonymous_page (228 samples, 1.07%)page_add_new_anon_rmap (3 samples, 0.01%)__mod_memcg_lruvec_state (3 samples, 0.01%)mem_cgroup_charge_statistics.constprop.0 (3 samples, 0.01%)mem_cgroup_charge (14 samples, 0.07%)try_charge (8 samples, 0.04%)page_counter_try_charge (6 samples, 0.03%)handle_mm_fault (436 samples, 2.04%)h..page_add_new_anon_rmap (8 samples, 0.04%)asm_exc_page_fault (483 samples, 2.26%)a..exc_page_fault (472 samples, 2.21%)e..do_user_addr_fault (471 samples, 2.20%)d..up_read (13 samples, 0.06%)flush_tlb_func_common.constprop.0 (4 samples, 0.02%)flush_tlb_func_remote (5 samples, 0.02%)asm_sysvec_call_function (12 samples, 0.06%)sysvec_call_function (11 samples, 0.05%)__sysvec_call_function (11 samples, 0.05%)flush_smp_call_function_queue (11 samples, 0.05%)k2o::decode::decode (658 samples, 3.08%)k2o..<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (1,006 samples, 4.70%)<k2o:..std::time::Instant::now (6 samples, 0.03%)std::sys::unix::time::inner::Instant::now (6 samples, 0.03%)std::sys::unix::time::inner::now (6 samples, 0.03%)__clock_gettime (5 samples, 0.02%)[libc-2.31.so] (4 samples, 0.02%)alloc::boxed::Box<T>::new (5 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::start_send (15 samples, 0.07%)core::sync::atomic::AtomicPtr<T>::load (10 samples, 0.05%)core::sync::atomic::atomic_load (10 samples, 0.05%)crossbeam_channel::channel::Sender<T>::send (21 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::send (21 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::write (6 samples, 0.03%)k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)kfree (6 samples, 0.03%)slab_free_freelist_hook.constprop.0 (6 samples, 0.03%)kfree (21 samples, 0.10%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (4 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.02%)__list_add_valid (5 samples, 0.02%)__free_one_page (45 samples, 0.21%)__list_del_entry_valid (32 samples, 0.15%)free_pcppages_bulk (171 samples, 0.80%)_raw_spin_lock (80 samples, 0.37%)native_queued_spin_lock_slowpath (79 samples, 0.37%)__consume_stateless_skb (259 samples, 1.21%)skb_release_data (238 samples, 1.11%)free_unref_page (208 samples, 0.97%)free_unref_page_commit (7 samples, 0.03%)__list_add_valid (5 samples, 0.02%)__local_bh_enable_ip (3 samples, 0.01%)mem_cgroup_uncharge_skmem (3 samples, 0.01%)__skb_recv_udp (15 samples, 0.07%)udp_rmem_release (8 samples, 0.04%)__sk_mem_reduce_allocated (7 samples, 0.03%)refill_stock (3 samples, 0.01%)drain_stock (3 samples, 0.01%)page_counter_uncharge (3 samples, 0.01%)__slab_free (7 samples, 0.03%)kmem_cache_free (14 samples, 0.07%)put_cpu_partial (5 samples, 0.02%)unfreeze_partials (4 samples, 0.02%)__free_pages_ok (4 samples, 0.02%)free_one_page (4 samples, 0.02%)_raw_spin_lock (4 samples, 0.02%)native_queued_spin_lock_slowpath (4 samples, 0.02%)lock_sock_nested (5 samples, 0.02%)_raw_spin_lock_bh (5 samples, 0.02%)flush_tlb_func_common.constprop.0 (10 samples, 0.05%)native_flush_tlb_one_user (3 samples, 0.01%)asm_sysvec_call_function (20 samples, 0.09%)sysvec_call_function (15 samples, 0.07%)asm_call_sysvec_on_stack (15 samples, 0.07%)__sysvec_call_function (15 samples, 0.07%)flush_smp_call_function_queue (15 samples, 0.07%)_copy_to_iter (301 samples, 1.41%)copy_user_generic_string (294 samples, 1.37%)__virt_addr_valid (6 samples, 0.03%)inet_recvmsg (740 samples, 3.46%)ine..udp_recvmsg (740 samples, 3.46%)udp..skb_copy_datagram_iter (434 samples, 2.03%)s..__skb_datagram_iter (434 samples, 2.03%)_..simple_copy_to_iter (107 samples, 0.50%)__check_object_size (107 samples, 0.50%)move_addr_to_user (6 samples, 0.03%)_copy_to_user (4 samples, 0.02%)copy_user_generic_string (4 samples, 0.02%)__x64_sys_recvfrom (753 samples, 3.52%)__x..__sys_recvfrom (753 samples, 3.52%)__s..__libc_recvfrom (757 samples, 3.54%)__l..entry_SYSCALL_64_after_hwframe (754 samples, 3.52%)ent..do_syscall_64 (754 samples, 3.52%)do_..[unknown] (1,793 samples, 8.38%)[unknown]main::recv_decode_assemble_loop (1,793 samples, 8.38%)main::recv_d..std::net::udp::UdpSocket::recv_from (758 samples, 3.54%)std:..std::sys_common::net::UdpSocket::recv_from (758 samples, 3.54%)std:..std::sys::unix::net::Socket::recv_from (758 samples, 3.54%)std:..std::sys::unix::net::Socket::recv_from_with_flags (758 samples, 3.54%)std:..recv-decode-5 (1,796 samples, 8.39%)recv-decode-5asm_sysvec_call_function (3 samples, 0.01%)entry_SYSCALL_64 (5 samples, 0.02%)[anon] (9 samples, 0.04%)std::sys::unix::net::Socket::recv_from_with_flags (9 samples, 0.04%)__libc_recvfrom (9 samples, 0.04%)extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)extent_recycle_extract (5 samples, 0.02%)__default_send_IPI_dest_field (3 samples, 0.01%)_rjem_je_extent_alloc (12 samples, 0.06%)_rjem_je_extent_alloc (12 samples, 0.06%)_rjem_je_base_alloc_extent (12 samples, 0.06%)extent_esn_set (10 samples, 0.05%)asm_exc_page_fault (10 samples, 0.05%)exc_page_fault (10 samples, 0.05%)do_user_addr_fault (10 samples, 0.05%)handle_mm_fault (9 samples, 0.04%)wp_page_copy (9 samples, 0.04%)ptep_clear_flush (7 samples, 0.03%)flush_tlb_mm_range (7 samples, 0.03%)on_each_cpu_cond_mask (7 samples, 0.03%)smp_call_function_many_cond (7 samples, 0.03%)default_send_IPI_mask_sequence_phys (4 samples, 0.02%)malloc_mutex_trylock_final (8 samples, 0.04%)__GI___pthread_mutex_trylock (8 samples, 0.04%)extent_lock2 (9 samples, 0.04%)mutex_pool_lock2 (9 samples, 0.04%)malloc_mutex_lock (9 samples, 0.04%)extent_recycle (31 samples, 0.14%)extent_recycle_split (26 samples, 0.12%)extent_split_interior (24 samples, 0.11%)extent_split_impl (24 samples, 0.11%)_rjem_je_extent_alloc_wrapper (34 samples, 0.16%)extent_alloc_retained (34 samples, 0.16%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)down_read (3 samples, 0.01%)__pagevec_lru_add_fn (8 samples, 0.04%)_raw_spin_lock_irqsave (5 samples, 0.02%)lru_add_drain (19 samples, 0.09%)lru_add_drain_cpu (19 samples, 0.09%)pagevec_lru_move_fn (19 samples, 0.09%)release_pages (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (8 samples, 0.04%)native_flush_tlb_one_user (5 samples, 0.02%)asm_sysvec_call_function (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (6 samples, 0.03%)__default_send_IPI_dest_field (6 samples, 0.03%)on_each_cpu_cond_mask (55 samples, 0.26%)smp_call_function_many_cond (54 samples, 0.25%)tlb_is_not_lazy (6 samples, 0.03%)asm_sysvec_call_function (6 samples, 0.03%)sysvec_call_function (6 samples, 0.03%)asm_call_sysvec_on_stack (6 samples, 0.03%)__sysvec_call_function (6 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.03%)__default_send_IPI_dest_field (9 samples, 0.04%)default_send_IPI_mask_sequence_phys (11 samples, 0.05%)flush_tlb_mm_range (164 samples, 0.77%)smp_call_function_many_cond (101 samples, 0.47%)llist_add_batch (5 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)__list_del_entry_valid (4 samples, 0.02%)_raw_spin_lock_irqsave (4 samples, 0.02%)free_unref_page_list (8 samples, 0.04%)free_pcppages_bulk (6 samples, 0.03%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)tlb_finish_mmu (195 samples, 0.91%)release_pages (30 samples, 0.14%)mem_cgroup_uncharge_list (9 samples, 0.04%)uncharge_batch (8 samples, 0.04%)page_counter_uncharge (7 samples, 0.03%)tlb_gather_mmu (5 samples, 0.02%)__split_huge_pmd (5 samples, 0.02%)__tlb_remove_page_size (16 samples, 0.07%)__get_free_pages (16 samples, 0.07%)__alloc_pages_nodemask (16 samples, 0.07%)get_page_from_freelist (16 samples, 0.07%)prep_new_page (10 samples, 0.05%)kernel_init_free_pages (10 samples, 0.05%)clear_page_rep (10 samples, 0.05%)deferred_split_huge_page (3 samples, 0.01%)page_remove_rmap (8 samples, 0.04%)entry_SYSCALL_64_after_hwframe (263 samples, 1.23%)do_syscall_64 (263 samples, 1.23%)__x64_sys_madvise (263 samples, 1.23%)do_madvise.part.0 (263 samples, 1.23%)zap_page_range (260 samples, 1.22%)unmap_page_range (41 samples, 0.19%)_rjem_je_pages_purge_forced (267 samples, 1.25%)madvise (266 samples, 1.24%)_rjem_je_extent_heap_first (4 samples, 0.02%)extents_best_fit_locked (5 samples, 0.02%)extents_fit_locked (6 samples, 0.03%)malloc_mutex_lock (9 samples, 0.04%)malloc_mutex_trylock_final (9 samples, 0.04%)__GI___pthread_mutex_trylock (8 samples, 0.04%)extent_recycle_extract (17 samples, 0.08%)extent_lock2 (3 samples, 0.01%)mutex_pool_lock2 (3 samples, 0.01%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)extent_recycle (293 samples, 1.37%)extent_recycle_split (8 samples, 0.04%)extent_split_interior (7 samples, 0.03%)extent_split_impl (7 samples, 0.03%)_rjem_je_arena_extent_alloc_large (329 samples, 1.54%)alloc::vec::from_elem (336 samples, 1.57%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (336 samples, 1.57%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (335 samples, 1.57%)alloc::raw_vec::RawVec<T,A>::allocate_in (335 samples, 1.57%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (335 samples, 1.57%)alloc::alloc::Global::alloc_impl (335 samples, 1.57%)alloc::alloc::alloc_zeroed (335 samples, 1.57%)_rjem_calloc (334 samples, 1.56%)imalloc (334 samples, 1.56%)imalloc_body (333 samples, 1.56%)imalloc_no_sample (333 samples, 1.56%)iallocztm (333 samples, 1.56%)arena_malloc (333 samples, 1.56%)tcache_alloc_large (331 samples, 1.55%)_rjem_je_large_palloc (331 samples, 1.55%)down_read_trylock (24 samples, 0.11%)__count_memcg_events.part.0 (3 samples, 0.01%)__list_del_entry_valid (13 samples, 0.06%)_raw_spin_lock (9 samples, 0.04%)native_queued_spin_lock_slowpath (8 samples, 0.04%)alloc_pages_vma (138 samples, 0.65%)__alloc_pages_nodemask (137 samples, 0.64%)get_page_from_freelist (132 samples, 0.62%)prep_new_page (76 samples, 0.36%)kernel_init_free_pages (75 samples, 0.35%)clear_page_rep (73 samples, 0.34%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)_raw_spin_lock_irqsave (7 samples, 0.03%)native_queued_spin_lock_slowpath (6 samples, 0.03%)kernel_init_free_pages (172 samples, 0.80%)clear_page_rep (171 samples, 0.80%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)alloc_pages_vma (184 samples, 0.86%)__alloc_pages_nodemask (184 samples, 0.86%)get_page_from_freelist (184 samples, 0.86%)prep_new_page (174 samples, 0.81%)clear_huge_page (37 samples, 0.17%)clear_subpage (36 samples, 0.17%)clear_page_rep (35 samples, 0.16%)page_add_new_anon_rmap (4 samples, 0.02%)__mod_memcg_lruvec_state (4 samples, 0.02%)__mod_memcg_state.part.0 (3 samples, 0.01%)do_huge_pmd_anonymous_page (228 samples, 1.07%)mem_cgroup_charge_statistics.constprop.0 (3 samples, 0.01%)mem_cgroup_charge (18 samples, 0.08%)try_charge (11 samples, 0.05%)page_counter_try_charge (5 samples, 0.02%)handle_mm_fault (413 samples, 1.93%)h..page_add_new_anon_rmap (6 samples, 0.03%)asm_exc_page_fault (466 samples, 2.18%)a..exc_page_fault (453 samples, 2.12%)e..do_user_addr_fault (452 samples, 2.11%)d..up_read (13 samples, 0.06%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)k2o::decode::decode (630 samples, 2.94%)k2..error_entry (4 samples, 0.02%)sync_regs (3 samples, 0.01%)<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (972 samples, 4.54%)<k2o:..std::time::Instant::now (4 samples, 0.02%)std::sys::unix::time::inner::Instant::now (4 samples, 0.02%)std::sys::unix::time::inner::now (4 samples, 0.02%)__clock_gettime (4 samples, 0.02%)alloc::boxed::Box<T>::new (5 samples, 0.02%)[libc-2.31.so] (5 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::start_send (17 samples, 0.08%)core::sync::atomic::AtomicPtr<T>::load (11 samples, 0.05%)core::sync::atomic::atomic_load (11 samples, 0.05%)crossbeam_channel::channel::Sender<T>::send (31 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::send (31 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::write (14 samples, 0.07%)k2o::helpers::set_cpu_affinity (6 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)entry_SYSCALL_64_after_hwframe (6 samples, 0.03%)do_syscall_64 (6 samples, 0.03%)__x64_sys_sched_setaffinity (6 samples, 0.03%)sched_setaffinity (6 samples, 0.03%)kfree (6 samples, 0.03%)__slab_free (6 samples, 0.03%)kfree (26 samples, 0.12%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_call_sysvec_on_stack (10 samples, 0.05%)__sysvec_call_function (10 samples, 0.05%)flush_smp_call_function_queue (10 samples, 0.05%)asm_sysvec_call_function (14 samples, 0.07%)sysvec_call_function (11 samples, 0.05%)__list_add_valid (7 samples, 0.03%)__free_one_page (37 samples, 0.17%)__list_del_entry_valid (47 samples, 0.22%)free_pcppages_bulk (156 samples, 0.73%)_raw_spin_lock (62 samples, 0.29%)native_queued_spin_lock_slowpath (57 samples, 0.27%)__consume_stateless_skb (245 samples, 1.15%)skb_release_data (219 samples, 1.02%)free_unref_page (192 samples, 0.90%)free_unref_page_commit (5 samples, 0.02%)__list_add_valid (3 samples, 0.01%)__perf_event_task_sched_out (4 samples, 0.02%)amd_pmu_disable_all (4 samples, 0.02%)__skb_wait_for_more_packets (6 samples, 0.03%)schedule_timeout (6 samples, 0.03%)schedule (6 samples, 0.03%)__schedule (6 samples, 0.03%)__sk_mem_reduce_allocated (5 samples, 0.02%)mem_cgroup_uncharge_skmem (3 samples, 0.01%)__mod_memcg_state.part.0 (3 samples, 0.01%)__skb_recv_udp (16 samples, 0.07%)udp_rmem_release (9 samples, 0.04%)__slab_free (7 samples, 0.03%)kmem_cache_free (13 samples, 0.06%)put_cpu_partial (4 samples, 0.02%)unfreeze_partials (3 samples, 0.01%)lock_sock_nested (4 samples, 0.02%)_raw_spin_lock_bh (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (4 samples, 0.02%)native_flush_tlb_one_user (3 samples, 0.01%)_copy_to_iter (343 samples, 1.60%)copy_user_generic_string (341 samples, 1.59%)asm_sysvec_call_function (16 samples, 0.07%)sysvec_call_function (9 samples, 0.04%)asm_call_sysvec_on_stack (9 samples, 0.04%)__sysvec_call_function (9 samples, 0.04%)flush_smp_call_function_queue (9 samples, 0.04%)flush_tlb_func_remote (4 samples, 0.02%)__virt_addr_valid (13 samples, 0.06%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)inet_recvmsg (786 samples, 3.67%)inet..udp_recvmsg (786 samples, 3.67%)udp_..skb_copy_datagram_iter (495 samples, 2.31%)s..__skb_datagram_iter (495 samples, 2.31%)_..simple_copy_to_iter (106 samples, 0.50%)__check_object_size (106 samples, 0.50%)move_addr_to_user (6 samples, 0.03%)_copy_to_user (4 samples, 0.02%)copy_user_generic_string (4 samples, 0.02%)[unknown] (1,813 samples, 8.47%)[unknown]main::recv_decode_assemble_loop (1,811 samples, 8.46%)main::recv_d..std::net::udp::UdpSocket::recv_from (801 samples, 3.74%)std:..std::sys_common::net::UdpSocket::recv_from (801 samples, 3.74%)std:..std::sys::unix::net::Socket::recv_from (801 samples, 3.74%)std:..std::sys::unix::net::Socket::recv_from_with_flags (801 samples, 3.74%)std:..__libc_recvfrom (801 samples, 3.74%)__li..entry_SYSCALL_64_after_hwframe (799 samples, 3.73%)entr..do_syscall_64 (798 samples, 3.73%)do_s..__x64_sys_recvfrom (797 samples, 3.73%)__x6..__sys_recvfrom (797 samples, 3.73%)__sy..recv-decode-6 (1,823 samples, 8.52%)recv-decode-6extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)extent_recycle_extract (6 samples, 0.03%)base_alloc_impl (4 samples, 0.02%)_rjem_je_extent_alloc (7 samples, 0.03%)_rjem_je_base_alloc_extent (7 samples, 0.03%)extent_esn_set (3 samples, 0.01%)_rjem_je_extent_alloc (8 samples, 0.04%)extent_lock2 (9 samples, 0.04%)mutex_pool_lock2 (9 samples, 0.04%)malloc_mutex_lock (9 samples, 0.04%)malloc_mutex_trylock_final (9 samples, 0.04%)__GI___pthread_mutex_trylock (9 samples, 0.04%)extent_recycle (29 samples, 0.14%)extent_recycle_split (22 samples, 0.10%)extent_split_interior (20 samples, 0.09%)extent_split_impl (20 samples, 0.09%)_rjem_je_extent_alloc_wrapper (33 samples, 0.15%)extent_alloc_retained (33 samples, 0.15%)asm_exc_page_fault (3 samples, 0.01%)down_read (8 samples, 0.04%)__pagevec_lru_add_fn (17 samples, 0.08%)_raw_spin_lock_irqsave (5 samples, 0.02%)lru_add_drain (27 samples, 0.13%)lru_add_drain_cpu (27 samples, 0.13%)pagevec_lru_move_fn (27 samples, 0.13%)flush_tlb_func_common.constprop.0 (10 samples, 0.05%)native_flush_tlb_one_user (6 samples, 0.03%)default_send_IPI_mask_sequence_phys (18 samples, 0.08%)__default_send_IPI_dest_field (18 samples, 0.08%)on_each_cpu_cond_mask (89 samples, 0.42%)smp_call_function_many_cond (87 samples, 0.41%)tlb_is_not_lazy (8 samples, 0.04%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__default_send_IPI_dest_field (12 samples, 0.06%)default_send_IPI_mask_sequence_phys (14 samples, 0.07%)flush_tlb_mm_range (181 samples, 0.85%)smp_call_function_many_cond (81 samples, 0.38%)llist_add_batch (7 samples, 0.03%)_raw_spin_lock_irqsave (5 samples, 0.02%)native_queued_spin_lock_slowpath (5 samples, 0.02%)__free_one_page (3 samples, 0.01%)free_pcppages_bulk (9 samples, 0.04%)_raw_spin_lock (4 samples, 0.02%)native_queued_spin_lock_slowpath (3 samples, 0.01%)free_unref_page_list (17 samples, 0.08%)mem_cgroup_uncharge_list (5 samples, 0.02%)uncharge_batch (5 samples, 0.02%)page_counter_uncharge (5 samples, 0.02%)tlb_finish_mmu (219 samples, 1.02%)release_pages (31 samples, 0.14%)tlb_gather_mmu (4 samples, 0.02%)__split_huge_pmd (4 samples, 0.02%)pmdp_invalidate (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)__alloc_pages_nodemask (8 samples, 0.04%)get_page_from_freelist (8 samples, 0.04%)prep_new_page (6 samples, 0.03%)kernel_init_free_pages (6 samples, 0.03%)clear_page_rep (6 samples, 0.03%)__tlb_remove_page_size (10 samples, 0.05%)__get_free_pages (10 samples, 0.05%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)page_remove_rmap (8 samples, 0.04%)_rjem_je_pages_purge_forced (297 samples, 1.39%)madvise (297 samples, 1.39%)entry_SYSCALL_64_after_hwframe (293 samples, 1.37%)do_syscall_64 (293 samples, 1.37%)__x64_sys_madvise (293 samples, 1.37%)do_madvise.part.0 (293 samples, 1.37%)zap_page_range (283 samples, 1.32%)unmap_page_range (33 samples, 0.15%)_rjem_je_extent_heap_first (4 samples, 0.02%)extents_best_fit_locked (5 samples, 0.02%)extents_fit_locked (6 samples, 0.03%)extent_recycle_extract (14 samples, 0.07%)malloc_mutex_lock (7 samples, 0.03%)malloc_mutex_trylock_final (7 samples, 0.03%)__GI___pthread_mutex_trylock (7 samples, 0.03%)_rjem_je_extent_alloc (3 samples, 0.01%)_rjem_je_extent_avail_first (3 samples, 0.01%)extent_split_impl (4 samples, 0.02%)_rjem_je_arena_extent_alloc_large (354 samples, 1.65%)extent_recycle (317 samples, 1.48%)extent_recycle_split (5 samples, 0.02%)extent_split_interior (5 samples, 0.02%)_rjem_je_large_palloc (361 samples, 1.69%)arena_decay_tick (5 samples, 0.02%)arena_decay_ticks (5 samples, 0.02%)_rjem_je_arena_decay (5 samples, 0.02%)arena_decay_dirty (5 samples, 0.02%)arena_decay_impl (5 samples, 0.02%)arena_maybe_decay (5 samples, 0.02%)arena_maybe_decay (5 samples, 0.02%)arena_decay_try_purge (5 samples, 0.02%)arena_decay_try_purge (5 samples, 0.02%)arena_decay_to_limit (5 samples, 0.02%)arena_decay_stashed (5 samples, 0.02%)_rjem_je_extent_purge_lazy_wrapper (5 samples, 0.02%)extent_purge_lazy_impl (5 samples, 0.02%)_rjem_je_pages_purge_lazy (5 samples, 0.02%)_rjem_je_pages_purge_lazy (5 samples, 0.02%)madvise (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (5 samples, 0.02%)do_syscall_64 (5 samples, 0.02%)__x64_sys_madvise (5 samples, 0.02%)do_madvise.part.0 (5 samples, 0.02%)madvise_free_single_vma (5 samples, 0.02%)walk_page_range (5 samples, 0.02%)__walk_page_range (5 samples, 0.02%)madvise_free_pte_range (5 samples, 0.02%)split_huge_page_to_list (5 samples, 0.02%)try_to_unmap (4 samples, 0.02%)rmap_walk_anon (4 samples, 0.02%)try_to_unmap_one (4 samples, 0.02%)ptep_clear_flush (4 samples, 0.02%)flush_tlb_mm_range (4 samples, 0.02%)on_each_cpu_cond_mask (4 samples, 0.02%)smp_call_function_many_cond (4 samples, 0.02%)alloc::vec::from_elem (364 samples, 1.70%)<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (364 samples, 1.70%)alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (364 samples, 1.70%)alloc::raw_vec::RawVec<T,A>::allocate_in (364 samples, 1.70%)<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (364 samples, 1.70%)alloc::alloc::Global::alloc_impl (364 samples, 1.70%)alloc::alloc::alloc_zeroed (364 samples, 1.70%)_rjem_calloc (364 samples, 1.70%)imalloc (364 samples, 1.70%)imalloc_body (364 samples, 1.70%)imalloc_no_sample (364 samples, 1.70%)iallocztm (364 samples, 1.70%)arena_malloc (364 samples, 1.70%)tcache_alloc_large (362 samples, 1.69%)down_read_trylock (20 samples, 0.09%)__list_del_entry_valid (12 samples, 0.06%)_raw_spin_lock (21 samples, 0.10%)native_queued_spin_lock_slowpath (21 samples, 0.10%)alloc_pages_vma (171 samples, 0.80%)__alloc_pages_nodemask (170 samples, 0.79%)get_page_from_freelist (165 samples, 0.77%)prep_new_page (99 samples, 0.46%)kernel_init_free_pages (96 samples, 0.45%)clear_page_rep (94 samples, 0.44%)_raw_spin_lock_irqsave (5 samples, 0.02%)native_queued_spin_lock_slowpath (4 samples, 0.02%)alloc_pages_vma (169 samples, 0.79%)__alloc_pages_nodemask (169 samples, 0.79%)get_page_from_freelist (169 samples, 0.79%)prep_new_page (163 samples, 0.76%)kernel_init_free_pages (163 samples, 0.76%)clear_page_rep (161 samples, 0.75%)asm_sysvec_call_function (10 samples, 0.05%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)clear_huge_page (46 samples, 0.22%)clear_subpage (46 samples, 0.22%)clear_page_rep (46 samples, 0.22%)do_huge_pmd_anonymous_page (220 samples, 1.03%)mem_cgroup_charge_statistics.constprop.0 (4 samples, 0.02%)__count_memcg_events.part.0 (3 samples, 0.01%)mem_cgroup_charge (13 samples, 0.06%)try_charge (5 samples, 0.02%)page_counter_try_charge (3 samples, 0.01%)handle_mm_fault (428 samples, 2.00%)h..page_add_new_anon_rmap (5 samples, 0.02%)asm_exc_page_fault (487 samples, 2.28%)a..exc_page_fault (475 samples, 2.22%)e..do_user_addr_fault (470 samples, 2.20%)d..up_read (19 samples, 0.09%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)native_flush_tlb_one_user (3 samples, 0.01%)asm_sysvec_call_function (9 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)error_entry (6 samples, 0.03%)sync_regs (3 samples, 0.01%)k2o::decode::decode (661 samples, 3.09%)k2o..<k2o::decode::K2ISBlock as k2o::decode::K2Block>::from_bytes (1,031 samples, 4.82%)<k2o::..std::time::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::now (5 samples, 0.02%)__clock_gettime (4 samples, 0.02%)alloc::boxed::Box<T>::new (3 samples, 0.01%)[libc-2.31.so] (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (13 samples, 0.06%)core::sync::atomic::AtomicPtr<T>::load (7 samples, 0.03%)core::sync::atomic::atomic_load (7 samples, 0.03%)crossbeam_channel::channel::Sender<T>::send (28 samples, 0.13%)crossbeam_channel::flavors::list::Channel<T>::send (28 samples, 0.13%)crossbeam_channel::flavors::list::Channel<T>::write (15 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::write (3 samples, 0.01%)core::ptr::write (3 samples, 0.01%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)__set_cpus_allowed_ptr (7 samples, 0.03%)stop_one_cpu (7 samples, 0.03%)_cond_resched (7 samples, 0.03%)__schedule (7 samples, 0.03%)finish_task_switch (7 samples, 0.03%)__mmdrop (7 samples, 0.03%)__free_pages (7 samples, 0.03%)kfree (23 samples, 0.11%)asm_sysvec_call_function (4 samples, 0.02%)sysvec_call_function (4 samples, 0.02%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_smp_call_function_queue (7 samples, 0.03%)asm_sysvec_call_function (10 samples, 0.05%)sysvec_call_function (8 samples, 0.04%)asm_call_sysvec_on_stack (8 samples, 0.04%)__sysvec_call_function (8 samples, 0.04%)__list_add_valid (8 samples, 0.04%)__free_one_page (52 samples, 0.24%)__list_del_entry_valid (35 samples, 0.16%)free_pcppages_bulk (169 samples, 0.79%)_raw_spin_lock (72 samples, 0.34%)native_queued_spin_lock_slowpath (71 samples, 0.33%)__consume_stateless_skb (236 samples, 1.10%)skb_release_data (213 samples, 1.00%)free_unref_page (192 samples, 0.90%)free_unref_page_commit (4 samples, 0.02%)__skb_wait_for_more_packets (4 samples, 0.02%)schedule_timeout (4 samples, 0.02%)schedule (4 samples, 0.02%)__schedule (4 samples, 0.02%)__skb_recv_udp (12 samples, 0.06%)udp_rmem_release (6 samples, 0.03%)__sk_mem_reduce_allocated (5 samples, 0.02%)refill_stock (3 samples, 0.01%)drain_stock (3 samples, 0.01%)page_counter_uncharge (3 samples, 0.01%)__slab_free (6 samples, 0.03%)kmem_cache_free (10 samples, 0.05%)put_cpu_partial (3 samples, 0.01%)lock_sock_nested (4 samples, 0.02%)_raw_spin_lock_bh (4 samples, 0.02%)flush_tlb_func_common.constprop.0 (4 samples, 0.02%)_copy_to_iter (301 samples, 1.41%)copy_user_generic_string (293 samples, 1.37%)asm_sysvec_call_function (13 samples, 0.06%)sysvec_call_function (11 samples, 0.05%)asm_call_sysvec_on_stack (10 samples, 0.05%)__sysvec_call_function (10 samples, 0.05%)flush_smp_call_function_queue (10 samples, 0.05%)__virt_addr_valid (12 samples, 0.06%)inet_recvmsg (731 samples, 3.42%)ine..udp_recvmsg (730 samples, 3.41%)udp..skb_copy_datagram_iter (454 samples, 2.12%)s..__skb_datagram_iter (454 samples, 2.12%)_..simple_copy_to_iter (106 samples, 0.50%)__check_object_size (105 samples, 0.49%)move_addr_to_user (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (744 samples, 3.48%)ent..do_syscall_64 (744 samples, 3.48%)do_..__x64_sys_recvfrom (744 samples, 3.48%)__x..__sys_recvfrom (744 samples, 3.48%)__s..sockfd_lookup_light (5 samples, 0.02%)__fget_light (5 samples, 0.02%)[unknown] (1,816 samples, 8.49%)[unknown]main::recv_decode_assemble_loop (1,816 samples, 8.49%)main::recv_d..std::net::udp::UdpSocket::recv_from (749 samples, 3.50%)std..std::sys_common::net::UdpSocket::recv_from (749 samples, 3.50%)std..std::sys::unix::net::Socket::recv_from (749 samples, 3.50%)std..std::sys::unix::net::Socket::recv_from_with_flags (749 samples, 3.50%)std..__libc_recvfrom (749 samples, 3.50%)__l..all (21,394 samples, 100%)recv-decode-7 (1,818 samples, 8.50%)recv-decode-7 \ No newline at end of file diff --git a/k2o/flamegraph_history/flamegraph-without-allocation-reuse.svg b/k2o/flamegraph_history/flamegraph-without-allocation-reuse.svg new file mode 100644 index 00000000..63fcb047 --- /dev/null +++ b/k2o/flamegraph_history/flamegraph-without-allocation-reuse.svg @@ -0,0 +1,414 @@ +Flame Graph Reset ZoomSearch [anon] (6 samples, 0.02%)k2o::frame::K2Frame::assign_block (6 samples, 0.02%)k2o::frame::K2Frame::track_block (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (6 samples, 0.02%)ndarray::zip::Zip<(P1,P2),D>::for_each (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core_strided (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core_strided_c (6 samples, 0.02%)ndarray::zip::Zip<P,D>::inner (6 samples, 0.02%)ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (4 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (4 samples, 0.01%)ndarray::zip::Zip<(P1,P2),D>::for_each (4 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core (4 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core_contiguous (4 samples, 0.01%)ndarray::zip::Zip<P,D>::inner (4 samples, 0.01%)[unknown] (3 samples, 0.01%)_rjem_je_extent_heap_insert (4 samples, 0.01%)extent_deactivate_locked (11 samples, 0.04%)extents_insert_locked (11 samples, 0.04%)extent_activate_locked (4 samples, 0.01%)extents_remove_locked (4 samples, 0.01%)_rjem_je_extent_dalloc (3 samples, 0.01%)malloc_mutex_trylock_final (6 samples, 0.02%)__GI___pthread_mutex_trylock (6 samples, 0.02%)extent_lock2 (7 samples, 0.03%)mutex_pool_lock2 (7 samples, 0.03%)malloc_mutex_lock (7 samples, 0.03%)extent_merge_impl (19 samples, 0.07%)extent_unlock2 (7 samples, 0.03%)mutex_pool_unlock2 (7 samples, 0.03%)malloc_mutex_unlock (7 samples, 0.03%)__pthread_mutex_unlock_usercnt (7 samples, 0.03%)extent_coalesce (25 samples, 0.09%)malloc_mutex_lock (23 samples, 0.09%)malloc_mutex_trylock_final (22 samples, 0.08%)__GI___pthread_mutex_trylock (22 samples, 0.08%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)extent_lock (26 samples, 0.10%)mutex_pool_lock (26 samples, 0.10%)mutex_pool_mutex (3 samples, 0.01%)extent_lock_from_addr (29 samples, 0.11%)extent_rtree_leaf_elm_try_lock (28 samples, 0.10%)extent_try_coalesce (62 samples, 0.23%)extent_unlock (4 samples, 0.01%)mutex_pool_unlock (4 samples, 0.01%)mutex_pool_mutex (3 samples, 0.01%)malloc_mutex_lock (9 samples, 0.03%)malloc_mutex_trylock_final (9 samples, 0.03%)__GI___pthread_mutex_trylock (9 samples, 0.03%)_rjem_je_large_dalloc_finish (90 samples, 0.33%)large_dalloc_finish_impl (90 samples, 0.33%)_rjem_je_arena_extents_dirty_dalloc (90 samples, 0.33%)extent_record (89 samples, 0.33%)malloc_mutex_unlock (5 samples, 0.02%)__pthread_mutex_unlock_usercnt (5 samples, 0.02%)_rjem_sdallocx (102 samples, 0.38%)isfree (101 samples, 0.37%)isdalloct (101 samples, 0.37%)arena_sdalloc (101 samples, 0.37%)tcache_dalloc_large (101 samples, 0.37%)_rjem_je_tcache_bin_flush_large (101 samples, 0.37%)core::ptr::drop_in_place<k2o::block::K2ISBlock> (105 samples, 0.39%)core::ptr::drop_in_place<alloc::vec::Vec<u16>> (105 samples, 0.39%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16>> (105 samples, 0.39%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (105 samples, 0.39%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (104 samples, 0.39%)alloc::alloc::dealloc (104 samples, 0.39%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (22 samples, 0.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (22 samples, 0.08%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (22 samples, 0.08%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (25 samples, 0.09%)amd_pmu_disable_all (4 samples, 0.01%)__perf_event_task_sched_out (5 samples, 0.02%)std::sys_common::thread_parker::futex::Parker::park (8 samples, 0.03%)std::sys::unix::futex::futex_wait (8 samples, 0.03%)syscall (8 samples, 0.03%)entry_SYSCALL_64_after_hwframe (8 samples, 0.03%)do_syscall_64 (8 samples, 0.03%)__x64_sys_futex (8 samples, 0.03%)do_futex (8 samples, 0.03%)futex_wait (8 samples, 0.03%)futex_wait_queue_me (8 samples, 0.03%)schedule (8 samples, 0.03%)__schedule (8 samples, 0.03%)crossbeam_channel::context::Context::wait_until (36 samples, 0.13%)std::thread::park (9 samples, 0.03%)crossbeam_channel::context::Context::with (40 samples, 0.15%)std::thread::local::LocalKey<T>::try_with (40 samples, 0.15%)crossbeam_channel::context::Context::with::{{closure}} (39 samples, 0.14%)crossbeam_channel::context::Context::with::{{closure}} (39 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (39 samples, 0.14%)crossbeam_channel::waker::SyncWaker::register (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (10 samples, 0.04%)core::sync::atomic::AtomicUsize::load (4 samples, 0.01%)core::sync::atomic::atomic_load (4 samples, 0.01%)__GI___sched_yield (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_sched_yield (3 samples, 0.01%)schedule (3 samples, 0.01%)__schedule (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::recv (78 samples, 0.29%)crossbeam_utils::backoff::Backoff::snooze (24 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (21 samples, 0.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (21 samples, 0.08%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (21 samples, 0.08%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::recv (81 samples, 0.30%)_raw_spin_lock_irqsave (4 samples, 0.01%)native_queued_spin_lock_slowpath (4 samples, 0.01%)flush_tlb_func_remote (5 samples, 0.02%)kernel_init_free_pages (171 samples, 0.63%)clear_page_rep (171 samples, 0.63%)asm_sysvec_call_function (21 samples, 0.08%)sysvec_call_function (12 samples, 0.04%)asm_call_sysvec_on_stack (12 samples, 0.04%)__sysvec_call_function (12 samples, 0.04%)flush_smp_call_function_queue (11 samples, 0.04%)alloc_pages_vma (180 samples, 0.67%)__alloc_pages_nodemask (180 samples, 0.67%)get_page_from_freelist (180 samples, 0.67%)prep_new_page (173 samples, 0.64%)clear_huge_page (51 samples, 0.19%)clear_subpage (49 samples, 0.18%)clear_page_rep (47 samples, 0.17%)asm_sysvec_call_function (3 samples, 0.01%)do_huge_pmd_anonymous_page (235 samples, 0.87%)handle_mm_fault (239 samples, 0.89%)asm_exc_page_fault (241 samples, 0.89%)exc_page_fault (241 samples, 0.89%)do_user_addr_fault (241 samples, 0.89%)flush_tlb_func_remote (3 samples, 0.01%)__sysvec_call_function (8 samples, 0.03%)flush_smp_call_function_queue (8 samples, 0.03%)llist_reverse_order (4 samples, 0.01%)asm_sysvec_call_function (15 samples, 0.06%)sysvec_call_function (9 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (441 samples, 1.63%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (441 samples, 1.63%)core::iter::traits::iterator::Iterator::for_each (441 samples, 1.63%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold (441 samples, 1.63%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold (441 samples, 1.63%)core::iter::traits::iterator::Iterator::try_fold (441 samples, 1.63%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold::check::{{closure}} (441 samples, 1.63%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold::ok::{{closure}} (441 samples, 1.63%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (441 samples, 1.63%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend::{{closure}} (441 samples, 1.63%)core::ptr::write (441 samples, 1.63%)__memset_avx2_unaligned_erms (441 samples, 1.63%)<k2o::assemble::ChanReuseFrameSource<F> as k2o::assemble::FrameReuseSource<F>>::new_frame_from_block (443 samples, 1.64%)k2o::frame::K2Frame::empty_from_block (443 samples, 1.64%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::empty_with_timestamp (443 samples, 1.64%)k2o::frame::K2Frame::track_block (14 samples, 0.05%)std::time::Instant::now (10 samples, 0.04%)std::sys::unix::time::inner::Instant::now (10 samples, 0.04%)std::sys::unix::time::inner::now (10 samples, 0.04%)__GI___clock_gettime (10 samples, 0.04%)__vdso_clock_gettime (5 samples, 0.02%)<(A,B) as ndarray::zip::OffsetTuple>::stride_offset (56 samples, 0.21%)<*mut T as ndarray::zip::ndproducer::Offset>::stride_offset (56 samples, 0.21%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (6 samples, 0.02%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)llist_reverse_order (3 samples, 0.01%)asm_sysvec_apic_timer_interrupt (3 samples, 0.01%)sysvec_apic_timer_interrupt (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (5 samples, 0.02%)native_flush_tlb_local (3 samples, 0.01%)flush_tlb_func_remote (10 samples, 0.04%)asm_sysvec_call_function (35 samples, 0.13%)sysvec_call_function (28 samples, 0.10%)__sysvec_call_function (28 samples, 0.10%)flush_smp_call_function_queue (28 samples, 0.10%)llist_reverse_order (7 samples, 0.03%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)flush_tlb_func_remote (5 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (900 samples, 3.33%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (900 samples, 3.33%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (899 samples, 3.33%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (898 samples, 3.33%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (898 samples, 3.33%)nda..ndarray::zip::Zip<P,D>::for_each_core (898 samples, 3.33%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided (898 samples, 3.33%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided_c (898 samples, 3.33%)nda..ndarray::zip::Zip<P,D>::inner (897 samples, 3.32%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (803 samples, 2.97%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (803 samples, 2.97%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (803 samples, 2.97%)nda..ndarray::zip::Zip<P,D>::for_each_core (803 samples, 2.97%)nda..ndarray::zip::Zip<P,D>::for_each_core_contiguous (803 samples, 2.97%)nda..ndarray::zip::Zip<P,D>::inner (803 samples, 2.97%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (283 samples, 1.05%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}}::{{closure}} (283 samples, 1.05%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign::{{closure}} (283 samples, 1.05%)asm_sysvec_call_function (29 samples, 0.11%)sysvec_call_function (19 samples, 0.07%)__sysvec_call_function (19 samples, 0.07%)flush_smp_call_function_queue (19 samples, 0.07%)llist_reverse_order (3 samples, 0.01%)k2o::frame::K2Frame::assign_block (919 samples, 3.40%)k2o..k2o::assemble::PendingFrames<F,S>::assign_block (1,365 samples, 5.06%)k2o::a..core::num::<impl isize>::wrapping_neg (3 samples, 0.01%)core::num::<impl isize>::wrapping_sub (3 samples, 0.01%)hashbrown::raw::Bucket<T>::next_n (11 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::sub (11 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (8 samples, 0.03%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (43 samples, 0.16%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (43 samples, 0.16%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (43 samples, 0.16%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (41 samples, 0.15%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (20 samples, 0.07%)asm_sysvec_call_function (3 samples, 0.01%)alloc::vec::Vec<T>::with_capacity (4 samples, 0.01%)alloc::vec::Vec<T,A>::with_capacity_in (4 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (4 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::allocate_in (4 samples, 0.01%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (4 samples, 0.01%)alloc::alloc::Global::alloc_impl (4 samples, 0.01%)alloc::alloc::alloc (4 samples, 0.01%)_rjem_mallocx (3 samples, 0.01%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (6 samples, 0.02%)alloc::alloc::dealloc (6 samples, 0.02%)_rjem_sdallocx (5 samples, 0.02%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (7 samples, 0.03%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (7 samples, 0.03%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (7 samples, 0.03%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (7 samples, 0.03%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (7 samples, 0.03%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (7 samples, 0.03%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (30 samples, 0.11%)alloc::vec::Vec<T,A>::as_ptr (16 samples, 0.06%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (129 samples, 0.48%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (209 samples, 0.77%)k2o::assemble::PendingFrames<F,S>::retire_finished (311 samples, 1.15%)k2o::frame::K2Frame::is_finished (256 samples, 0.95%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (13 samples, 0.05%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_modified_timestamp (21 samples, 0.08%)hashbrown::raw::Bucket<T>::next_n (8 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::sub (8 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (7 samples, 0.03%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (33 samples, 0.12%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (33 samples, 0.12%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (28 samples, 0.10%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (20 samples, 0.07%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (4 samples, 0.01%)core::result::Result<T,E>::ok (20 samples, 0.07%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd<&B> for &A>::ge (8 samples, 0.03%)core::cmp::PartialOrd::ge (8 samples, 0.03%)<std::time::Instant as core::ops::arith::Sub>::sub (87 samples, 0.32%)std::time::Instant::duration_since (75 samples, 0.28%)std::time::Instant::checked_duration_since (75 samples, 0.28%)std::sys::unix::time::inner::Instant::checked_sub_instant (75 samples, 0.28%)std::sys::unix::time::Timespec::sub_timespec (55 samples, 0.20%)core::time::Duration::new (10 samples, 0.04%)core::num::<impl u64>::checked_add (5 samples, 0.02%)core::num::<impl u64>::overflowing_add (5 samples, 0.02%)core::cmp::PartialOrd::gt (4 samples, 0.01%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::partial_cmp (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::Ord for u64>::cmp (4 samples, 0.01%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (6 samples, 0.02%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (6 samples, 0.02%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (6 samples, 0.02%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (6 samples, 0.02%)alloc::alloc::dealloc (6 samples, 0.02%)_rjem_sdallocx (3 samples, 0.01%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (4 samples, 0.01%)alloc::vec::Vec<T,A>::as_ptr (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (124 samples, 0.46%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)llist_reverse_order (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (181 samples, 0.67%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)k2o::frame::K2Frame::is_finished (202 samples, 0.75%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (16 samples, 0.06%)k2o::assemble_ng::assembly_worker (2,256 samples, 8.36%)k2o::assembl..k2o::assemble::PendingFrames<F,S>::retire_timed_out (394 samples, 1.46%)asm-frame-0 (2,271 samples, 8.41%)asm-frame-0__GI___clone (2,262 samples, 8.38%)__GI___clonestart_thread (2,262 samples, 8.38%)start_threadstd::sys::unix::thread::Thread::new::thread_start (2,262 samples, 8.38%)std::sys::un..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,262 samples, 8.38%)<alloc::boxe..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,262 samples, 8.38%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,262 samples, 8.38%)core::ops::f..std::thread::Builder::spawn_unchecked_::{{closure}} (2,262 samples, 8.38%)std::thread:..std::panic::catch_unwind (2,262 samples, 8.38%)std::panic::..std::panicking::try (2,262 samples, 8.38%)std::panicki..std::panicking::try::do_call (2,262 samples, 8.38%)std::panicki..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (2,262 samples, 8.38%)<core::panic..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (2,262 samples, 8.38%)std::thread:..std::sys_common::backtrace::__rust_begin_short_backtrace (2,262 samples, 8.38%)std::sys_com..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,262 samples, 8.38%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,262 samples, 8.38%)core::ops::f..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (2,262 samples, 8.38%)crossbeam_ut..k2o::assemble_ng::assembler_main::{{closure}}::{{closure}} (2,262 samples, 8.38%)k2o::assembl..k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)cpuset_cpus_allowed (6 samples, 0.02%)_raw_spin_lock_irqsave (6 samples, 0.02%)[anon] (6 samples, 0.02%)k2o::frame::K2Frame::assign_block (6 samples, 0.02%)k2o::frame::K2Frame::track_block (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (6 samples, 0.02%)ndarray::zip::Zip<(P1,P2),D>::for_each (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core_strided (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core_strided_c (6 samples, 0.02%)ndarray::zip::Zip<P,D>::inner (6 samples, 0.02%)ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (4 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (4 samples, 0.01%)ndarray::zip::Zip<(P1,P2),D>::for_each (4 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core (4 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core_contiguous (4 samples, 0.01%)ndarray::zip::Zip<P,D>::inner (4 samples, 0.01%)_rjem_je_arena_extent_dalloc_large_prep (4 samples, 0.01%)arena_nactive_sub (3 samples, 0.01%)atomic_fetch_sub_zu (3 samples, 0.01%)bitmap_unset (3 samples, 0.01%)extent_deactivate_locked (12 samples, 0.04%)extents_insert_locked (12 samples, 0.04%)extent_can_coalesce (5 samples, 0.02%)extent_arena_get (5 samples, 0.02%)atomic_load_p (5 samples, 0.02%)_rjem_je_extent_dalloc (3 samples, 0.01%)extent_lock2 (3 samples, 0.01%)mutex_pool_lock2 (3 samples, 0.01%)extent_merge_impl (7 samples, 0.03%)extent_coalesce (10 samples, 0.04%)malloc_mutex_lock (24 samples, 0.09%)malloc_mutex_trylock_final (23 samples, 0.09%)__GI___pthread_mutex_trylock (23 samples, 0.09%)extent_lock (26 samples, 0.10%)mutex_pool_lock (26 samples, 0.10%)extent_lock_from_addr (29 samples, 0.11%)extent_rtree_leaf_elm_try_lock (27 samples, 0.10%)malloc_mutex_unlock (3 samples, 0.01%)__pthread_mutex_unlock_usercnt (3 samples, 0.01%)extent_try_coalesce (51 samples, 0.19%)extent_unlock (4 samples, 0.01%)mutex_pool_unlock (4 samples, 0.01%)malloc_mutex_lock (5 samples, 0.02%)malloc_mutex_trylock_final (4 samples, 0.01%)__GI___pthread_mutex_trylock (4 samples, 0.01%)_rjem_je_large_dalloc_finish (74 samples, 0.27%)large_dalloc_finish_impl (74 samples, 0.27%)_rjem_je_arena_extents_dirty_dalloc (74 samples, 0.27%)extent_record (74 samples, 0.27%)arena_decay_ticks (3 samples, 0.01%)_rjem_je_arena_decay (3 samples, 0.01%)arena_decay_dirty (3 samples, 0.01%)arena_decay_impl (3 samples, 0.01%)arena_maybe_decay (3 samples, 0.01%)arena_maybe_decay (3 samples, 0.01%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_try_purge (3 samples, 0.01%)arena_decay_to_limit (3 samples, 0.01%)arena_decay_stashed (3 samples, 0.01%)_rjem_je_extent_purge_lazy_wrapper (3 samples, 0.01%)extent_purge_lazy_impl (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)_rjem_je_pages_purge_lazy (3 samples, 0.01%)__GI_madvise (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_madvise (3 samples, 0.01%)do_madvise.part.0 (3 samples, 0.01%)madvise_free_single_vma (3 samples, 0.01%)walk_page_range (3 samples, 0.01%)__walk_page_range (3 samples, 0.01%)madvise_free_pte_range (3 samples, 0.01%)split_huge_page_to_list (3 samples, 0.01%)__put_page (3 samples, 0.01%)__page_cache_release (3 samples, 0.01%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)core::ptr::drop_in_place<k2o::block::K2ISBlock> (94 samples, 0.35%)core::ptr::drop_in_place<alloc::vec::Vec<u16>> (94 samples, 0.35%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16>> (94 samples, 0.35%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (94 samples, 0.35%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (93 samples, 0.34%)alloc::alloc::dealloc (93 samples, 0.34%)_rjem_sdallocx (93 samples, 0.34%)isfree (93 samples, 0.34%)isdalloct (93 samples, 0.34%)arena_sdalloc (93 samples, 0.34%)tcache_dalloc_large (93 samples, 0.34%)_rjem_je_tcache_bin_flush_large (92 samples, 0.34%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (14 samples, 0.05%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (14 samples, 0.05%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (14 samples, 0.05%)crossbeam_utils::backoff::Backoff::snooze (16 samples, 0.06%)amd_pmu_wait_on_overflow (4 samples, 0.01%)futex_wait_queue_me (11 samples, 0.04%)schedule (11 samples, 0.04%)__schedule (11 samples, 0.04%)__perf_event_task_sched_out (11 samples, 0.04%)amd_pmu_disable_all (11 samples, 0.04%)x86_pmu_disable_all (7 samples, 0.03%)native_write_msr (4 samples, 0.01%)crossbeam_channel::context::Context::wait_until (29 samples, 0.11%)std::thread::park (13 samples, 0.05%)std::sys_common::thread_parker::futex::Parker::park (13 samples, 0.05%)std::sys::unix::futex::futex_wait (12 samples, 0.04%)syscall (12 samples, 0.04%)entry_SYSCALL_64_after_hwframe (12 samples, 0.04%)do_syscall_64 (12 samples, 0.04%)__x64_sys_futex (12 samples, 0.04%)do_futex (12 samples, 0.04%)futex_wait (12 samples, 0.04%)crossbeam_channel::context::Context::with (34 samples, 0.13%)std::thread::local::LocalKey<T>::try_with (34 samples, 0.13%)crossbeam_channel::context::Context::with::{{closure}} (33 samples, 0.12%)crossbeam_channel::context::Context::with::{{closure}} (33 samples, 0.12%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (33 samples, 0.12%)crossbeam_channel::waker::SyncWaker::register (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::read (5 samples, 0.02%)crossbeam_channel::flavors::list::Slot<T>::wait_write (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (4 samples, 0.01%)pick_next_task_fair (4 samples, 0.01%)update_curr (3 samples, 0.01%)__x64_sys_sched_yield (7 samples, 0.03%)schedule (5 samples, 0.02%)__schedule (5 samples, 0.02%)__GI___sched_yield (9 samples, 0.03%)entry_SYSCALL_64_after_hwframe (9 samples, 0.03%)do_syscall_64 (8 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (17 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (17 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (17 samples, 0.06%)crossbeam_channel::channel::Receiver<T>::recv (71 samples, 0.26%)crossbeam_channel::flavors::list::Channel<T>::recv (70 samples, 0.26%)crossbeam_utils::backoff::Backoff::snooze (27 samples, 0.10%)alloc_pages_vma (3 samples, 0.01%)__alloc_pages_nodemask (3 samples, 0.01%)get_page_from_freelist (3 samples, 0.01%)flush_tlb_func_remote (4 samples, 0.01%)kernel_init_free_pages (166 samples, 0.61%)clear_page_rep (166 samples, 0.61%)asm_sysvec_call_function (9 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)alloc_pages_vma (172 samples, 0.64%)__alloc_pages_nodemask (172 samples, 0.64%)get_page_from_freelist (172 samples, 0.64%)prep_new_page (169 samples, 0.63%)prep_compound_page (3 samples, 0.01%)clear_huge_page (53 samples, 0.20%)clear_subpage (52 samples, 0.19%)clear_page_rep (49 samples, 0.18%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)do_huge_pmd_anonymous_page (229 samples, 0.85%)asm_exc_page_fault (233 samples, 0.86%)exc_page_fault (233 samples, 0.86%)do_user_addr_fault (233 samples, 0.86%)handle_mm_fault (233 samples, 0.86%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)flush_tlb_func_remote (8 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (481 samples, 1.78%)<..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (481 samples, 1.78%)<..core::iter::traits::iterator::Iterator::for_each (481 samples, 1.78%)c..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold (481 samples, 1.78%)<..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold (481 samples, 1.78%)<..core::iter::traits::iterator::Iterator::try_fold (481 samples, 1.78%)c..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold::check::{{closure}} (481 samples, 1.78%)<..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold::ok::{{closure}} (481 samples, 1.78%)<..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (481 samples, 1.78%)c..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend::{{closure}} (481 samples, 1.78%)<..core::ptr::write (481 samples, 1.78%)c..__memset_avx2_unaligned_erms (481 samples, 1.78%)_..asm_sysvec_call_function (25 samples, 0.09%)sysvec_call_function (19 samples, 0.07%)__sysvec_call_function (19 samples, 0.07%)flush_smp_call_function_queue (18 samples, 0.07%)llist_reverse_order (3 samples, 0.01%)<k2o::assemble::ChanReuseFrameSource<F> as k2o::assemble::FrameReuseSource<F>>::new_frame_from_block (482 samples, 1.79%)<..k2o::frame::K2Frame::empty_from_block (482 samples, 1.79%)k..<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::empty_with_timestamp (482 samples, 1.79%)<..<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::set_modified_timestamp (3 samples, 0.01%)k2o::frame::K2Frame::track_block (13 samples, 0.05%)std::time::Instant::now (8 samples, 0.03%)std::sys::unix::time::inner::Instant::now (8 samples, 0.03%)std::sys::unix::time::inner::now (8 samples, 0.03%)__GI___clock_gettime (7 samples, 0.03%)__vdso_clock_gettime (3 samples, 0.01%)<(A,B) as ndarray::zip::OffsetTuple>::stride_offset (40 samples, 0.15%)<*mut T as ndarray::zip::ndproducer::Offset>::stride_offset (40 samples, 0.15%)asm_sysvec_call_function (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)flush_tlb_func_remote (10 samples, 0.04%)flush_smp_call_function_queue (42 samples, 0.16%)llist_reverse_order (12 samples, 0.04%)__sysvec_call_function (45 samples, 0.17%)asm_sysvec_call_function (55 samples, 0.20%)sysvec_call_function (46 samples, 0.17%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (921 samples, 3.41%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (919 samples, 3.40%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (919 samples, 3.40%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (919 samples, 3.40%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (919 samples, 3.40%)nda..ndarray::zip::Zip<P,D>::for_each_core (919 samples, 3.40%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided (919 samples, 3.40%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided_c (919 samples, 3.40%)nda..ndarray::zip::Zip<P,D>::inner (918 samples, 3.40%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (844 samples, 3.13%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (844 samples, 3.13%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (844 samples, 3.13%)nda..ndarray::zip::Zip<P,D>::for_each_core (844 samples, 3.13%)nda..ndarray::zip::Zip<P,D>::for_each_core_contiguous (844 samples, 3.13%)nda..ndarray::zip::Zip<P,D>::inner (844 samples, 3.13%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (284 samples, 1.05%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}}::{{closure}} (284 samples, 1.05%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign::{{closure}} (284 samples, 1.05%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (16 samples, 0.06%)__sysvec_call_function (16 samples, 0.06%)flush_smp_call_function_queue (16 samples, 0.06%)llist_reverse_order (5 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::for_each (5 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move::{{closure}} (5 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_axis_inplace (5 samples, 0.02%)k2o::frame::K2Frame::assign_block (943 samples, 3.49%)k2o..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_mut (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move (6 samples, 0.02%)core::hash::BuildHasher::hash_one (3 samples, 0.01%)k2o::assemble::PendingFrames<F,S>::assign_block (1,429 samples, 5.29%)k2o::a..std::collections::hash::map::HashMap<K,V,S>::get_mut (4 samples, 0.01%)hashbrown::map::HashMap<K,V,S,A>::get_mut (4 samples, 0.01%)hashbrown::map::HashMap<K,V,S,A>::get_inner_mut (4 samples, 0.01%)hashbrown::map::make_hash (4 samples, 0.01%)hashbrown::raw::Bucket<T>::next_n (7 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::sub (7 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (6 samples, 0.02%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (39 samples, 0.14%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (39 samples, 0.14%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (38 samples, 0.14%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (37 samples, 0.14%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (18 samples, 0.07%)alloc::vec::Vec<T>::with_capacity (7 samples, 0.03%)alloc::vec::Vec<T,A>::with_capacity_in (7 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (7 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::allocate_in (7 samples, 0.03%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (7 samples, 0.03%)alloc::alloc::Global::alloc_impl (7 samples, 0.03%)alloc::alloc::alloc (7 samples, 0.03%)_rjem_mallocx (6 samples, 0.02%)imalloc (6 samples, 0.02%)imalloc_body (4 samples, 0.01%)imalloc_no_sample (3 samples, 0.01%)iallocztm (3 samples, 0.01%)arena_malloc (3 samples, 0.01%)tcache_alloc_small (3 samples, 0.01%)cache_bin_alloc_easy (3 samples, 0.01%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (5 samples, 0.02%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (5 samples, 0.02%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (5 samples, 0.02%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (5 samples, 0.02%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (5 samples, 0.02%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (5 samples, 0.02%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (5 samples, 0.02%)alloc::alloc::dealloc (5 samples, 0.02%)_rjem_sdallocx (3 samples, 0.01%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (17 samples, 0.06%)alloc::vec::Vec<T,A>::as_ptr (16 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (114 samples, 0.42%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (202 samples, 0.75%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)k2o::assemble::PendingFrames<F,S>::retire_finished (293 samples, 1.09%)k2o::frame::K2Frame::is_finished (238 samples, 0.88%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (15 samples, 0.06%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_modified_timestamp (29 samples, 0.11%)hashbrown::raw::Bucket<T>::next_n (5 samples, 0.02%)core::ptr::mut_ptr::<impl *mut T>::sub (5 samples, 0.02%)core::ptr::mut_ptr::<impl *mut T>::offset (5 samples, 0.02%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (10 samples, 0.04%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (36 samples, 0.13%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (36 samples, 0.13%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (34 samples, 0.13%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (31 samples, 0.11%)core::result::Result<T,E>::ok (11 samples, 0.04%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd<&B> for &A>::ge (12 samples, 0.04%)core::cmp::PartialOrd::ge (12 samples, 0.04%)<std::sys::unix::time::Timespec as core::cmp::PartialOrd>::partial_cmp (9 samples, 0.03%)<std::sys::unix::time::Timespec as core::cmp::Ord>::cmp (9 samples, 0.03%)core::tuple::<impl core::cmp::Ord for (A,B)>::cmp (9 samples, 0.03%)<std::time::Instant as core::ops::arith::Sub>::sub (111 samples, 0.41%)std::time::Instant::duration_since (93 samples, 0.34%)std::time::Instant::checked_duration_since (93 samples, 0.34%)std::sys::unix::time::inner::Instant::checked_sub_instant (93 samples, 0.34%)std::sys::unix::time::Timespec::sub_timespec (82 samples, 0.30%)core::time::Duration::new (12 samples, 0.04%)core::cmp::PartialOrd::gt (4 samples, 0.01%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::partial_cmp (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::Ord for u64>::cmp (4 samples, 0.01%)<std::time::Instant as core::ops::arith::Sub>::sub (3 samples, 0.01%)std::time::Instant::duration_since (3 samples, 0.01%)std::time::Instant::checked_duration_since (3 samples, 0.01%)std::sys::unix::time::inner::Instant::checked_sub_instant (3 samples, 0.01%)std::sys::unix::time::Timespec::sub_timespec (3 samples, 0.01%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (6 samples, 0.02%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (6 samples, 0.02%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (6 samples, 0.02%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (6 samples, 0.02%)alloc::alloc::dealloc (6 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (115 samples, 0.43%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (168 samples, 0.62%)asm_sysvec_call_function (3 samples, 0.01%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (11 samples, 0.04%)k2o::frame::K2Frame::is_finished (182 samples, 0.67%)k2o::assemble_ng::assembly_worker (2,298 samples, 8.51%)k2o::assembl..k2o::assemble::PendingFrames<F,S>::retire_timed_out (410 samples, 1.52%)std::time::Instant::now (7 samples, 0.03%)std::sys::unix::time::inner::Instant::now (7 samples, 0.03%)std::sys::unix::time::inner::now (7 samples, 0.03%)__GI___clock_gettime (7 samples, 0.03%)__vdso_clock_gettime (6 samples, 0.02%)[[vdso]] (5 samples, 0.02%)__GI___clone (2,304 samples, 8.53%)__GI___clonestart_thread (2,304 samples, 8.53%)start_threadstd::sys::unix::thread::Thread::new::thread_start (2,304 samples, 8.53%)std::sys::un..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,304 samples, 8.53%)<alloc::boxe..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,304 samples, 8.53%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,304 samples, 8.53%)core::ops::f..std::thread::Builder::spawn_unchecked_::{{closure}} (2,304 samples, 8.53%)std::thread:..std::panic::catch_unwind (2,304 samples, 8.53%)std::panic::..std::panicking::try (2,304 samples, 8.53%)std::panicki..std::panicking::try::do_call (2,304 samples, 8.53%)std::panicki..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (2,304 samples, 8.53%)<core::panic..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (2,304 samples, 8.53%)std::thread:..std::sys_common::backtrace::__rust_begin_short_backtrace (2,304 samples, 8.53%)std::sys_com..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,304 samples, 8.53%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,304 samples, 8.53%)core::ops::f..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (2,304 samples, 8.53%)crossbeam_ut..k2o::assemble_ng::assembler_main::{{closure}}::{{closure}} (2,304 samples, 8.53%)k2o::assembl..k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)kfree (6 samples, 0.02%)asm-frame-1 (2,313 samples, 8.57%)asm-frame-1asm_sysvec_call_function (4 samples, 0.01%)[anon] (9 samples, 0.03%)k2o::frame::K2Frame::assign_block (7 samples, 0.03%)k2o::frame::K2Frame::track_block (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (7 samples, 0.03%)ndarray::zip::Zip<(P1,P2),D>::for_each (7 samples, 0.03%)ndarray::zip::Zip<P,D>::for_each_core (7 samples, 0.03%)ndarray::zip::Zip<P,D>::for_each_core_strided (7 samples, 0.03%)ndarray::zip::Zip<P,D>::for_each_core_strided_c (7 samples, 0.03%)ndarray::zip::Zip<P,D>::inner (7 samples, 0.03%)ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (6 samples, 0.02%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (6 samples, 0.02%)ndarray::zip::Zip<(P1,P2),D>::for_each (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core (6 samples, 0.02%)ndarray::zip::Zip<P,D>::for_each_core_contiguous (6 samples, 0.02%)ndarray::zip::Zip<P,D>::inner (6 samples, 0.02%)[unknown] (4 samples, 0.01%)_rjem_je_arena_extent_dalloc_large_prep (3 samples, 0.01%)arena_nactive_sub (3 samples, 0.01%)atomic_fetch_sub_zu (3 samples, 0.01%)extent_deactivate_locked (11 samples, 0.04%)extents_insert_locked (11 samples, 0.04%)extent_can_coalesce (5 samples, 0.02%)extent_arena_get (5 samples, 0.02%)atomic_load_p (5 samples, 0.02%)_rjem_je_extent_heap_remove (5 samples, 0.02%)extent_activate_locked (6 samples, 0.02%)extents_remove_locked (6 samples, 0.02%)_rjem_je_extent_avail_insert (4 samples, 0.01%)_rjem_je_extent_dalloc (5 samples, 0.02%)extent_rtree_leaf_elms_lookup (3 samples, 0.01%)extent_merge_impl (18 samples, 0.07%)extent_unlock2 (5 samples, 0.02%)mutex_pool_unlock2 (5 samples, 0.02%)malloc_mutex_unlock (5 samples, 0.02%)__pthread_mutex_unlock_usercnt (5 samples, 0.02%)extent_coalesce (25 samples, 0.09%)malloc_mutex_lock (30 samples, 0.11%)malloc_mutex_trylock_final (30 samples, 0.11%)__GI___pthread_mutex_trylock (29 samples, 0.11%)extent_lock (32 samples, 0.12%)mutex_pool_lock (32 samples, 0.12%)extent_lock_from_addr (35 samples, 0.13%)extent_rtree_leaf_elm_try_lock (34 samples, 0.13%)extent_try_coalesce (68 samples, 0.25%)extent_unlock (3 samples, 0.01%)mutex_pool_unlock (3 samples, 0.01%)malloc_mutex_lock (4 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)_rjem_je_large_dalloc_finish (88 samples, 0.33%)large_dalloc_finish_impl (88 samples, 0.33%)_rjem_je_arena_extents_dirty_dalloc (88 samples, 0.33%)extent_record (88 samples, 0.33%)extent_arena_get (3 samples, 0.01%)atomic_load_p (3 samples, 0.01%)core::ptr::drop_in_place<k2o::block::K2ISBlock> (105 samples, 0.39%)core::ptr::drop_in_place<alloc::vec::Vec<u16>> (105 samples, 0.39%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16>> (105 samples, 0.39%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (105 samples, 0.39%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (105 samples, 0.39%)alloc::alloc::dealloc (105 samples, 0.39%)_rjem_sdallocx (104 samples, 0.39%)isfree (102 samples, 0.38%)isdalloct (102 samples, 0.38%)arena_sdalloc (102 samples, 0.38%)tcache_dalloc_large (100 samples, 0.37%)_rjem_je_tcache_bin_flush_large (100 samples, 0.37%)__GI___sched_yield (3 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (14 samples, 0.05%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (11 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (11 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (11 samples, 0.04%)amd_pmu_wait_on_overflow (3 samples, 0.01%)__perf_event_task_sched_out (5 samples, 0.02%)amd_pmu_disable_all (5 samples, 0.02%)futex_wait_queue_me (8 samples, 0.03%)schedule (8 samples, 0.03%)__schedule (8 samples, 0.03%)crossbeam_channel::context::Context::wait_until (24 samples, 0.09%)std::thread::park (10 samples, 0.04%)std::sys_common::thread_parker::futex::Parker::park (10 samples, 0.04%)std::sys::unix::futex::futex_wait (10 samples, 0.04%)syscall (10 samples, 0.04%)entry_SYSCALL_64_after_hwframe (10 samples, 0.04%)do_syscall_64 (10 samples, 0.04%)__x64_sys_futex (10 samples, 0.04%)do_futex (10 samples, 0.04%)futex_wait (10 samples, 0.04%)crossbeam_channel::context::Context::with (28 samples, 0.10%)std::thread::local::LocalKey<T>::try_with (28 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (27 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (26 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (26 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::read (7 samples, 0.03%)crossbeam_channel::flavors::list::Slot<T>::wait_write (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (8 samples, 0.03%)core::sync::atomic::AtomicUsize::load (3 samples, 0.01%)core::sync::atomic::atomic_load (3 samples, 0.01%)__GI___sched_yield (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (5 samples, 0.02%)do_syscall_64 (5 samples, 0.02%)__x64_sys_sched_yield (4 samples, 0.01%)schedule (3 samples, 0.01%)__schedule (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::recv (68 samples, 0.25%)crossbeam_utils::backoff::Backoff::snooze (23 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (18 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (18 samples, 0.07%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (18 samples, 0.07%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::recv (71 samples, 0.26%)_raw_spin_lock_irqsave (5 samples, 0.02%)native_queued_spin_lock_slowpath (5 samples, 0.02%)kernel_init_free_pages (164 samples, 0.61%)clear_page_rep (163 samples, 0.60%)asm_sysvec_call_function (11 samples, 0.04%)sysvec_call_function (6 samples, 0.02%)asm_call_sysvec_on_stack (6 samples, 0.02%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)alloc_pages_vma (174 samples, 0.64%)__alloc_pages_nodemask (174 samples, 0.64%)get_page_from_freelist (174 samples, 0.64%)prep_new_page (165 samples, 0.61%)clear_huge_page (43 samples, 0.16%)clear_subpage (43 samples, 0.16%)clear_page_rep (43 samples, 0.16%)handle_mm_fault (222 samples, 0.82%)do_huge_pmd_anonymous_page (220 samples, 0.81%)lru_cache_add (3 samples, 0.01%)pagevec_lru_move_fn (3 samples, 0.01%)asm_exc_page_fault (223 samples, 0.83%)exc_page_fault (223 samples, 0.83%)do_user_addr_fault (223 samples, 0.83%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)asm_sysvec_call_function (23 samples, 0.09%)sysvec_call_function (13 samples, 0.05%)__sysvec_call_function (13 samples, 0.05%)flush_smp_call_function_queue (13 samples, 0.05%)llist_reverse_order (4 samples, 0.01%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (458 samples, 1.70%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (458 samples, 1.70%)core::iter::traits::iterator::Iterator::for_each (458 samples, 1.70%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold (458 samples, 1.70%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold (458 samples, 1.70%)core::iter::traits::iterator::Iterator::try_fold (458 samples, 1.70%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold::check::{{closure}} (458 samples, 1.70%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold::ok::{{closure}} (458 samples, 1.70%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (458 samples, 1.70%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend::{{closure}} (458 samples, 1.70%)core::ptr::write (458 samples, 1.70%)__memset_avx2_unaligned_erms (458 samples, 1.70%)<k2o::assemble::ChanReuseFrameSource<F> as k2o::assemble::FrameReuseSource<F>>::new_frame_from_block (461 samples, 1.71%)k2o::frame::K2Frame::empty_from_block (461 samples, 1.71%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::empty_with_timestamp (461 samples, 1.71%)k2o::frame::K2Frame::track_block (20 samples, 0.07%)std::time::Instant::now (13 samples, 0.05%)std::sys::unix::time::inner::Instant::now (12 samples, 0.04%)std::sys::unix::time::inner::now (12 samples, 0.04%)__GI___clock_gettime (12 samples, 0.04%)<(A,B) as ndarray::zip::OffsetTuple>::stride_offset (41 samples, 0.15%)<*mut T as ndarray::zip::ndproducer::Offset>::stride_offset (41 samples, 0.15%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_sysvec_apic_timer_interrupt (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (5 samples, 0.02%)__sysvec_call_function (23 samples, 0.09%)flush_smp_call_function_queue (23 samples, 0.09%)llist_reverse_order (8 samples, 0.03%)asm_sysvec_call_function (32 samples, 0.12%)sysvec_call_function (24 samples, 0.09%)flush_tlb_func_remote (3 samples, 0.01%)flush_smp_call_function_queue (9 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (877 samples, 3.25%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (877 samples, 3.25%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (877 samples, 3.25%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (877 samples, 3.25%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (876 samples, 3.24%)nda..ndarray::zip::Zip<P,D>::for_each_core (876 samples, 3.24%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided (876 samples, 3.24%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided_c (876 samples, 3.24%)nda..ndarray::zip::Zip<P,D>::inner (876 samples, 3.24%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (800 samples, 2.96%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (800 samples, 2.96%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (800 samples, 2.96%)nda..ndarray::zip::Zip<P,D>::for_each_core (800 samples, 2.96%)nda..ndarray::zip::Zip<P,D>::for_each_core_contiguous (800 samples, 2.96%)nda..ndarray::zip::Zip<P,D>::inner (800 samples, 2.96%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (251 samples, 0.93%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}}::{{closure}} (251 samples, 0.93%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign::{{closure}} (251 samples, 0.93%)asm_sysvec_call_function (12 samples, 0.04%)sysvec_call_function (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)k2o::frame::K2Frame::assign_block (901 samples, 3.34%)k2o..k2o::assemble::PendingFrames<F,S>::assign_block (1,365 samples, 5.06%)k2o::a..std::collections::hash::map::HashMap<K,V,S>::get_mut (3 samples, 0.01%)hashbrown::map::HashMap<K,V,S,A>::get_mut (3 samples, 0.01%)hashbrown::map::HashMap<K,V,S,A>::get_inner_mut (3 samples, 0.01%)hashbrown::raw::RawTable<T,A>::get_mut (3 samples, 0.01%)hashbrown::raw::RawTable<T,A>::find (3 samples, 0.01%)hashbrown::raw::RawTableInner<A>::find_inner (3 samples, 0.01%)core::num::<impl isize>::wrapping_neg (3 samples, 0.01%)core::num::<impl isize>::wrapping_sub (3 samples, 0.01%)hashbrown::raw::Bucket<T>::next_n (12 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::sub (12 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (9 samples, 0.03%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (19 samples, 0.07%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (53 samples, 0.20%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (53 samples, 0.20%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (49 samples, 0.18%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (45 samples, 0.17%)alloc::vec::Vec<T>::with_capacity (7 samples, 0.03%)alloc::vec::Vec<T,A>::with_capacity_in (7 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (7 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::allocate_in (7 samples, 0.03%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (7 samples, 0.03%)alloc::alloc::Global::alloc_impl (7 samples, 0.03%)alloc::alloc::alloc (7 samples, 0.03%)_rjem_mallocx (7 samples, 0.03%)imalloc (5 samples, 0.02%)imalloc_body (3 samples, 0.01%)alloc::vec::Vec<T,A>::as_ptr (19 samples, 0.07%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (20 samples, 0.07%)flush_tlb_func_remote (5 samples, 0.02%)asm_sysvec_call_function (20 samples, 0.07%)sysvec_call_function (15 samples, 0.06%)__sysvec_call_function (15 samples, 0.06%)flush_smp_call_function_queue (15 samples, 0.06%)llist_reverse_order (6 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (148 samples, 0.55%)asm_sysvec_call_function (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (233 samples, 0.86%)k2o::assemble::PendingFrames<F,S>::retire_finished (335 samples, 1.24%)k2o::frame::K2Frame::is_finished (272 samples, 1.01%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (12 samples, 0.04%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_modified_timestamp (16 samples, 0.06%)asm_sysvec_call_function (3 samples, 0.01%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (21 samples, 0.08%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (17 samples, 0.06%)hashbrown::raw::Bucket<T>::next_n (4 samples, 0.01%)core::ptr::mut_ptr::<impl *mut T>::sub (4 samples, 0.01%)core::ptr::mut_ptr::<impl *mut T>::offset (4 samples, 0.01%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (25 samples, 0.09%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (25 samples, 0.09%)core::result::Result<T,E>::ok (11 samples, 0.04%)<std::sys::unix::time::Timespec as core::cmp::PartialOrd>::partial_cmp (10 samples, 0.04%)<std::sys::unix::time::Timespec as core::cmp::Ord>::cmp (10 samples, 0.04%)core::tuple::<impl core::cmp::Ord for (A,B)>::cmp (10 samples, 0.04%)core::cmp::impls::<impl core::cmp::Ord for i64>::cmp (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd<&B> for &A>::ge (12 samples, 0.04%)core::cmp::PartialOrd::ge (12 samples, 0.04%)<std::time::Instant as core::ops::arith::Sub>::sub (89 samples, 0.33%)std::time::Instant::duration_since (74 samples, 0.27%)std::time::Instant::checked_duration_since (74 samples, 0.27%)std::sys::unix::time::inner::Instant::checked_sub_instant (74 samples, 0.27%)std::sys::unix::time::Timespec::sub_timespec (63 samples, 0.23%)core::time::Duration::new (11 samples, 0.04%)core::num::<impl u64>::checked_add (5 samples, 0.02%)core::num::<impl u64>::overflowing_add (5 samples, 0.02%)core::cmp::PartialOrd::gt (3 samples, 0.01%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::partial_cmp (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::Ord for u64>::cmp (3 samples, 0.01%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (8 samples, 0.03%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (8 samples, 0.03%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (8 samples, 0.03%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (8 samples, 0.03%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (8 samples, 0.03%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (8 samples, 0.03%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (8 samples, 0.03%)alloc::alloc::dealloc (8 samples, 0.03%)_rjem_sdallocx (4 samples, 0.01%)flush_smp_call_function_queue (9 samples, 0.03%)llist_reverse_order (6 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (195 samples, 0.72%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (140 samples, 0.52%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)k2o::frame::K2Frame::is_finished (209 samples, 0.77%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (12 samples, 0.04%)[[vdso]] (5 samples, 0.02%)k2o::assemble_ng::assembly_worker (2,278 samples, 8.44%)k2o::assembl..k2o::assemble::PendingFrames<F,S>::retire_timed_out (401 samples, 1.49%)std::time::Instant::now (9 samples, 0.03%)std::sys::unix::time::inner::Instant::now (9 samples, 0.03%)std::sys::unix::time::inner::now (9 samples, 0.03%)__GI___clock_gettime (9 samples, 0.03%)__vdso_clock_gettime (7 samples, 0.03%)asm-frame-2 (2,297 samples, 8.51%)asm-frame-2__GI___clone (2,284 samples, 8.46%)__GI___clonestart_thread (2,284 samples, 8.46%)start_threadstd::sys::unix::thread::Thread::new::thread_start (2,284 samples, 8.46%)std::sys::un..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,284 samples, 8.46%)<alloc::boxe..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,284 samples, 8.46%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,284 samples, 8.46%)core::ops::f..std::thread::Builder::spawn_unchecked_::{{closure}} (2,284 samples, 8.46%)std::thread:..std::panic::catch_unwind (2,284 samples, 8.46%)std::panic::..std::panicking::try (2,284 samples, 8.46%)std::panicki..std::panicking::try::do_call (2,284 samples, 8.46%)std::panicki..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (2,284 samples, 8.46%)<core::panic..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (2,284 samples, 8.46%)std::thread:..std::sys_common::backtrace::__rust_begin_short_backtrace (2,284 samples, 8.46%)std::sys_com..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,284 samples, 8.46%)<alloc::boxe..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,284 samples, 8.46%)core::ops::f..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (2,284 samples, 8.46%)crossbeam_ut..k2o::assemble_ng::assembler_main::{{closure}}::{{closure}} (2,284 samples, 8.46%)k2o::assembl..k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)cpuset_cpus_allowed (6 samples, 0.02%)guarantee_online_cpus (6 samples, 0.02%)__bitmap_intersects (6 samples, 0.02%)[anon] (6 samples, 0.02%)k2o::frame::K2Frame::assign_block (3 samples, 0.01%)k2o::frame::K2Frame::track_block (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (3 samples, 0.01%)ndarray::zip::Zip<(P1,P2),D>::for_each (3 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core (3 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core_strided (3 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core_strided_c (3 samples, 0.01%)ndarray::zip::Zip<P,D>::inner (3 samples, 0.01%)ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (3 samples, 0.01%)ndarray::zip::Zip<(P1,P2),D>::for_each (3 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core (3 samples, 0.01%)ndarray::zip::Zip<P,D>::for_each_core_contiguous (3 samples, 0.01%)ndarray::zip::Zip<P,D>::inner (3 samples, 0.01%)[unknown] (6 samples, 0.02%)syscall (3 samples, 0.01%)_rjem_je_arena_extent_dalloc_large_prep (3 samples, 0.01%)extent_deactivate_locked (5 samples, 0.02%)extents_insert_locked (5 samples, 0.02%)extent_size_quantize_floor (3 samples, 0.01%)extent_can_coalesce (6 samples, 0.02%)extent_arena_get (5 samples, 0.02%)atomic_load_p (5 samples, 0.02%)extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)extent_merge_impl (7 samples, 0.03%)extent_unlock2 (3 samples, 0.01%)mutex_pool_unlock2 (3 samples, 0.01%)malloc_mutex_unlock (3 samples, 0.01%)__pthread_mutex_unlock_usercnt (3 samples, 0.01%)extent_coalesce (13 samples, 0.05%)malloc_mutex_lock (26 samples, 0.10%)malloc_mutex_trylock_final (25 samples, 0.09%)__GI___pthread_mutex_trylock (25 samples, 0.09%)extent_lock (30 samples, 0.11%)mutex_pool_lock (30 samples, 0.11%)mutex_pool_mutex (4 samples, 0.01%)hash (3 samples, 0.01%)hash_x64_128 (3 samples, 0.01%)hash_fmix_64 (3 samples, 0.01%)extent_lock_from_addr (33 samples, 0.12%)extent_rtree_leaf_elm_try_lock (33 samples, 0.12%)rtree_leaf_elm_extent_read (3 samples, 0.01%)rtree_leaf_elm_bits_extent_get (3 samples, 0.01%)extent_try_coalesce (54 samples, 0.20%)malloc_mutex_lock (7 samples, 0.03%)malloc_mutex_trylock_final (7 samples, 0.03%)__GI___pthread_mutex_trylock (7 samples, 0.03%)_rjem_je_large_dalloc_finish (69 samples, 0.26%)large_dalloc_finish_impl (69 samples, 0.26%)_rjem_je_arena_extents_dirty_dalloc (69 samples, 0.26%)extent_record (69 samples, 0.26%)arena_decay_ticks (9 samples, 0.03%)_rjem_je_arena_decay (9 samples, 0.03%)arena_decay_dirty (9 samples, 0.03%)arena_decay_impl (9 samples, 0.03%)arena_maybe_decay (9 samples, 0.03%)arena_maybe_decay (9 samples, 0.03%)arena_decay_try_purge (9 samples, 0.03%)arena_decay_try_purge (9 samples, 0.03%)arena_decay_to_limit (9 samples, 0.03%)arena_decay_stashed (9 samples, 0.03%)_rjem_je_extent_purge_lazy_wrapper (9 samples, 0.03%)extent_purge_lazy_impl (9 samples, 0.03%)_rjem_je_pages_purge_lazy (9 samples, 0.03%)_rjem_je_pages_purge_lazy (9 samples, 0.03%)__GI_madvise (9 samples, 0.03%)entry_SYSCALL_64_after_hwframe (9 samples, 0.03%)do_syscall_64 (9 samples, 0.03%)__x64_sys_madvise (9 samples, 0.03%)do_madvise.part.0 (9 samples, 0.03%)madvise_free_single_vma (8 samples, 0.03%)walk_page_range (8 samples, 0.03%)__walk_page_range (8 samples, 0.03%)madvise_free_pte_range (8 samples, 0.03%)split_huge_page_to_list (8 samples, 0.03%)try_to_unmap (6 samples, 0.02%)rmap_walk_anon (6 samples, 0.02%)try_to_unmap_one (6 samples, 0.02%)ptep_clear_flush (6 samples, 0.02%)flush_tlb_mm_range (6 samples, 0.02%)on_each_cpu_cond_mask (6 samples, 0.02%)smp_call_function_many_cond (5 samples, 0.02%)extent_arena_get (3 samples, 0.01%)atomic_load_p (3 samples, 0.01%)_rjem_je_tcache_bin_flush_large (89 samples, 0.33%)tcache_dalloc_large (90 samples, 0.33%)_rjem_sdallocx (93 samples, 0.34%)isfree (93 samples, 0.34%)isdalloct (93 samples, 0.34%)arena_sdalloc (93 samples, 0.34%)core::ptr::drop_in_place<k2o::block::K2ISBlock> (94 samples, 0.35%)core::ptr::drop_in_place<alloc::vec::Vec<u16>> (94 samples, 0.35%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16>> (94 samples, 0.35%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (94 samples, 0.35%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (94 samples, 0.35%)alloc::alloc::dealloc (94 samples, 0.35%)__GI___sched_yield (3 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (15 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (12 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (12 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (12 samples, 0.04%)__const_udelay (5 samples, 0.02%)amd_pmu_wait_on_overflow (8 samples, 0.03%)futex_wait_queue_me (10 samples, 0.04%)schedule (10 samples, 0.04%)__schedule (10 samples, 0.04%)__perf_event_task_sched_out (10 samples, 0.04%)amd_pmu_disable_all (10 samples, 0.04%)crossbeam_channel::context::Context::wait_until (26 samples, 0.10%)std::thread::park (11 samples, 0.04%)std::sys_common::thread_parker::futex::Parker::park (11 samples, 0.04%)std::sys::unix::futex::futex_wait (11 samples, 0.04%)syscall (11 samples, 0.04%)entry_SYSCALL_64_after_hwframe (11 samples, 0.04%)do_syscall_64 (11 samples, 0.04%)__x64_sys_futex (11 samples, 0.04%)do_futex (11 samples, 0.04%)futex_wait (11 samples, 0.04%)crossbeam_channel::context::Context::with (28 samples, 0.10%)std::thread::local::LocalKey<T>::try_with (28 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (27 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (27 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (27 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::read (4 samples, 0.01%)crossbeam_channel::flavors::list::Slot<T>::wait_write (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (7 samples, 0.03%)__GI___sched_yield (3 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (19 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (19 samples, 0.07%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (19 samples, 0.07%)crossbeam_channel::channel::Receiver<T>::recv (66 samples, 0.24%)crossbeam_channel::flavors::list::Channel<T>::recv (64 samples, 0.24%)crossbeam_utils::backoff::Backoff::snooze (23 samples, 0.09%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_reverse_order (5 samples, 0.02%)kernel_init_free_pages (145 samples, 0.54%)clear_page_rep (145 samples, 0.54%)asm_sysvec_call_function (16 samples, 0.06%)sysvec_call_function (8 samples, 0.03%)alloc_pages_vma (152 samples, 0.56%)__alloc_pages_nodemask (152 samples, 0.56%)get_page_from_freelist (151 samples, 0.56%)prep_new_page (146 samples, 0.54%)clear_huge_page (49 samples, 0.18%)clear_subpage (45 samples, 0.17%)clear_page_rep (45 samples, 0.17%)handle_mm_fault (207 samples, 0.77%)do_huge_pmd_anonymous_page (205 samples, 0.76%)asm_exc_page_fault (210 samples, 0.78%)exc_page_fault (208 samples, 0.77%)do_user_addr_fault (208 samples, 0.77%)flush_tlb_func_remote (6 samples, 0.02%)asm_sysvec_call_function (11 samples, 0.04%)sysvec_call_function (8 samples, 0.03%)__sysvec_call_function (8 samples, 0.03%)flush_smp_call_function_queue (8 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (444 samples, 1.64%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (444 samples, 1.64%)core::iter::traits::iterator::Iterator::for_each (444 samples, 1.64%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold (444 samples, 1.64%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold (444 samples, 1.64%)core::iter::traits::iterator::Iterator::try_fold (444 samples, 1.64%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold::check::{{closure}} (444 samples, 1.64%)<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold::ok::{{closure}} (444 samples, 1.64%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (444 samples, 1.64%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend::{{closure}} (444 samples, 1.64%)core::ptr::write (444 samples, 1.64%)__memset_avx2_unaligned_erms (444 samples, 1.64%)<k2o::assemble::ChanReuseFrameSource<F> as k2o::assemble::FrameReuseSource<F>>::new_frame_from_block (448 samples, 1.66%)k2o::frame::K2Frame::empty_from_block (448 samples, 1.66%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::empty_with_timestamp (448 samples, 1.66%)alloc::vec::Vec<T,A>::with_capacity_in (4 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (4 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::allocate_in (4 samples, 0.01%)<k2o::dio::PageAlignedAllocator as core::alloc::Allocator>::allocate (4 samples, 0.01%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (4 samples, 0.01%)alloc::alloc::Global::alloc_impl (4 samples, 0.01%)alloc::alloc::alloc (4 samples, 0.01%)_rjem_mallocx (4 samples, 0.01%)imalloc (4 samples, 0.01%)imalloc_body (4 samples, 0.01%)imalloc_no_sample (4 samples, 0.01%)ipalloct (4 samples, 0.01%)ipallocztm (4 samples, 0.01%)_rjem_je_large_palloc (4 samples, 0.01%)_rjem_je_arena_extent_alloc_large (3 samples, 0.01%)_rjem_je_extent_alloc_wrapper (3 samples, 0.01%)extent_alloc_retained (3 samples, 0.01%)extent_grow_retained (3 samples, 0.01%)extent_register_no_gdump_add (3 samples, 0.01%)extent_register_impl (3 samples, 0.01%)k2o::block::K2Block::get_x_offset (3 samples, 0.01%)k2o::frame::K2Frame::track_block (16 samples, 0.06%)std::time::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::now (4 samples, 0.01%)__GI___clock_gettime (4 samples, 0.01%)__vdso_clock_gettime (3 samples, 0.01%)<(A,B) as ndarray::zip::OffsetTuple>::stride_offset (32 samples, 0.12%)<*mut T as ndarray::zip::ndproducer::Offset>::stride_offset (32 samples, 0.12%)asm_sysvec_call_function (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (7 samples, 0.03%)flush_tlb_func_remote (11 samples, 0.04%)__sysvec_call_function (35 samples, 0.13%)flush_smp_call_function_queue (35 samples, 0.13%)llist_reverse_order (10 samples, 0.04%)asm_sysvec_call_function (41 samples, 0.15%)sysvec_call_function (36 samples, 0.13%)flush_tlb_func_remote (6 samples, 0.02%)asm_sysvec_call_function (15 samples, 0.06%)sysvec_call_function (15 samples, 0.06%)__sysvec_call_function (15 samples, 0.06%)flush_smp_call_function_queue (15 samples, 0.06%)llist_reverse_order (9 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign (843 samples, 3.12%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with (843 samples, 3.12%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_same_shape (843 samples, 3.12%)nda..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows (843 samples, 3.12%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each (843 samples, 3.12%)nda..ndarray::zip::Zip<P,D>::for_each_core (843 samples, 3.12%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided (843 samples, 3.12%)nda..ndarray::zip::Zip<P,D>::for_each_core_strided_c (843 samples, 3.12%)nda..ndarray::zip::Zip<P,D>::inner (843 samples, 3.12%)nda..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (777 samples, 2.88%)nd..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}} (777 samples, 2.88%)nd..ndarray::zip::Zip<(P1,P2),D>::for_each (777 samples, 2.88%)nd..ndarray::zip::Zip<P,D>::for_each_core (777 samples, 2.88%)nd..ndarray::zip::Zip<P,D>::for_each_core_contiguous (777 samples, 2.88%)nd..ndarray::zip::Zip<P,D>::inner (777 samples, 2.88%)nd..ndarray::zip::Zip<(P1,P2),D>::for_each::{{closure}} (247 samples, 0.91%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::zip_mut_with_by_rows::{{closure}}::{{closure}} (247 samples, 0.91%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::assign::{{closure}} (247 samples, 0.91%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::for_each (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move::{{closure}} (3 samples, 0.01%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_axis_inplace (3 samples, 0.01%)k2o::frame::K2Frame::assign_block (867 samples, 3.21%)k2o..ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_mut (7 samples, 0.03%)ndarray::impl_methods::<impl ndarray::ArrayBase<S,D>>::slice_move (7 samples, 0.03%)k2o::assemble::PendingFrames<F,S>::assign_block (1,317 samples, 4.88%)k2o::a..core::num::<impl isize>::wrapping_neg (4 samples, 0.01%)core::num::<impl isize>::wrapping_sub (4 samples, 0.01%)hashbrown::raw::Bucket<T>::next_n (11 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::sub (11 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (7 samples, 0.03%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (45 samples, 0.17%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (45 samples, 0.17%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (44 samples, 0.16%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (41 samples, 0.15%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (20 samples, 0.07%)alloc::vec::Vec<T>::with_capacity (3 samples, 0.01%)alloc::vec::Vec<T,A>::with_capacity_in (3 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (3 samples, 0.01%)alloc::raw_vec::RawVec<T,A>::allocate_in (3 samples, 0.01%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (3 samples, 0.01%)alloc::alloc::Global::alloc_impl (3 samples, 0.01%)alloc::alloc::alloc (3 samples, 0.01%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (17 samples, 0.06%)alloc::vec::Vec<T,A>::as_ptr (14 samples, 0.05%)flush_tlb_func_remote (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (153 samples, 0.57%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)flush_tlb_func_remote (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (240 samples, 0.89%)asm_sysvec_call_function (9 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)k2o::assemble::PendingFrames<F,S>::retire_finished (330 samples, 1.22%)k2o::frame::K2Frame::is_finished (279 samples, 1.03%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (18 samples, 0.07%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_modified_timestamp (20 samples, 0.07%)hashbrown::raw::Bucket<T>::next_n (10 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::sub (10 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (9 samples, 0.03%)hashbrown::raw::bitmask::BitMask::lowest_set_bit (4 samples, 0.01%)<std::collections::hash::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (38 samples, 0.14%)<hashbrown::map::Iter<K,V> as core::iter::traits::iterator::Iterator>::next (38 samples, 0.14%)<hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next (33 samples, 0.12%)<hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next (23 samples, 0.09%)core::result::Result<T,E>::ok (11 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd<&B> for &A>::ge (14 samples, 0.05%)core::cmp::PartialOrd::ge (14 samples, 0.05%)<std::sys::unix::time::Timespec as core::cmp::PartialOrd>::partial_cmp (11 samples, 0.04%)<std::sys::unix::time::Timespec as core::cmp::Ord>::cmp (11 samples, 0.04%)core::tuple::<impl core::cmp::Ord for (A,B)>::cmp (11 samples, 0.04%)<std::time::Instant as core::ops::arith::Sub>::sub (113 samples, 0.42%)std::time::Instant::duration_since (96 samples, 0.36%)std::time::Instant::checked_duration_since (96 samples, 0.36%)std::sys::unix::time::inner::Instant::checked_sub_instant (96 samples, 0.36%)std::sys::unix::time::Timespec::sub_timespec (85 samples, 0.31%)core::time::Duration::new (15 samples, 0.06%)core::num::<impl u64>::checked_add (5 samples, 0.02%)core::num::<impl u64>::overflowing_add (5 samples, 0.02%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u32>> (6 samples, 0.02%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u32,alloc::alloc::Global>> (6 samples, 0.02%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u32>> (6 samples, 0.02%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (6 samples, 0.02%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (6 samples, 0.02%)alloc::alloc::dealloc (6 samples, 0.02%)_rjem_sdallocx (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (105 samples, 0.39%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::all (160 samples, 0.59%)k2o::frame::K2Frame::is_finished (173 samples, 0.64%)<k2o::frame::K2ISFrame as k2o::frame::K2Frame>::get_tracker (10 samples, 0.04%)k2o::assemble_ng::assembly_worker (2,200 samples, 8.15%)k2o::assemb..k2o::assemble::PendingFrames<F,S>::retire_timed_out (392 samples, 1.45%)std::time::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::now (5 samples, 0.02%)__GI___clock_gettime (5 samples, 0.02%)__vdso_clock_gettime (3 samples, 0.01%)[[vdso]] (3 samples, 0.01%)std::panic::catch_unwind (2,206 samples, 8.17%)std::panic:..std::panicking::try (2,206 samples, 8.17%)std::panick..std::panicking::try::do_call (2,206 samples, 8.17%)std::panick..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (2,206 samples, 8.17%)<core::pani..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (2,206 samples, 8.17%)std::thread..std::sys_common::backtrace::__rust_begin_short_backtrace (2,206 samples, 8.17%)std::sys_co..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,206 samples, 8.17%)<alloc::box..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,206 samples, 8.17%)core::ops::..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (2,206 samples, 8.17%)crossbeam_u..k2o::assemble_ng::assembler_main::{{closure}}::{{closure}} (2,206 samples, 8.17%)k2o::assemb..k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)kfree (6 samples, 0.02%)asm-frame-3 (2,219 samples, 8.22%)asm-frame-3__GI___clone (2,207 samples, 8.17%)__GI___clonestart_thread (2,207 samples, 8.17%)start_threadstd::sys::unix::thread::Thread::new::thread_start (2,207 samples, 8.17%)std::sys::u..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,207 samples, 8.17%)<alloc::box..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (2,207 samples, 8.17%)<alloc::box..core::ops::function::FnOnce::call_once{{vtable.shim}} (2,207 samples, 8.17%)core::ops::..std::thread::Builder::spawn_unchecked_::{{closure}} (2,207 samples, 8.17%)std::thread.._raw_spin_lock_irq (6 samples, 0.02%)calculate_sigpending (12 samples, 0.04%)recalc_sigpending (6 samples, 0.02%)ret_from_fork (24 samples, 0.09%)syscall_exit_to_user_mode (12 samples, 0.04%)exit_to_user_mode_prepare (12 samples, 0.04%)switch_fpu_return (12 samples, 0.04%)copy_kernel_to_fpregs (6 samples, 0.02%)core::ptr::drop_in_place<crossbeam_channel::channel::Sender<k2o::block::K2ISBlock>> (3 samples, 0.01%)<crossbeam_channel::channel::Sender<T> as core::ops::drop::Drop>::drop (3 samples, 0.01%)asm_sysvec_call_function (4 samples, 0.01%)__GI___sched_yield (6 samples, 0.02%)<crossbeam_channel::select::Token as core::default::Default>::default (8 samples, 0.03%)asm_sysvec_call_function (11 samples, 0.04%)__GI___sched_yield (18 samples, 0.07%)error_entry (4 samples, 0.01%)sync_regs (3 samples, 0.01%)<crossbeam_channel::select::Selected as core::convert::From<usize>>::from (13 samples, 0.05%)entry_SYSCALL_64 (8 samples, 0.03%)do_sched_yield (8 samples, 0.03%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)pick_next_entity (3 samples, 0.01%)pick_next_task_fair (17 samples, 0.06%)update_curr (7 samples, 0.03%)do_syscall_64 (51 samples, 0.19%)__x64_sys_sched_yield (50 samples, 0.19%)schedule (42 samples, 0.16%)__schedule (42 samples, 0.16%)update_rq_clock (8 samples, 0.03%)sched_clock_cpu (6 samples, 0.02%)sched_clock (6 samples, 0.02%)native_sched_clock (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (56 samples, 0.21%)__GI___sched_yield (70 samples, 0.26%)syscall_return_via_sysret (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_smp_call_function_queue (12 samples, 0.04%)llist_reverse_order (4 samples, 0.01%)asm_sysvec_call_function (13 samples, 0.05%)sysvec_call_function (13 samples, 0.05%)__sysvec_call_function (13 samples, 0.05%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (316 samples, 1.17%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (316 samples, 1.17%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (316 samples, 1.17%)core::sync::atomic::spin_loop_hint (10 samples, 0.04%)core::hint::spin_loop (10 samples, 0.04%)core::core_arch::x86::sse2::_mm_pause (10 samples, 0.04%)crossbeam_utils::backoff::Backoff::snooze (397 samples, 1.47%)__const_udelay (24 samples, 0.09%)delay_halt (14 samples, 0.05%)delay_halt_mwaitx (14 samples, 0.05%)amd_pmu_wait_on_overflow (57 samples, 0.21%)native_read_msr (16 samples, 0.06%)amd_pmu_addr_offset (4 samples, 0.01%)native_read_msr (19 samples, 0.07%)amd_pmu_disable_all (118 samples, 0.44%)x86_pmu_disable_all (61 samples, 0.23%)native_write_msr (31 samples, 0.11%)__perf_event_task_sched_out (124 samples, 0.46%)dequeue_task_fair (10 samples, 0.04%)dequeue_entity (7 samples, 0.03%)finish_task_switch (8 samples, 0.03%)__mmdrop (7 samples, 0.03%)__free_pages_ok (7 samples, 0.03%)__memcg_kmem_uncharge_page (7 samples, 0.03%)pick_next_task_fair (3 samples, 0.01%)newidle_balance (3 samples, 0.01%)pick_next_task_idle (3 samples, 0.01%)__update_idle_core (3 samples, 0.01%)psi_task_change (20 samples, 0.07%)psi_group_change (19 samples, 0.07%)record_times (7 samples, 0.03%)sched_clock_cpu (6 samples, 0.02%)sched_clock (6 samples, 0.02%)native_sched_clock (6 samples, 0.02%)__schedule (174 samples, 0.64%)futex_wait_queue_me (186 samples, 0.69%)schedule (186 samples, 0.69%)__x64_sys_futex (212 samples, 0.79%)do_futex (212 samples, 0.79%)futex_wait (210 samples, 0.78%)futex_wait_setup (16 samples, 0.06%)entry_SYSCALL_64_after_hwframe (213 samples, 0.79%)do_syscall_64 (213 samples, 0.79%)std::sys_common::thread_parker::futex::Parker::park (228 samples, 0.84%)std::sys::unix::futex::futex_wait (221 samples, 0.82%)syscall (221 samples, 0.82%)syscall_return_via_sysret (6 samples, 0.02%)std::sys_common::thread_info::THREAD_INFO::__getit (3 samples, 0.01%)crossbeam_channel::context::Context::wait_until (649 samples, 2.40%)cr..std::thread::park (235 samples, 0.87%)std::thread::current (7 samples, 0.03%)std::sys_common::thread_info::current_thread (6 samples, 0.02%)std::sys_common::thread_info::ThreadInfo::with (6 samples, 0.02%)std::thread::local::LocalKey<T>::try_with (6 samples, 0.02%)std::sys_common::thread_info::ThreadInfo::with::{{closure}} (3 samples, 0.01%)std::sys_common::thread_info::current_thread::{{closure}} (3 samples, 0.01%)<std::thread::Thread as core::clone::Clone>::clone (3 samples, 0.01%)<alloc::sync::Arc<T> as core::clone::Clone>::clone (3 samples, 0.01%)core::ptr::drop_in_place<crossbeam_channel::utils::SpinlockGuard<crossbeam_channel::waker::Waker>> (20 samples, 0.07%)<crossbeam_channel::utils::SpinlockGuard<T> as core::ops::drop::Drop>::drop (20 samples, 0.07%)crossbeam_channel::utils::Spinlock<T>::lock (18 samples, 0.07%)core::sync::atomic::AtomicBool::swap (18 samples, 0.07%)core::sync::atomic::atomic_swap (18 samples, 0.07%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)<crossbeam_channel::context::Context as core::clone::Clone>::clone (4 samples, 0.01%)<alloc::sync::Arc<T> as core::clone::Clone>::clone (4 samples, 0.01%)crossbeam_channel::waker::SyncWaker::register (43 samples, 0.16%)crossbeam_channel::waker::Waker::register (5 samples, 0.02%)crossbeam_channel::waker::Waker::register_with_packet (5 samples, 0.02%)crossbeam_channel::context::Context::with (715 samples, 2.65%)cr..std::thread::local::LocalKey<T>::try_with (715 samples, 2.65%)st..crossbeam_channel::context::Context::with::{{closure}} (715 samples, 2.65%)cr..crossbeam_channel::context::Context::with::{{closure}} (696 samples, 2.58%)cr..crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (696 samples, 2.58%)cr.._rjem_je_arena_dalloc_bin_junked_locked (3 samples, 0.01%)arena_dalloc_bin_locked_impl (3 samples, 0.01%)arena_dalloc_bin_slab (3 samples, 0.01%)_rjem_sdallocx (8 samples, 0.03%)isfree (8 samples, 0.03%)isdalloct (8 samples, 0.03%)arena_sdalloc (8 samples, 0.03%)tcache_dalloc_small (8 samples, 0.03%)_rjem_je_tcache_bin_flush_small (7 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::read (3 samples, 0.01%)core::ptr::read (3 samples, 0.01%)core::slice::<impl [T]>::get_unchecked (42 samples, 0.16%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked (42 samples, 0.16%)core::ptr::const_ptr::<impl *const T>::add (42 samples, 0.16%)core::ptr::const_ptr::<impl *const T>::offset (42 samples, 0.16%)core::sync::atomic::AtomicUsize::fetch_or (6 samples, 0.02%)core::sync::atomic::atomic_or (6 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::read (71 samples, 0.26%)crossbeam_channel::flavors::list::Slot<T>::wait_write (5 samples, 0.02%)crossbeam_utils::backoff::Backoff::snooze (4 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (4 samples, 0.01%)core::sync::atomic::AtomicPtr<T>::load (4 samples, 0.01%)core::sync::atomic::atomic_load (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (135 samples, 0.50%)core::sync::atomic::AtomicUsize::load (65 samples, 0.24%)core::sync::atomic::atomic_load (65 samples, 0.24%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)entry_SYSCALL_64 (8 samples, 0.03%)_raw_spin_lock (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)do_sched_yield (16 samples, 0.06%)yield_task_fair (5 samples, 0.02%)asm_sysvec_call_function (12 samples, 0.04%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)__list_add_valid (4 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)cpuacct_charge (13 samples, 0.05%)pick_next_task_fair (40 samples, 0.15%)update_curr (22 samples, 0.08%)update_min_vruntime (3 samples, 0.01%)__x64_sys_sched_yield (106 samples, 0.39%)schedule (88 samples, 0.33%)__schedule (86 samples, 0.32%)update_rq_clock (14 samples, 0.05%)sched_clock_cpu (11 samples, 0.04%)sched_clock (11 samples, 0.04%)native_sched_clock (11 samples, 0.04%)do_syscall_64 (111 samples, 0.41%)entry_SYSCALL_64_after_hwframe (115 samples, 0.43%)__GI___sched_yield (132 samples, 0.49%)flush_tlb_func_remote (3 samples, 0.01%)flush_smp_call_function_queue (26 samples, 0.10%)llist_reverse_order (10 samples, 0.04%)asm_sysvec_call_function (29 samples, 0.11%)sysvec_call_function (27 samples, 0.10%)__sysvec_call_function (27 samples, 0.10%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (641 samples, 2.37%)co..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (641 samples, 2.37%)<c..core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (637 samples, 2.36%)c..core::sync::atomic::spin_loop_hint (26 samples, 0.10%)core::hint::spin_loop (26 samples, 0.10%)core::core_arch::x86::sse2::_mm_pause (26 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (3 samples, 0.01%)crossbeam_channel::context::Context::wait_until (3 samples, 0.01%)std::thread::park (3 samples, 0.01%)std::sys_common::thread_parker::futex::Parker::park (3 samples, 0.01%)std::sys::unix::futex::futex_wait (3 samples, 0.01%)syscall (3 samples, 0.01%)entry_SYSCALL_64 (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::recv (1,751 samples, 6.48%)crossbea..crossbeam_channel::flavors::list::Channel<T>::recv (1,749 samples, 6.48%)crossbea..crossbeam_utils::backoff::Backoff::snooze (810 samples, 3.00%)cro..std::thread::yield_now (3 samples, 0.01%)std::sys::unix::thread::Thread::yield_now (3 samples, 0.01%)__memset_avx2_unaligned_erms (18 samples, 0.07%)arena_bin_nonfull_slab_get (3 samples, 0.01%)_rjem_je_tcache_alloc_small_hard (6 samples, 0.02%)_rjem_je_arena_tcache_fill_small (6 samples, 0.02%)arena_bin_malloc_hard (6 samples, 0.02%)arena_slab_reg_alloc (3 samples, 0.01%)bitmap_sfu (3 samples, 0.01%)ffs_lu (3 samples, 0.01%)alloc::boxed::Box<T>::new (27 samples, 0.10%)alloc::alloc::exchange_malloc (9 samples, 0.03%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (9 samples, 0.03%)alloc::alloc::Global::alloc_impl (9 samples, 0.03%)alloc::alloc::alloc (9 samples, 0.03%)_rjem_mallocx (7 samples, 0.03%)imalloc (7 samples, 0.03%)imalloc_body (7 samples, 0.03%)imalloc_no_sample (7 samples, 0.03%)iallocztm (7 samples, 0.03%)arena_malloc (7 samples, 0.03%)tcache_alloc_small (7 samples, 0.03%)core::sync::atomic::AtomicPtr<T>::load (9 samples, 0.03%)core::sync::atomic::atomic_load (9 samples, 0.03%)crossbeam_channel::flavors::list::Channel<T>::start_send (49 samples, 0.18%)__smp_call_single_queue (3 samples, 0.01%)llist_add_batch (3 samples, 0.01%)do_syscall_64 (20 samples, 0.07%)__x64_sys_futex (20 samples, 0.07%)do_futex (19 samples, 0.07%)futex_wake (19 samples, 0.07%)wake_up_q (10 samples, 0.04%)try_to_wake_up (9 samples, 0.03%)ttwu_queue_wakelist (8 samples, 0.03%)entry_SYSCALL_64_after_hwframe (21 samples, 0.08%)crossbeam_channel::channel::Sender<T>::send (95 samples, 0.35%)crossbeam_channel::flavors::list::Channel<T>::send (91 samples, 0.34%)crossbeam_channel::flavors::list::Channel<T>::write (39 samples, 0.14%)crossbeam_channel::waker::SyncWaker::notify (27 samples, 0.10%)crossbeam_channel::waker::Waker::try_select (27 samples, 0.10%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (27 samples, 0.10%)crossbeam_channel::waker::Waker::try_select::{{closure}} (27 samples, 0.10%)crossbeam_channel::context::Context::unpark (23 samples, 0.09%)std::thread::Thread::unpark (23 samples, 0.09%)std::sys_common::thread_parker::futex::Parker::unpark (23 samples, 0.09%)syscall (22 samples, 0.08%)<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,852 samples, 6.86%)<alloc::b..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,852 samples, 6.86%)<alloc::b..core::ops::function::FnOnce::call_once{{vtable.shim}} (1,852 samples, 6.86%)core::ops..std::thread::Builder::spawn_unchecked_::{{closure}} (1,852 samples, 6.86%)std::thre..std::panic::catch_unwind (1,852 samples, 6.86%)std::pani..std::panicking::try (1,852 samples, 6.86%)std::pani..std::panicking::try::do_call (1,852 samples, 6.86%)std::pani..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (1,852 samples, 6.86%)<core::pa..std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (1,852 samples, 6.86%)std::thre..std::sys_common::backtrace::__rust_begin_short_backtrace (1,852 samples, 6.86%)std::sys_..<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (1,852 samples, 6.86%)<alloc::b..core::ops::function::FnOnce::call_once{{vtable.shim}} (1,852 samples, 6.86%)core::ops..crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (1,852 samples, 6.86%)crossbeam..main::start_recv_threads::{{closure}}::{{closure}} (1,852 samples, 6.86%)main::sta..k2o::assemble_ng::assembler_main (1,852 samples, 6.86%)k2o::asse..crossbeam_utils::thread::scope (1,851 samples, 6.86%)crossbeam..std::panic::catch_unwind (1,851 samples, 6.86%)std::pani..std::panicking::try (1,851 samples, 6.86%)std::pani..std::panicking::try::do_call (1,851 samples, 6.86%)std::pani..<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (1,851 samples, 6.86%)<core::pa..crossbeam_utils::thread::scope::{{closure}} (1,851 samples, 6.86%)crossbeam..k2o::assemble_ng::assembler_main::{{closure}} (1,851 samples, 6.86%)k2o::asse..__GI___clone (1,877 samples, 6.95%)__GI___cl..start_thread (1,853 samples, 6.86%)start_thr..std::sys::unix::thread::Thread::new::thread_start (1,853 samples, 6.86%)std::sys:..entry_SYSCALL_64_safe_stack (3 samples, 0.01%)assembly (1,888 samples, 6.99%)assemblysyscall_return_via_sysret (3 samples, 0.01%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)cpuset_cpus_allowed (6 samples, 0.02%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)extent_arena_get (3 samples, 0.01%)atomic_load_p (3 samples, 0.01%)_rjem_je_large_dalloc (10 samples, 0.04%)large_dalloc_finish_impl (7 samples, 0.03%)_rjem_je_arena_extents_dirty_dalloc (7 samples, 0.03%)extent_record (7 samples, 0.03%)extent_try_coalesce (7 samples, 0.03%)extent_lock_from_addr (6 samples, 0.02%)extent_rtree_leaf_elm_try_lock (6 samples, 0.02%)extent_lock (6 samples, 0.02%)mutex_pool_lock (6 samples, 0.02%)malloc_mutex_lock (6 samples, 0.02%)malloc_mutex_trylock_final (6 samples, 0.02%)__GI___pthread_mutex_trylock (6 samples, 0.02%)core::ptr::drop_in_place<k2o::frame::K2ISFrame> (13 samples, 0.05%)core::ptr::drop_in_place<alloc::vec::Vec<u16,k2o::dio::PageAlignedAllocator>> (12 samples, 0.04%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u16,k2o::dio::PageAlignedAllocator>> (12 samples, 0.04%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (12 samples, 0.04%)crossbeam_utils::backoff::Backoff::snooze (13 samples, 0.05%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (12 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (12 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (12 samples, 0.04%)__perf_event_task_sched_out (3 samples, 0.01%)amd_pmu_disable_all (3 samples, 0.01%)x86_pmu_disable_all (3 samples, 0.01%)pick_next_task_fair (3 samples, 0.01%)newidle_balance (3 samples, 0.01%)futex_wait_queue_me (9 samples, 0.03%)schedule (9 samples, 0.03%)__schedule (9 samples, 0.03%)std::sys_common::thread_parker::futex::Parker::park (11 samples, 0.04%)std::sys::unix::futex::futex_wait (11 samples, 0.04%)syscall (11 samples, 0.04%)entry_SYSCALL_64_after_hwframe (11 samples, 0.04%)do_syscall_64 (11 samples, 0.04%)__x64_sys_futex (11 samples, 0.04%)do_futex (11 samples, 0.04%)futex_wait (10 samples, 0.04%)crossbeam_channel::context::Context::wait_until (25 samples, 0.09%)std::thread::park (12 samples, 0.04%)crossbeam_channel::context::Context::with (26 samples, 0.10%)std::thread::local::LocalKey<T>::try_with (26 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (26 samples, 0.10%)crossbeam_channel::context::Context::with::{{closure}} (26 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::recv::{{closure}} (26 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::start_recv (5 samples, 0.02%)core::sync::atomic::AtomicUsize::load (3 samples, 0.01%)core::sync::atomic::atomic_load (3 samples, 0.01%)__GI___sched_yield (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::recv (46 samples, 0.17%)crossbeam_channel::flavors::list::Channel<T>::recv (46 samples, 0.17%)crossbeam_utils::backoff::Backoff::snooze (15 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (10 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (10 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (10 samples, 0.04%)__perf_event_task_sched_out (4 samples, 0.01%)amd_pmu_disable_all (3 samples, 0.01%)x86_pmu_disable_all (3 samples, 0.01%)native_read_msr (3 samples, 0.01%)__sched_text_start (5 samples, 0.02%)schedule_timeout (5 samples, 0.02%)schedule (5 samples, 0.02%)__schedule (5 samples, 0.02%)__iommu_dma_map (5 samples, 0.02%)iommu_map_atomic (4 samples, 0.01%)__iommu_map (4 samples, 0.01%)amd_iommu_map (7 samples, 0.03%)dma_map_sg_attrs (10 samples, 0.04%)iommu_dma_map_sg (10 samples, 0.04%)__iommu_map_sg (10 samples, 0.04%)__iommu_map (10 samples, 0.04%)blk_finish_plug (18 samples, 0.07%)blk_mq_flush_plug_list (18 samples, 0.07%)blk_mq_sched_insert_requests (16 samples, 0.06%)blk_mq_try_issue_list_directly (16 samples, 0.06%)__blk_mq_try_issue_directly (16 samples, 0.06%)nvme_queue_rq (16 samples, 0.06%)ext4_iomap_begin (5 samples, 0.02%)ext4_map_blocks (5 samples, 0.02%)ext4_ext_map_blocks (4 samples, 0.01%)ext4_split_extent (4 samples, 0.01%)__bio_try_merge_page (7 samples, 0.03%)bio_iov_iter_get_pages (24 samples, 0.09%)iov_iter_get_pages (10 samples, 0.04%)internal_get_user_pages_fast (10 samples, 0.04%)__blk_mq_alloc_request (3 samples, 0.01%)__blk_queue_split (3 samples, 0.01%)__rq_qos_track (4 samples, 0.01%)wbt_track (4 samples, 0.01%)iommu_dma_alloc_iova (11 samples, 0.04%)alloc_iova_fast (11 samples, 0.04%)alloc_iova (10 samples, 0.04%)rb_prev (7 samples, 0.03%)amd_iommu_map (43 samples, 0.16%)asm_sysvec_call_function (3 samples, 0.01%)__iommu_dma_map (62 samples, 0.23%)iommu_map_atomic (49 samples, 0.18%)__iommu_map (49 samples, 0.18%)iommu_pgsize (6 samples, 0.02%)__iommu_map_sg (4 samples, 0.01%)__iommu_map (4 samples, 0.01%)amd_iommu_map (3 samples, 0.01%)dma_map_sg_attrs (7 samples, 0.03%)iommu_dma_map_sg (7 samples, 0.03%)iommu_dma_alloc_iova (3 samples, 0.01%)alloc_iova_fast (3 samples, 0.01%)alloc_iova (3 samples, 0.01%)blk_mq_flush_plug_list (77 samples, 0.29%)blk_mq_sched_insert_requests (77 samples, 0.29%)blk_mq_try_issue_list_directly (77 samples, 0.29%)__blk_mq_try_issue_directly (76 samples, 0.28%)nvme_queue_rq (75 samples, 0.28%)blk_mq_submit_bio (94 samples, 0.35%)blk_mq_rq_ctx_init (3 samples, 0.01%)blk_queue_split (6 samples, 0.02%)__blk_queue_split (6 samples, 0.02%)map_sector.isra.0 (3 samples, 0.01%)new_sync_write (168 samples, 0.62%)ext4_file_write_iter (168 samples, 0.62%)iomap_dio_rw (164 samples, 0.61%)__iomap_dio_rw (164 samples, 0.61%)iomap_apply (141 samples, 0.52%)iomap_dio_bio_actor (136 samples, 0.50%)iomap_dio_submit_bio (111 samples, 0.41%)submit_bio_noacct (111 samples, 0.41%)md_submit_bio (14 samples, 0.05%)md_handle_request (6 samples, 0.02%)raid0_make_request (6 samples, 0.02%)std::io::Write::write_all (176 samples, 0.65%)std::os::unix::net::datagram::UnixDatagram::send (176 samples, 0.65%)std::sys::unix::net::Socket::write (176 samples, 0.65%)std::sys::unix::fd::FileDesc::write (176 samples, 0.65%)__libc_write (176 samples, 0.65%)__libc_write (176 samples, 0.65%)entry_SYSCALL_64_after_hwframe (171 samples, 0.63%)do_syscall_64 (171 samples, 0.63%)ksys_write (171 samples, 0.63%)vfs_write (171 samples, 0.63%)ff_writer (246 samples, 0.91%)__GI___clone (246 samples, 0.91%)start_thread (246 samples, 0.91%)std::sys::unix::thread::Thread::new::thread_start (246 samples, 0.91%)<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (246 samples, 0.91%)<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (246 samples, 0.91%)core::ops::function::FnOnce::call_once{{vtable.shim}} (246 samples, 0.91%)std::thread::Builder::spawn_unchecked_::{{closure}} (246 samples, 0.91%)std::panic::catch_unwind (246 samples, 0.91%)std::panicking::try (246 samples, 0.91%)std::panicking::try::do_call (246 samples, 0.91%)<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (246 samples, 0.91%)std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} (246 samples, 0.91%)std::sys_common::backtrace::__rust_begin_short_backtrace (246 samples, 0.91%)<alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once (246 samples, 0.91%)core::ops::function::FnOnce::call_once{{vtable.shim}} (246 samples, 0.91%)crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}} (246 samples, 0.91%)main::start_recv_threads::{{closure}}::{{closure}} (246 samples, 0.91%)main::full_frame_writer_direct (239 samples, 0.89%)__mark_inode_dirty (4 samples, 0.01%)ext4_dirty_inode (4 samples, 0.01%)__ext4_mark_inode_dirty (4 samples, 0.01%)ext4_reserve_inode_write (3 samples, 0.01%)ext4_mb_find_by_goal (4 samples, 0.01%)ext4_mb_load_buddy_gfp (4 samples, 0.01%)ext4_mb_init_group (3 samples, 0.01%)ext4_get_group_desc (3 samples, 0.01%)ext4_mb_prefetch (27 samples, 0.10%)ext4_mb_regular_allocator (52 samples, 0.19%)main::preallocate (68 samples, 0.25%)nix::fcntl::fallocate (68 samples, 0.25%)fallocate64 (68 samples, 0.25%)entry_SYSCALL_64_after_hwframe (64 samples, 0.24%)do_syscall_64 (64 samples, 0.24%)__x64_sys_fallocate (64 samples, 0.24%)vfs_fallocate (64 samples, 0.24%)ext4_fallocate (64 samples, 0.24%)ext4_alloc_file_blocks.isra.0 (64 samples, 0.24%)ext4_map_blocks (60 samples, 0.22%)ext4_ext_map_blocks (60 samples, 0.22%)ext4_mb_new_blocks (59 samples, 0.22%)[unknown] (70 samples, 0.26%)main::main (69 samples, 0.26%)_raw_spin_lock_irq (25 samples, 0.09%)native_queued_spin_lock_slowpath (6 samples, 0.02%)calculate_sigpending (38 samples, 0.14%)recalc_sigpending (13 samples, 0.05%)__list_del_entry_valid (14 samples, 0.05%)schedule_tail (21 samples, 0.08%)finish_task_switch (21 samples, 0.08%)__mmdrop (21 samples, 0.08%)pgd_free (21 samples, 0.08%)_raw_spin_lock (7 samples, 0.03%)native_queued_spin_lock_slowpath (7 samples, 0.03%)ret_from_fork (65 samples, 0.24%)syscall_exit_to_user_mode (6 samples, 0.02%)exit_to_user_mode_prepare (6 samples, 0.02%)switch_fpu_return (6 samples, 0.02%)copy_kernel_to_fpregs (6 samples, 0.02%)__GI___clone (67 samples, 0.25%)main (139 samples, 0.51%)perf_5.10 (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_execve (6 samples, 0.02%)do_execveat_common (6 samples, 0.02%)bprm_execve (6 samples, 0.02%)load_elf_binary (6 samples, 0.02%)begin_new_exec (6 samples, 0.02%)perf_event_comm (6 samples, 0.02%)perf_iterate_sb (6 samples, 0.02%)_rjem_je_extent_alloc_wrapper (5 samples, 0.02%)extent_alloc_retained (5 samples, 0.02%)extent_recycle (3 samples, 0.01%)asm_exc_page_fault (4 samples, 0.01%)down_read (7 samples, 0.03%)up_read (4 samples, 0.01%)__list_add_valid (8 samples, 0.03%)__mod_lruvec_state (5 samples, 0.02%)__mod_node_page_state (3 samples, 0.01%)__pagevec_lru_add_fn (23 samples, 0.09%)mem_cgroup_update_lru_size (3 samples, 0.01%)_raw_spin_lock_irqsave (23 samples, 0.09%)native_queued_spin_lock_slowpath (17 samples, 0.06%)_raw_spin_unlock_irqrestore (5 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)lru_add_drain (59 samples, 0.22%)lru_add_drain_cpu (59 samples, 0.22%)pagevec_lru_move_fn (59 samples, 0.22%)release_pages (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (7 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (14 samples, 0.05%)__default_send_IPI_dest_field (14 samples, 0.05%)on_each_cpu_cond_mask (40 samples, 0.15%)smp_call_function_many_cond (40 samples, 0.15%)tlb_is_not_lazy (6 samples, 0.02%)flush_tlb_func_remote (5 samples, 0.02%)asm_sysvec_call_function (11 samples, 0.04%)sysvec_call_function (8 samples, 0.03%)asm_call_sysvec_on_stack (8 samples, 0.03%)__sysvec_call_function (8 samples, 0.03%)flush_smp_call_function_queue (8 samples, 0.03%)_find_next_bit.constprop.0 (3 samples, 0.01%)cpumask_next (4 samples, 0.01%)__default_send_IPI_dest_field (61 samples, 0.23%)flush_tlb_func_remote (4 samples, 0.01%)default_send_IPI_mask_sequence_phys (73 samples, 0.27%)asm_sysvec_call_function (9 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_add_batch (21 samples, 0.08%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_mm_range (337 samples, 1.25%)smp_call_function_many_cond (282 samples, 1.04%)free_unref_page (7 samples, 0.03%)free_pcppages_bulk (6 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)__list_del_entry_valid (9 samples, 0.03%)_raw_spin_lock_irqsave (18 samples, 0.07%)native_queued_spin_lock_slowpath (13 samples, 0.05%)_raw_spin_unlock_irqrestore (7 samples, 0.03%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__free_one_page (11 samples, 0.04%)__list_del_entry_valid (3 samples, 0.01%)free_pcppages_bulk (28 samples, 0.10%)_raw_spin_lock (11 samples, 0.04%)native_queued_spin_lock_slowpath (10 samples, 0.04%)free_unref_page_list (40 samples, 0.15%)asm_sysvec_call_function (3 samples, 0.01%)uncharge_batch (21 samples, 0.08%)page_counter_uncharge (19 samples, 0.07%)mem_cgroup_uncharge_list (24 samples, 0.09%)uncharge_page (3 samples, 0.01%)tlb_finish_mmu (468 samples, 1.73%)release_pages (112 samples, 0.41%)mem_cgroup_update_lru_size (3 samples, 0.01%)tlb_gather_mmu (5 samples, 0.02%)__alloc_pages_nodemask (7 samples, 0.03%)get_page_from_freelist (6 samples, 0.02%)prep_new_page (5 samples, 0.02%)kernel_init_free_pages (5 samples, 0.02%)clear_page_rep (5 samples, 0.02%)__tlb_remove_page_size (8 samples, 0.03%)__get_free_pages (8 samples, 0.03%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)__mod_memcg_lruvec_state (3 samples, 0.01%)page_remove_rmap (12 samples, 0.04%)_rjem_je_pages_purge_forced (620 samples, 2.30%)_..__GI_madvise (619 samples, 2.29%)_..entry_SYSCALL_64_after_hwframe (612 samples, 2.27%)e..do_syscall_64 (612 samples, 2.27%)d..__x64_sys_madvise (612 samples, 2.27%)_..do_madvise.part.0 (612 samples, 2.27%)d..zap_page_range (599 samples, 2.22%)z..unmap_page_range (65 samples, 0.24%)sync_mm_rss (7 samples, 0.03%)_rjem_je_extent_heap_first (8 samples, 0.03%)extents_fit_locked (9 samples, 0.03%)extents_best_fit_locked (9 samples, 0.03%)extent_recycle_extract (12 samples, 0.04%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)_rjem_je_extent_alloc (4 samples, 0.01%)extent_lock2 (5 samples, 0.02%)mutex_pool_lock2 (5 samples, 0.02%)malloc_mutex_lock (5 samples, 0.02%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_split_impl (11 samples, 0.04%)extent_recycle (647 samples, 2.40%)ex..extent_recycle_split (15 samples, 0.06%)extent_split_interior (15 samples, 0.06%)rtree_szind_slab_update (3 samples, 0.01%)rtree_leaf_elm_szind_slab_update (3 samples, 0.01%)rtree_leaf_elm_slab_write (3 samples, 0.01%)alloc::vec::from_elem (659 samples, 2.44%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (659 samples, 2.44%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (659 samples, 2.44%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (659 samples, 2.44%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (659 samples, 2.44%)<a..alloc::alloc::Global::alloc_impl (659 samples, 2.44%)al..alloc::alloc::alloc_zeroed (659 samples, 2.44%)al.._rjem_calloc (658 samples, 2.44%)_r..imalloc (658 samples, 2.44%)im..imalloc_body (658 samples, 2.44%)im..imalloc_no_sample (658 samples, 2.44%)im..iallocztm (658 samples, 2.44%)ia..arena_malloc (658 samples, 2.44%)ar..tcache_alloc_large (658 samples, 2.44%)tc.._rjem_je_large_palloc (658 samples, 2.44%)_r.._rjem_je_arena_extent_alloc_large (657 samples, 2.43%)_r..asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)down_read_trylock (51 samples, 0.19%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__count_memcg_events.part.0 (5 samples, 0.02%)__list_del_entry_valid (9 samples, 0.03%)_raw_spin_lock (23 samples, 0.09%)native_queued_spin_lock_slowpath (22 samples, 0.08%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)alloc_pages_vma (355 samples, 1.31%)__alloc_pages_nodemask (352 samples, 1.30%)get_page_from_freelist (349 samples, 1.29%)prep_new_page (249 samples, 0.92%)kernel_init_free_pages (248 samples, 0.92%)clear_page_rep (239 samples, 0.89%)asm_sysvec_call_function (25 samples, 0.09%)sysvec_call_function (10 samples, 0.04%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)llist_reverse_order (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)cgroup_throttle_swaprate (3 samples, 0.01%)kernel_init_free_pages (28 samples, 0.10%)clear_page_rep (28 samples, 0.10%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)alloc_pages_vma (29 samples, 0.11%)__alloc_pages_nodemask (29 samples, 0.11%)get_page_from_freelist (29 samples, 0.11%)prep_new_page (29 samples, 0.11%)clear_huge_page (6 samples, 0.02%)clear_subpage (6 samples, 0.02%)clear_page_rep (5 samples, 0.02%)do_huge_pmd_anonymous_page (36 samples, 0.13%)mem_cgroup_charge_statistics.constprop.0 (13 samples, 0.05%)__count_memcg_events.part.0 (12 samples, 0.04%)mem_cgroup_charge (41 samples, 0.15%)try_charge (18 samples, 0.07%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)handle_mm_fault (488 samples, 1.81%)h..page_add_new_anon_rmap (8 samples, 0.03%)__mod_memcg_lruvec_state (3 samples, 0.01%)asm_exc_page_fault (647 samples, 2.40%)as..exc_page_fault (622 samples, 2.30%)e..do_user_addr_fault (617 samples, 2.29%)d..up_read (70 samples, 0.26%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)asm_sysvec_call_function (13 samples, 0.05%)sysvec_call_function (11 samples, 0.04%)__sysvec_call_function (11 samples, 0.04%)flush_smp_call_function_queue (11 samples, 0.04%)error_entry (6 samples, 0.02%)sync_regs (5 samples, 0.02%)<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,440 samples, 5.33%)<k2o::b..k2o::decode::decode (781 samples, 2.89%)k2..crossbeam_channel::flavors::list::Channel<T>::start_send (9 samples, 0.03%)crossbeam_channel::utils::Spinlock<T>::lock (4 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (4 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (19 samples, 0.07%)crossbeam_channel::waker::Waker::try_select::{{closure}} (19 samples, 0.07%)crossbeam_channel::context::Context::unpark (17 samples, 0.06%)std::thread::Thread::unpark (17 samples, 0.06%)std::sys_common::thread_parker::futex::Parker::unpark (17 samples, 0.06%)syscall (16 samples, 0.06%)entry_SYSCALL_64_after_hwframe (16 samples, 0.06%)do_syscall_64 (16 samples, 0.06%)__x64_sys_futex (16 samples, 0.06%)do_futex (16 samples, 0.06%)futex_wake (16 samples, 0.06%)wake_up_q (8 samples, 0.03%)try_to_wake_up (7 samples, 0.03%)ttwu_queue_wakelist (3 samples, 0.01%)crossbeam_channel::channel::Sender<T>::send (40 samples, 0.15%)crossbeam_channel::flavors::list::Channel<T>::send (39 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::write (30 samples, 0.11%)crossbeam_channel::waker::SyncWaker::notify (24 samples, 0.09%)crossbeam_channel::waker::Waker::try_select (20 samples, 0.07%)k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)kfree (5 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)__free_one_page (26 samples, 0.10%)free_pcppages_bulk (69 samples, 0.26%)_raw_spin_lock (39 samples, 0.14%)native_queued_spin_lock_slowpath (37 samples, 0.14%)__consume_stateless_skb (115 samples, 0.43%)skb_release_data (110 samples, 0.41%)free_unref_page (86 samples, 0.32%)free_unref_page_commit (3 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__skb_recv_udp (4 samples, 0.01%)kmem_cache_free (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)native_flush_tlb_one_user (3 samples, 0.01%)flush_tlb_func_remote (4 samples, 0.01%)_copy_to_iter (211 samples, 0.78%)copy_user_generic_string (207 samples, 0.77%)asm_sysvec_call_function (22 samples, 0.08%)sysvec_call_function (18 samples, 0.07%)asm_call_sysvec_on_stack (18 samples, 0.07%)__sysvec_call_function (18 samples, 0.07%)flush_smp_call_function_queue (18 samples, 0.07%)llist_reverse_order (3 samples, 0.01%)__virt_addr_valid (3 samples, 0.01%)inet_recvmsg (432 samples, 1.60%)udp_recvmsg (432 samples, 1.60%)skb_copy_datagram_iter (302 samples, 1.12%)__skb_datagram_iter (302 samples, 1.12%)simple_copy_to_iter (67 samples, 0.25%)__check_object_size (67 samples, 0.25%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)move_addr_to_user (4 samples, 0.01%)sock_recvmsg (3 samples, 0.01%)security_socket_recvmsg (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (441 samples, 1.63%)do_syscall_64 (441 samples, 1.63%)__x64_sys_recvfrom (441 samples, 1.63%)__sys_recvfrom (441 samples, 1.63%)main::recv_decode_loop (1,933 samples, 7.16%)main::recv..std::net::udp::UdpSocket::recv_from (444 samples, 1.64%)std::sys_common::net::UdpSocket::recv_from (444 samples, 1.64%)std::sys::unix::net::Socket::recv_from (444 samples, 1.64%)std::sys::unix::net::Socket::recv_from_with_flags (444 samples, 1.64%)__libc_recvfrom (444 samples, 1.64%)[unknown] (1,940 samples, 7.18%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (7 samples, 0.03%)__libc_recvfrom (7 samples, 0.03%)entry_SYSCALL_64 (5 samples, 0.02%)recv-decode-0 (1,943 samples, 7.20%)recv-decod.._rjem_je_extent_alloc_wrapper (5 samples, 0.02%)extent_alloc_retained (5 samples, 0.02%)extent_recycle (5 samples, 0.02%)extent_recycle_split (5 samples, 0.02%)extent_split_interior (5 samples, 0.02%)extent_split_impl (5 samples, 0.02%)asm_exc_page_fault (8 samples, 0.03%)down_read (10 samples, 0.04%)__list_add_valid (3 samples, 0.01%)__pagevec_lru_add_fn (20 samples, 0.07%)_raw_spin_lock_irqsave (24 samples, 0.09%)native_queued_spin_lock_slowpath (18 samples, 0.07%)_raw_spin_unlock_irqrestore (4 samples, 0.01%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)lru_add_drain (53 samples, 0.20%)lru_add_drain_cpu (53 samples, 0.20%)pagevec_lru_move_fn (53 samples, 0.20%)native_flush_tlb_local (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (11 samples, 0.04%)__default_send_IPI_dest_field (10 samples, 0.04%)default_send_IPI_mask_sequence_phys (12 samples, 0.04%)on_each_cpu_cond_mask (33 samples, 0.12%)smp_call_function_many_cond (33 samples, 0.12%)tlb_is_not_lazy (4 samples, 0.01%)asm_sysvec_call_function (10 samples, 0.04%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)cpumask_next (4 samples, 0.01%)_find_next_bit.constprop.0 (3 samples, 0.01%)__default_send_IPI_dest_field (71 samples, 0.26%)default_send_IPI_mask_sequence_phys (75 samples, 0.28%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_mm_range (332 samples, 1.23%)smp_call_function_many_cond (283 samples, 1.05%)llist_add_batch (22 samples, 0.08%)__free_one_page (4 samples, 0.01%)free_pcppages_bulk (8 samples, 0.03%)free_unref_page (9 samples, 0.03%)__list_del_entry_valid (3 samples, 0.01%)__mod_zone_page_state (5 samples, 0.02%)_raw_spin_lock_irqsave (24 samples, 0.09%)native_queued_spin_lock_slowpath (18 samples, 0.07%)_raw_spin_unlock_irqrestore (6 samples, 0.02%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (4 samples, 0.01%)__free_one_page (14 samples, 0.05%)__list_del_entry_valid (5 samples, 0.02%)free_pcppages_bulk (36 samples, 0.13%)_raw_spin_lock (12 samples, 0.04%)native_queued_spin_lock_slowpath (12 samples, 0.04%)free_unref_page_list (42 samples, 0.16%)uncharge_batch (17 samples, 0.06%)page_counter_uncharge (15 samples, 0.06%)mem_cgroup_uncharge_list (20 samples, 0.07%)uncharge_page (3 samples, 0.01%)tlb_finish_mmu (473 samples, 1.75%)release_pages (118 samples, 0.44%)mem_cgroup_update_lru_size (6 samples, 0.02%)tlb_gather_mmu (7 samples, 0.03%)__alloc_pages_nodemask (14 samples, 0.05%)get_page_from_freelist (14 samples, 0.05%)prep_new_page (9 samples, 0.03%)kernel_init_free_pages (9 samples, 0.03%)clear_page_rep (9 samples, 0.03%)__tlb_remove_page_size (16 samples, 0.06%)__get_free_pages (16 samples, 0.06%)__mod_lruvec_state (3 samples, 0.01%)page_remove_rmap (16 samples, 0.06%)sync_mm_rss (4 samples, 0.01%)__x64_sys_madvise (629 samples, 2.33%)_..do_madvise.part.0 (629 samples, 2.33%)d..zap_page_range (616 samples, 2.28%)z..unmap_page_range (82 samples, 0.30%)_rjem_je_pages_purge_forced (643 samples, 2.38%)_r..__GI_madvise (643 samples, 2.38%)__..entry_SYSCALL_64_after_hwframe (632 samples, 2.34%)e..do_syscall_64 (632 samples, 2.34%)d.._rjem_je_extent_heap_first (4 samples, 0.01%)extents_fit_locked (5 samples, 0.02%)extents_best_fit_locked (5 samples, 0.02%)extent_recycle_extract (11 samples, 0.04%)malloc_mutex_lock (6 samples, 0.02%)malloc_mutex_trylock_final (6 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)_rjem_je_extent_alloc (3 samples, 0.01%)_rjem_je_extent_avail_first (3 samples, 0.01%)extent_split_impl (8 samples, 0.03%)extent_recycle_split (15 samples, 0.06%)extent_split_interior (13 samples, 0.05%)rtree_szind_slab_update (5 samples, 0.02%)rtree_leaf_elm_szind_slab_update (5 samples, 0.02%)rtree_leaf_elm_slab_write (5 samples, 0.02%)_rjem_je_arena_extent_alloc_large (682 samples, 2.53%)_r..extent_recycle (671 samples, 2.49%)ex.._rjem_je_arena_decay (4 samples, 0.01%)arena_decay_dirty (4 samples, 0.01%)arena_decay_impl (4 samples, 0.01%)arena_maybe_decay (4 samples, 0.01%)arena_maybe_decay (4 samples, 0.01%)arena_decay_try_purge (4 samples, 0.01%)arena_decay_try_purge (4 samples, 0.01%)arena_decay_to_limit (4 samples, 0.01%)arena_decay_stashed (4 samples, 0.01%)_rjem_je_extent_purge_lazy_wrapper (4 samples, 0.01%)extent_purge_lazy_impl (4 samples, 0.01%)_rjem_je_pages_purge_lazy (4 samples, 0.01%)_rjem_je_pages_purge_lazy (4 samples, 0.01%)__GI_madvise (4 samples, 0.01%)entry_SYSCALL_64_after_hwframe (4 samples, 0.01%)do_syscall_64 (4 samples, 0.01%)__x64_sys_madvise (4 samples, 0.01%)do_madvise.part.0 (4 samples, 0.01%)madvise_free_single_vma (4 samples, 0.01%)walk_page_range (4 samples, 0.01%)__walk_page_range (4 samples, 0.01%)madvise_free_pte_range (4 samples, 0.01%)split_huge_page_to_list (4 samples, 0.01%)try_to_unmap (3 samples, 0.01%)rmap_walk_anon (3 samples, 0.01%)try_to_unmap_one (3 samples, 0.01%)ptep_clear_flush (3 samples, 0.01%)flush_tlb_mm_range (3 samples, 0.01%)on_each_cpu_cond_mask (3 samples, 0.01%)smp_call_function_many_cond (3 samples, 0.01%)alloc::vec::from_elem (690 samples, 2.56%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (690 samples, 2.56%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (690 samples, 2.56%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (690 samples, 2.56%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (690 samples, 2.56%)<a..alloc::alloc::Global::alloc_impl (690 samples, 2.56%)al..alloc::alloc::alloc_zeroed (690 samples, 2.56%)al.._rjem_calloc (690 samples, 2.56%)_r..imalloc (688 samples, 2.55%)im..imalloc_body (688 samples, 2.55%)im..imalloc_no_sample (688 samples, 2.55%)im..iallocztm (688 samples, 2.55%)ia..arena_malloc (688 samples, 2.55%)ar..tcache_alloc_large (687 samples, 2.54%)tc.._rjem_je_large_palloc (687 samples, 2.54%)_r..arena_decay_tick (5 samples, 0.02%)arena_decay_ticks (5 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)down_read_trylock (56 samples, 0.21%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__list_del_entry_valid (13 samples, 0.05%)_raw_spin_lock (10 samples, 0.04%)native_queued_spin_lock_slowpath (10 samples, 0.04%)asm_sysvec_call_function (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_smp_call_function_queue (10 samples, 0.04%)llist_reverse_order (5 samples, 0.02%)alloc_pages_vma (326 samples, 1.21%)__alloc_pages_nodemask (322 samples, 1.19%)get_page_from_freelist (306 samples, 1.13%)prep_new_page (237 samples, 0.88%)kernel_init_free_pages (227 samples, 0.84%)clear_page_rep (220 samples, 0.81%)asm_sysvec_call_function (20 samples, 0.07%)sysvec_call_function (13 samples, 0.05%)asm_call_sysvec_on_stack (11 samples, 0.04%)__sysvec_call_function (11 samples, 0.04%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (6 samples, 0.02%)asm_call_sysvec_on_stack (6 samples, 0.02%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)cgroup_throttle_swaprate (4 samples, 0.01%)alloc_pages_vma (35 samples, 0.13%)__alloc_pages_nodemask (35 samples, 0.13%)get_page_from_freelist (35 samples, 0.13%)prep_new_page (34 samples, 0.13%)kernel_init_free_pages (34 samples, 0.13%)clear_page_rep (34 samples, 0.13%)clear_huge_page (5 samples, 0.02%)clear_subpage (5 samples, 0.02%)clear_page_rep (5 samples, 0.02%)do_huge_pmd_anonymous_page (41 samples, 0.15%)mem_cgroup_charge_statistics.constprop.0 (9 samples, 0.03%)__count_memcg_events.part.0 (5 samples, 0.02%)mem_cgroup_charge (48 samples, 0.18%)try_charge (30 samples, 0.11%)page_counter_try_charge (10 samples, 0.04%)handle_mm_fault (478 samples, 1.77%)h..page_add_new_anon_rmap (8 samples, 0.03%)asm_exc_page_fault (612 samples, 2.27%)a..exc_page_fault (584 samples, 2.16%)e..do_user_addr_fault (582 samples, 2.16%)d..up_read (39 samples, 0.14%)asm_sysvec_call_function (12 samples, 0.04%)sysvec_call_function (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)llist_reverse_order (4 samples, 0.01%)error_entry (9 samples, 0.03%)sync_regs (8 samples, 0.03%)k2o::decode::decode (756 samples, 2.80%)k2..<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,453 samples, 5.38%)<k2o::b..std::time::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::Instant::now (5 samples, 0.02%)std::sys::unix::time::inner::now (5 samples, 0.02%)__GI___clock_gettime (4 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::try_recv (5 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::try_recv (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (15 samples, 0.06%)core::sync::atomic::AtomicPtr<T>::load (10 samples, 0.04%)core::sync::atomic::atomic_load (10 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::write (4 samples, 0.01%)core::ptr::write (4 samples, 0.01%)crossbeam_channel::utils::Spinlock<T>::lock (6 samples, 0.02%)crossbeam_utils::backoff::Backoff::snooze (6 samples, 0.02%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.02%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.02%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (5 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (8 samples, 0.03%)crossbeam_channel::waker::Waker::try_select::{{closure}} (8 samples, 0.03%)crossbeam_channel::context::Context::unpark (7 samples, 0.03%)std::thread::Thread::unpark (7 samples, 0.03%)std::sys_common::thread_parker::futex::Parker::unpark (7 samples, 0.03%)syscall (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_futex (7 samples, 0.03%)do_futex (7 samples, 0.03%)futex_wake (7 samples, 0.03%)crossbeam_channel::channel::Sender<T>::send (40 samples, 0.15%)crossbeam_channel::flavors::list::Channel<T>::send (39 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::write (24 samples, 0.09%)crossbeam_channel::waker::SyncWaker::notify (15 samples, 0.06%)crossbeam_channel::waker::Waker::try_select (9 samples, 0.03%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)__GI___sched_setaffinity_new (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)cpuset_cpus_allowed (6 samples, 0.02%)_raw_spin_lock_irqsave (6 samples, 0.02%)kfree (10 samples, 0.04%)asm_sysvec_call_function (3 samples, 0.01%)__free_one_page (23 samples, 0.09%)__list_del_entry_valid (6 samples, 0.02%)__list_del_entry_valid (5 samples, 0.02%)free_pcppages_bulk (63 samples, 0.23%)_raw_spin_lock (26 samples, 0.10%)native_queued_spin_lock_slowpath (26 samples, 0.10%)__consume_stateless_skb (105 samples, 0.39%)skb_release_data (95 samples, 0.35%)free_unref_page (76 samples, 0.28%)free_unref_page_commit (4 samples, 0.01%)__list_add_valid (3 samples, 0.01%)kmem_cache_free (4 samples, 0.01%)__slab_free (3 samples, 0.01%)_copy_to_iter (211 samples, 0.78%)copy_user_generic_string (208 samples, 0.77%)asm_sysvec_call_function (13 samples, 0.05%)sysvec_call_function (9 samples, 0.03%)asm_call_sysvec_on_stack (9 samples, 0.03%)__sysvec_call_function (9 samples, 0.03%)flush_smp_call_function_queue (9 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)__virt_addr_valid (10 samples, 0.04%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)inet_recvmsg (441 samples, 1.63%)udp_recvmsg (441 samples, 1.63%)skb_copy_datagram_iter (325 samples, 1.20%)__skb_datagram_iter (325 samples, 1.20%)simple_copy_to_iter (79 samples, 0.29%)__check_object_size (79 samples, 0.29%)do_syscall_64 (446 samples, 1.65%)__x64_sys_recvfrom (446 samples, 1.65%)__sys_recvfrom (446 samples, 1.65%)move_addr_to_user (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (447 samples, 1.66%)[unknown] (1,957 samples, 7.25%)[unknown]main::recv_decode_loop (1,957 samples, 7.25%)main::recv..std::net::udp::UdpSocket::recv_from (451 samples, 1.67%)std::sys_common::net::UdpSocket::recv_from (451 samples, 1.67%)std::sys::unix::net::Socket::recv_from (451 samples, 1.67%)std::sys::unix::net::Socket::recv_from_with_flags (451 samples, 1.67%)__libc_recvfrom (451 samples, 1.67%)recv-decode-1 (1,963 samples, 7.27%)recv-decod.._rjem_je_extent_alloc (4 samples, 0.01%)_rjem_je_extent_alloc (4 samples, 0.01%)_rjem_je_base_alloc_extent (4 samples, 0.01%)base_alloc_impl (4 samples, 0.01%)extent_recycle (7 samples, 0.03%)extent_recycle_split (7 samples, 0.03%)extent_split_interior (7 samples, 0.03%)extent_split_impl (6 samples, 0.02%)_rjem_je_extent_alloc_wrapper (8 samples, 0.03%)extent_alloc_retained (8 samples, 0.03%)asm_exc_page_fault (6 samples, 0.02%)down_read (3 samples, 0.01%)up_read (4 samples, 0.01%)__list_add_valid (5 samples, 0.02%)__mod_memcg_lruvec_state (4 samples, 0.01%)__pagevec_lru_add_fn (37 samples, 0.14%)page_mapping (4 samples, 0.01%)_raw_spin_lock_irqsave (16 samples, 0.06%)native_queued_spin_lock_slowpath (9 samples, 0.03%)_raw_spin_unlock_irqrestore (5 samples, 0.02%)asm_sysvec_call_function (4 samples, 0.01%)lru_add_drain (64 samples, 0.24%)lru_add_drain_cpu (64 samples, 0.24%)pagevec_lru_move_fn (63 samples, 0.23%)release_pages (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (6 samples, 0.02%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)__default_send_IPI_dest_field (15 samples, 0.06%)default_send_IPI_mask_sequence_phys (17 samples, 0.06%)on_each_cpu_cond_mask (58 samples, 0.21%)smp_call_function_many_cond (57 samples, 0.21%)tlb_is_not_lazy (10 samples, 0.04%)flush_tlb_func_remote (5 samples, 0.02%)asm_sysvec_call_function (14 samples, 0.05%)sysvec_call_function (13 samples, 0.05%)asm_call_sysvec_on_stack (13 samples, 0.05%)__sysvec_call_function (13 samples, 0.05%)flush_smp_call_function_queue (13 samples, 0.05%)llist_reverse_order (4 samples, 0.01%)__default_send_IPI_dest_field (55 samples, 0.20%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (67 samples, 0.25%)llist_add_batch (15 samples, 0.06%)flush_tlb_mm_range (317 samples, 1.17%)smp_call_function_many_cond (247 samples, 0.91%)free_unref_page (5 samples, 0.02%)free_pcppages_bulk (4 samples, 0.01%)__list_del_entry_valid (4 samples, 0.01%)_raw_spin_lock_irqsave (18 samples, 0.07%)native_queued_spin_lock_slowpath (12 samples, 0.04%)_raw_spin_unlock_irqrestore (4 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)__free_one_page (12 samples, 0.04%)__list_del_entry_valid (4 samples, 0.01%)free_pcppages_bulk (31 samples, 0.11%)_raw_spin_lock (12 samples, 0.04%)native_queued_spin_lock_slowpath (11 samples, 0.04%)free_unref_page_list (40 samples, 0.15%)uncharge_batch (19 samples, 0.07%)page_counter_uncharge (18 samples, 0.07%)mem_cgroup_uncharge_list (23 samples, 0.09%)uncharge_page (3 samples, 0.01%)tlb_finish_mmu (438 samples, 1.62%)release_pages (104 samples, 0.39%)tlb_gather_mmu (6 samples, 0.02%)__alloc_pages_nodemask (22 samples, 0.08%)get_page_from_freelist (21 samples, 0.08%)prep_new_page (14 samples, 0.05%)kernel_init_free_pages (14 samples, 0.05%)clear_page_rep (14 samples, 0.05%)__tlb_remove_page_size (25 samples, 0.09%)__get_free_pages (25 samples, 0.09%)alloc_pages_current (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)__mod_lruvec_state (4 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)page_remove_rmap (13 samples, 0.05%)do_syscall_64 (585 samples, 2.17%)d..__x64_sys_madvise (585 samples, 2.17%)_..do_madvise.part.0 (585 samples, 2.17%)d..zap_page_range (578 samples, 2.14%)z..unmap_page_range (69 samples, 0.26%)sync_mm_rss (9 samples, 0.03%)_rjem_je_pages_purge_forced (593 samples, 2.20%)_..__GI_madvise (593 samples, 2.20%)_..entry_SYSCALL_64_after_hwframe (587 samples, 2.17%)e..extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)_rjem_je_extent_heap_first (3 samples, 0.01%)extents_fit_locked (4 samples, 0.01%)extents_best_fit_locked (4 samples, 0.01%)malloc_mutex_lock (8 samples, 0.03%)malloc_mutex_trylock_final (8 samples, 0.03%)__GI___pthread_mutex_trylock (8 samples, 0.03%)extent_recycle_extract (16 samples, 0.06%)_rjem_je_extent_avail_first (4 samples, 0.01%)_rjem_je_extent_alloc (6 samples, 0.02%)extent_lock2 (8 samples, 0.03%)mutex_pool_lock2 (8 samples, 0.03%)malloc_mutex_lock (8 samples, 0.03%)malloc_mutex_trylock_final (8 samples, 0.03%)__GI___pthread_mutex_trylock (7 samples, 0.03%)extent_split_impl (16 samples, 0.06%)extent_recycle (628 samples, 2.33%)e..extent_recycle_split (18 samples, 0.07%)extent_split_interior (18 samples, 0.07%)_rjem_je_large_palloc (639 samples, 2.37%)_r.._rjem_je_arena_extent_alloc_large (639 samples, 2.37%)_r..alloc::vec::from_elem (644 samples, 2.39%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (644 samples, 2.39%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (643 samples, 2.38%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (643 samples, 2.38%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (643 samples, 2.38%)<a..alloc::alloc::Global::alloc_impl (643 samples, 2.38%)al..alloc::alloc::alloc_zeroed (643 samples, 2.38%)al.._rjem_calloc (643 samples, 2.38%)_r..imalloc (642 samples, 2.38%)im..imalloc_body (642 samples, 2.38%)im..imalloc_no_sample (642 samples, 2.38%)im..iallocztm (642 samples, 2.38%)ia..arena_malloc (642 samples, 2.38%)ar..tcache_alloc_large (640 samples, 2.37%)tc..asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)down_read_trylock (60 samples, 0.22%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)__count_memcg_events.part.0 (5 samples, 0.02%)__list_del_entry_valid (11 samples, 0.04%)_raw_spin_lock (11 samples, 0.04%)native_queued_spin_lock_slowpath (11 samples, 0.04%)flush_tlb_func_remote (6 samples, 0.02%)kernel_init_free_pages (227 samples, 0.84%)clear_page_rep (220 samples, 0.81%)asm_sysvec_call_function (20 samples, 0.07%)sysvec_call_function (13 samples, 0.05%)asm_call_sysvec_on_stack (13 samples, 0.05%)__sysvec_call_function (13 samples, 0.05%)flush_smp_call_function_queue (13 samples, 0.05%)llist_reverse_order (3 samples, 0.01%)alloc_pages_vma (314 samples, 1.16%)__alloc_pages_nodemask (307 samples, 1.14%)get_page_from_freelist (303 samples, 1.12%)prep_new_page (234 samples, 0.87%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)cgroup_throttle_swaprate (4 samples, 0.01%)kernel_init_free_pages (35 samples, 0.13%)clear_page_rep (35 samples, 0.13%)alloc_pages_vma (37 samples, 0.14%)__alloc_pages_nodemask (37 samples, 0.14%)get_page_from_freelist (37 samples, 0.14%)prep_new_page (36 samples, 0.13%)clear_huge_page (9 samples, 0.03%)clear_subpage (9 samples, 0.03%)clear_page_rep (8 samples, 0.03%)do_huge_pmd_anonymous_page (48 samples, 0.18%)asm_sysvec_call_function (3 samples, 0.01%)mem_cgroup_charge_statistics.constprop.0 (10 samples, 0.04%)__count_memcg_events.part.0 (6 samples, 0.02%)mem_cgroup_charge (36 samples, 0.13%)try_charge (16 samples, 0.06%)page_counter_try_charge (8 samples, 0.03%)handle_mm_fault (463 samples, 1.71%)page_add_new_anon_rmap (9 samples, 0.03%)flush_smp_call_function_queue (4 samples, 0.01%)asm_exc_page_fault (617 samples, 2.29%)a..exc_page_fault (588 samples, 2.18%)e..do_user_addr_fault (587 samples, 2.17%)d..up_read (52 samples, 0.19%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (6 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)flush_tlb_func_remote (4 samples, 0.01%)k2o::decode::decode (748 samples, 2.77%)k2..error_entry (9 samples, 0.03%)sync_regs (8 samples, 0.03%)__vdso_clock_gettime (4 samples, 0.01%)<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,400 samples, 5.18%)<k2o::..std::time::Instant::now (8 samples, 0.03%)std::sys::unix::time::inner::Instant::now (8 samples, 0.03%)std::sys::unix::time::inner::now (8 samples, 0.03%)__GI___clock_gettime (8 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::try_recv (6 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::try_recv (5 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::start_recv (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (13 samples, 0.05%)core::sync::atomic::AtomicPtr<T>::load (10 samples, 0.04%)core::sync::atomic::atomic_load (10 samples, 0.04%)core::sync::atomic::AtomicBool::swap (3 samples, 0.01%)core::sync::atomic::atomic_swap (3 samples, 0.01%)crossbeam_channel::utils::Spinlock<T>::lock (10 samples, 0.04%)crossbeam_utils::backoff::Backoff::snooze (7 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.02%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.02%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (5 samples, 0.02%)crossbeam_channel::channel::Sender<T>::send (43 samples, 0.16%)crossbeam_channel::flavors::list::Channel<T>::send (43 samples, 0.16%)crossbeam_channel::flavors::list::Channel<T>::write (30 samples, 0.11%)crossbeam_channel::waker::SyncWaker::notify (25 samples, 0.09%)crossbeam_channel::waker::Waker::try_select (13 samples, 0.05%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (13 samples, 0.05%)crossbeam_channel::waker::Waker::try_select::{{closure}} (13 samples, 0.05%)crossbeam_channel::context::Context::unpark (8 samples, 0.03%)std::thread::Thread::unpark (8 samples, 0.03%)std::sys_common::thread_parker::futex::Parker::unpark (8 samples, 0.03%)syscall (8 samples, 0.03%)entry_SYSCALL_64_after_hwframe (8 samples, 0.03%)do_syscall_64 (8 samples, 0.03%)__x64_sys_futex (8 samples, 0.03%)do_futex (8 samples, 0.03%)futex_wake (8 samples, 0.03%)wake_up_q (6 samples, 0.02%)try_to_wake_up (6 samples, 0.02%)ttwu_queue_wakelist (5 samples, 0.02%)k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)__set_cpus_allowed_ptr (6 samples, 0.02%)stop_one_cpu (6 samples, 0.02%)_cond_resched (6 samples, 0.02%)__schedule (6 samples, 0.02%)finish_task_switch (6 samples, 0.02%)__mmdrop (6 samples, 0.02%)__free_pages_ok (6 samples, 0.02%)kfree (10 samples, 0.04%)put_cpu_partial (3 samples, 0.01%)unfreeze_partials (3 samples, 0.01%)asm_sysvec_call_function (9 samples, 0.03%)sysvec_call_function (8 samples, 0.03%)asm_call_sysvec_on_stack (8 samples, 0.03%)__sysvec_call_function (8 samples, 0.03%)flush_smp_call_function_queue (8 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)__list_add_valid (7 samples, 0.03%)__list_del_entry_valid (3 samples, 0.01%)__free_one_page (39 samples, 0.14%)__list_del_entry_valid (6 samples, 0.02%)__consume_stateless_skb (146 samples, 0.54%)skb_release_data (136 samples, 0.50%)free_unref_page (105 samples, 0.39%)free_pcppages_bulk (86 samples, 0.32%)_raw_spin_lock (34 samples, 0.13%)native_queued_spin_lock_slowpath (33 samples, 0.12%)__skb_recv_udp (4 samples, 0.01%)__slab_free (7 samples, 0.03%)kmem_cache_free (13 samples, 0.05%)release_sock (3 samples, 0.01%)flush_tlb_func_remote (8 samples, 0.03%)_copy_to_iter (198 samples, 0.73%)copy_user_generic_string (196 samples, 0.73%)asm_sysvec_call_function (19 samples, 0.07%)sysvec_call_function (14 samples, 0.05%)asm_call_sysvec_on_stack (14 samples, 0.05%)__sysvec_call_function (14 samples, 0.05%)flush_smp_call_function_queue (14 samples, 0.05%)llist_reverse_order (4 samples, 0.01%)__virt_addr_valid (5 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)inet_recvmsg (468 samples, 1.73%)udp_recvmsg (468 samples, 1.73%)skb_copy_datagram_iter (293 samples, 1.09%)__skb_datagram_iter (292 samples, 1.08%)simple_copy_to_iter (73 samples, 0.27%)__check_object_size (71 samples, 0.26%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)__x64_sys_recvfrom (474 samples, 1.76%)__sys_recvfrom (474 samples, 1.76%)do_syscall_64 (475 samples, 1.76%)entry_SYSCALL_64_after_hwframe (477 samples, 1.77%)main::recv_decode_loop (1,941 samples, 7.19%)main::recv..std::net::udp::UdpSocket::recv_from (485 samples, 1.80%)s..std::sys_common::net::UdpSocket::recv_from (484 samples, 1.79%)s..std::sys::unix::net::Socket::recv_from (484 samples, 1.79%)s..std::sys::unix::net::Socket::recv_from_with_flags (484 samples, 1.79%)s..__libc_recvfrom (484 samples, 1.79%)_..[unknown] (1,945 samples, 7.20%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (4 samples, 0.01%)__libc_recvfrom (4 samples, 0.01%)recv-decode-2 (1,948 samples, 7.21%)recv-decod.._rjem_je_extent_alloc (4 samples, 0.01%)_rjem_je_extent_alloc (4 samples, 0.01%)_rjem_je_base_alloc_extent (4 samples, 0.01%)extent_esn_set (3 samples, 0.01%)_rjem_je_extent_alloc_wrapper (7 samples, 0.03%)extent_alloc_retained (7 samples, 0.03%)extent_recycle (7 samples, 0.03%)extent_recycle_split (7 samples, 0.03%)extent_split_interior (6 samples, 0.02%)extent_split_impl (6 samples, 0.02%)down_read (4 samples, 0.01%)up_read (4 samples, 0.01%)__list_add_valid (5 samples, 0.02%)__mod_memcg_lruvec_state (6 samples, 0.02%)__mod_memcg_state.part.0 (6 samples, 0.02%)mem_cgroup_update_lru_size (3 samples, 0.01%)__pagevec_lru_add_fn (30 samples, 0.11%)page_mapping (3 samples, 0.01%)_raw_spin_lock_irqsave (14 samples, 0.05%)native_queued_spin_lock_slowpath (8 samples, 0.03%)_raw_spin_unlock_irqrestore (5 samples, 0.02%)asm_sysvec_call_function (3 samples, 0.01%)lru_add_drain (57 samples, 0.21%)lru_add_drain_cpu (57 samples, 0.21%)pagevec_lru_move_fn (57 samples, 0.21%)release_pages (4 samples, 0.01%)cpumask_any_but (3 samples, 0.01%)_find_next_bit.constprop.0 (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)__default_send_IPI_dest_field (14 samples, 0.05%)default_send_IPI_mask_sequence_phys (16 samples, 0.06%)smp_call_function_many_cond (36 samples, 0.13%)tlb_is_not_lazy (6 samples, 0.02%)on_each_cpu_cond_mask (37 samples, 0.14%)asm_sysvec_call_function (16 samples, 0.06%)sysvec_call_function (10 samples, 0.04%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)llist_reverse_order (4 samples, 0.01%)__default_send_IPI_dest_field (73 samples, 0.27%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)native_flush_tlb_local (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (86 samples, 0.32%)asm_sysvec_call_function (13 samples, 0.05%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_add_batch (30 samples, 0.11%)flush_tlb_mm_range (364 samples, 1.35%)smp_call_function_many_cond (318 samples, 1.18%)free_unref_page (6 samples, 0.02%)free_pcppages_bulk (5 samples, 0.02%)__list_del_entry_valid (5 samples, 0.02%)_raw_spin_lock_irqsave (17 samples, 0.06%)native_queued_spin_lock_slowpath (15 samples, 0.06%)__free_one_page (16 samples, 0.06%)__list_add_valid (5 samples, 0.02%)__list_del_entry_valid (5 samples, 0.02%)free_pcppages_bulk (40 samples, 0.15%)_raw_spin_lock (15 samples, 0.06%)native_queued_spin_lock_slowpath (15 samples, 0.06%)free_unref_page_list (45 samples, 0.17%)uncharge_batch (35 samples, 0.13%)page_counter_uncharge (35 samples, 0.13%)mem_cgroup_uncharge_list (36 samples, 0.13%)tlb_finish_mmu (496 samples, 1.84%)t..release_pages (117 samples, 0.43%)mem_cgroup_update_lru_size (5 samples, 0.02%)tlb_gather_mmu (5 samples, 0.02%)__alloc_pages_nodemask (12 samples, 0.04%)get_page_from_freelist (12 samples, 0.04%)prep_new_page (7 samples, 0.03%)kernel_init_free_pages (7 samples, 0.03%)clear_page_rep (7 samples, 0.03%)__tlb_remove_page_size (14 samples, 0.05%)__get_free_pages (13 samples, 0.05%)_raw_spin_lock (5 samples, 0.02%)asm_sysvec_call_function (3 samples, 0.01%)__mod_memcg_lruvec_state (3 samples, 0.01%)page_remove_rmap (13 samples, 0.05%)sync_mm_rss (4 samples, 0.01%)__x64_sys_madvise (639 samples, 2.37%)__..do_madvise.part.0 (639 samples, 2.37%)do..zap_page_range (630 samples, 2.33%)z..unmap_page_range (70 samples, 0.26%)_rjem_je_pages_purge_forced (647 samples, 2.40%)_r..__GI_madvise (644 samples, 2.39%)__..entry_SYSCALL_64_after_hwframe (640 samples, 2.37%)en..do_syscall_64 (640 samples, 2.37%)do.._rjem_je_extent_heap_first (4 samples, 0.01%)extents_fit_locked (6 samples, 0.02%)extents_best_fit_locked (6 samples, 0.02%)extent_recycle_extract (17 samples, 0.06%)malloc_mutex_lock (9 samples, 0.03%)malloc_mutex_trylock_final (9 samples, 0.03%)__GI___pthread_mutex_trylock (9 samples, 0.03%)_rjem_je_extent_alloc (4 samples, 0.01%)_rjem_je_extent_avail_first (4 samples, 0.01%)extent_lock2 (7 samples, 0.03%)mutex_pool_lock2 (7 samples, 0.03%)malloc_mutex_lock (7 samples, 0.03%)malloc_mutex_trylock_final (7 samples, 0.03%)__GI___pthread_mutex_trylock (7 samples, 0.03%)extent_split_impl (13 samples, 0.05%)_rjem_je_arena_extent_alloc_large (693 samples, 2.57%)_r..extent_recycle (684 samples, 2.53%)ex..extent_recycle_split (18 samples, 0.07%)extent_split_interior (16 samples, 0.06%)alloc::vec::from_elem (701 samples, 2.60%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (701 samples, 2.60%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (699 samples, 2.59%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (699 samples, 2.59%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (699 samples, 2.59%)<a..alloc::alloc::Global::alloc_impl (699 samples, 2.59%)al..alloc::alloc::alloc_zeroed (699 samples, 2.59%)al.._rjem_calloc (698 samples, 2.59%)_r..imalloc (695 samples, 2.57%)im..imalloc_body (695 samples, 2.57%)im..imalloc_no_sample (695 samples, 2.57%)im..iallocztm (695 samples, 2.57%)ia..arena_malloc (695 samples, 2.57%)ar..tcache_alloc_large (694 samples, 2.57%)tc.._rjem_je_large_palloc (694 samples, 2.57%)_r..flush_smp_call_function_queue (4 samples, 0.01%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)down_read_trylock (57 samples, 0.21%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)__list_del_entry_valid (17 samples, 0.06%)_raw_spin_lock (17 samples, 0.06%)native_queued_spin_lock_slowpath (16 samples, 0.06%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)__alloc_pages_nodemask (331 samples, 1.23%)get_page_from_freelist (321 samples, 1.19%)prep_new_page (229 samples, 0.85%)kernel_init_free_pages (223 samples, 0.83%)clear_page_rep (214 samples, 0.79%)asm_sysvec_call_function (16 samples, 0.06%)sysvec_call_function (10 samples, 0.04%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)alloc_pages_vma (337 samples, 1.25%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)cgroup_throttle_swaprate (3 samples, 0.01%)_raw_spin_lock_irqsave (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)alloc_pages_vma (35 samples, 0.13%)__alloc_pages_nodemask (35 samples, 0.13%)get_page_from_freelist (35 samples, 0.13%)prep_new_page (31 samples, 0.11%)kernel_init_free_pages (31 samples, 0.11%)clear_page_rep (31 samples, 0.11%)asm_sysvec_call_function (4 samples, 0.01%)do_huge_pmd_anonymous_page (44 samples, 0.16%)clear_huge_page (9 samples, 0.03%)clear_subpage (9 samples, 0.03%)clear_page_rep (9 samples, 0.03%)lru_cache_add (3 samples, 0.01%)mem_cgroup_charge_statistics.constprop.0 (6 samples, 0.02%)__count_memcg_events.part.0 (6 samples, 0.02%)mem_cgroup_charge (40 samples, 0.15%)try_charge (20 samples, 0.07%)page_counter_try_charge (6 samples, 0.02%)handle_mm_fault (469 samples, 1.74%)page_add_new_anon_rmap (6 samples, 0.02%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)exc_page_fault (589 samples, 2.18%)e..do_user_addr_fault (587 samples, 2.17%)d..up_read (51 samples, 0.19%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)asm_exc_page_fault (612 samples, 2.27%)a..asm_sysvec_call_function (9 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.02%)llist_reverse_order (3 samples, 0.01%)error_entry (10 samples, 0.04%)sync_regs (7 samples, 0.03%)k2o::decode::decode (728 samples, 2.70%)k2..<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,434 samples, 5.31%)<k2o::b..std::time::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::now (4 samples, 0.01%)__GI___clock_gettime (3 samples, 0.01%)__vdso_clock_gettime (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::try_recv (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::try_recv (4 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (4 samples, 0.01%)core::sync::atomic::AtomicPtr<T>::load (3 samples, 0.01%)core::sync::atomic::atomic_load (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (20 samples, 0.07%)core::sync::atomic::AtomicPtr<T>::load (11 samples, 0.04%)core::sync::atomic::atomic_load (11 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::write (3 samples, 0.01%)core::ptr::write (3 samples, 0.01%)crossbeam_channel::utils::Spinlock<T>::lock (4 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (4 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (3 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (16 samples, 0.06%)crossbeam_channel::waker::Waker::try_select::{{closure}} (16 samples, 0.06%)crossbeam_channel::context::Context::unpark (14 samples, 0.05%)std::thread::Thread::unpark (14 samples, 0.05%)std::sys_common::thread_parker::futex::Parker::unpark (14 samples, 0.05%)syscall (13 samples, 0.05%)entry_SYSCALL_64_after_hwframe (12 samples, 0.04%)do_syscall_64 (12 samples, 0.04%)__x64_sys_futex (12 samples, 0.04%)do_futex (12 samples, 0.04%)futex_wake (12 samples, 0.04%)wake_up_q (7 samples, 0.03%)try_to_wake_up (7 samples, 0.03%)ttwu_queue_wakelist (5 samples, 0.02%)crossbeam_channel::channel::Sender<T>::send (55 samples, 0.20%)crossbeam_channel::flavors::list::Channel<T>::send (55 samples, 0.20%)crossbeam_channel::flavors::list::Channel<T>::write (34 samples, 0.13%)crossbeam_channel::waker::SyncWaker::notify (21 samples, 0.08%)crossbeam_channel::waker::Waker::try_select (17 samples, 0.06%)k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)__set_cpus_allowed_ptr (6 samples, 0.02%)stop_one_cpu (6 samples, 0.02%)_cond_resched (6 samples, 0.02%)__schedule (6 samples, 0.02%)finish_task_switch (6 samples, 0.02%)__mmdrop (6 samples, 0.02%)pgd_free (6 samples, 0.02%)__list_del_entry_valid (6 samples, 0.02%)put_cpu_partial (4 samples, 0.01%)unfreeze_partials (3 samples, 0.01%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)kfree (6 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)__free_one_page (21 samples, 0.08%)__list_add_valid (3 samples, 0.01%)__list_del_entry_valid (8 samples, 0.03%)free_pcppages_bulk (67 samples, 0.25%)_raw_spin_lock (33 samples, 0.12%)native_queued_spin_lock_slowpath (31 samples, 0.11%)__consume_stateless_skb (112 samples, 0.41%)skb_release_data (106 samples, 0.39%)free_unref_page (80 samples, 0.30%)__skb_recv_udp (5 samples, 0.02%)udp_rmem_release (3 samples, 0.01%)kmem_cache_free (3 samples, 0.01%)lock_sock_nested (3 samples, 0.01%)_raw_spin_lock_bh (3 samples, 0.01%)flush_smp_call_function_queue (11 samples, 0.04%)llist_reverse_order (4 samples, 0.01%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (12 samples, 0.04%)asm_call_sysvec_on_stack (12 samples, 0.04%)__sysvec_call_function (12 samples, 0.04%)_copy_to_iter (193 samples, 0.71%)copy_user_generic_string (191 samples, 0.71%)__virt_addr_valid (6 samples, 0.02%)inet_recvmsg (421 samples, 1.56%)udp_recvmsg (421 samples, 1.56%)skb_copy_datagram_iter (290 samples, 1.07%)__skb_datagram_iter (289 samples, 1.07%)simple_copy_to_iter (69 samples, 0.26%)__check_object_size (69 samples, 0.26%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)move_addr_to_user (3 samples, 0.01%)entry_SYSCALL_64_after_hwframe (429 samples, 1.59%)do_syscall_64 (429 samples, 1.59%)__x64_sys_recvfrom (429 samples, 1.59%)__sys_recvfrom (428 samples, 1.59%)sockfd_lookup_light (3 samples, 0.01%)__fget_light (3 samples, 0.01%)__fget_files (3 samples, 0.01%)__libc_recvfrom (433 samples, 1.60%)main::recv_decode_loop (1,935 samples, 7.17%)main::recv..std::net::udp::UdpSocket::recv_from (434 samples, 1.61%)std::sys_common::net::UdpSocket::recv_from (434 samples, 1.61%)std::sys::unix::net::Socket::recv_from (434 samples, 1.61%)std::sys::unix::net::Socket::recv_from_with_flags (434 samples, 1.61%)entry_SYSCALL_64 (4 samples, 0.01%)[unknown] (1,943 samples, 7.20%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (7 samples, 0.03%)__libc_recvfrom (7 samples, 0.03%)recv-decode-3 (1,947 samples, 7.21%)recv-decod..extent_grow_retained (4 samples, 0.01%)extent_alloc_default_impl (4 samples, 0.01%)extent_alloc_core (4 samples, 0.01%)_rjem_je_extent_alloc_mmap (4 samples, 0.01%)_rjem_je_pages_map (4 samples, 0.01%)os_pages_map (4 samples, 0.01%)__GI___mmap64 (4 samples, 0.01%)__GI___mmap64 (4 samples, 0.01%)entry_SYSCALL_64_after_hwframe (4 samples, 0.01%)do_syscall_64 (4 samples, 0.01%)vm_mmap_pgoff (4 samples, 0.01%)extent_recycle (3 samples, 0.01%)extent_recycle_split (3 samples, 0.01%)extent_split_interior (3 samples, 0.01%)extent_split_impl (3 samples, 0.01%)_rjem_je_extent_alloc_wrapper (8 samples, 0.03%)extent_alloc_retained (8 samples, 0.03%)asm_exc_page_fault (4 samples, 0.01%)down_read (6 samples, 0.02%)__list_add_valid (5 samples, 0.02%)__mod_lruvec_state (3 samples, 0.01%)__pagevec_lru_add_fn (30 samples, 0.11%)_raw_spin_lock_irqsave (19 samples, 0.07%)native_queued_spin_lock_slowpath (15 samples, 0.06%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)_raw_spin_unlock_irqrestore (7 samples, 0.03%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)lru_add_drain (65 samples, 0.24%)lru_add_drain_cpu (65 samples, 0.24%)pagevec_lru_move_fn (65 samples, 0.24%)release_pages (6 samples, 0.02%)flush_tlb_func_common.constprop.0 (10 samples, 0.04%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (12 samples, 0.04%)__default_send_IPI_dest_field (12 samples, 0.04%)smp_call_function_many_cond (36 samples, 0.13%)tlb_is_not_lazy (5 samples, 0.02%)on_each_cpu_cond_mask (37 samples, 0.14%)flush_tlb_func_remote (3 samples, 0.01%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (11 samples, 0.04%)__default_send_IPI_dest_field (74 samples, 0.27%)asm_sysvec_call_function (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (82 samples, 0.30%)flush_tlb_mm_range (347 samples, 1.29%)smp_call_function_many_cond (294 samples, 1.09%)llist_add_batch (30 samples, 0.11%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)free_unref_page (5 samples, 0.02%)free_pcppages_bulk (4 samples, 0.01%)__list_del_entry_valid (4 samples, 0.01%)_raw_spin_lock_irqsave (37 samples, 0.14%)native_queued_spin_lock_slowpath (29 samples, 0.11%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)__free_one_page (20 samples, 0.07%)__list_del_entry_valid (7 samples, 0.03%)free_pcppages_bulk (42 samples, 0.16%)_raw_spin_lock (14 samples, 0.05%)native_queued_spin_lock_slowpath (12 samples, 0.04%)free_unref_page_list (50 samples, 0.19%)uncharge_batch (25 samples, 0.09%)page_counter_uncharge (23 samples, 0.09%)mem_cgroup_uncharge_list (29 samples, 0.11%)tlb_finish_mmu (497 samples, 1.84%)t..release_pages (136 samples, 0.50%)mem_cgroup_update_lru_size (4 samples, 0.01%)tlb_gather_mmu (6 samples, 0.02%)__tlb_remove_page_size (20 samples, 0.07%)__get_free_pages (20 samples, 0.07%)__alloc_pages_nodemask (20 samples, 0.07%)get_page_from_freelist (20 samples, 0.07%)prep_new_page (13 samples, 0.05%)kernel_init_free_pages (13 samples, 0.05%)clear_page_rep (13 samples, 0.05%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)page_remove_rmap (15 samples, 0.06%)deferred_split_huge_page (3 samples, 0.01%)_rjem_je_pages_purge_forced (652 samples, 2.41%)_r..__GI_madvise (651 samples, 2.41%)__..entry_SYSCALL_64_after_hwframe (644 samples, 2.39%)en..do_syscall_64 (644 samples, 2.39%)do..__x64_sys_madvise (644 samples, 2.39%)__..do_madvise.part.0 (644 samples, 2.39%)do..zap_page_range (637 samples, 2.36%)z..unmap_page_range (66 samples, 0.24%)sync_mm_rss (3 samples, 0.01%)_rjem_je_extent_heap_first (3 samples, 0.01%)extents_fit_locked (4 samples, 0.01%)extents_best_fit_locked (4 samples, 0.01%)malloc_mutex_lock (10 samples, 0.04%)malloc_mutex_trylock_final (9 samples, 0.03%)__GI___pthread_mutex_trylock (9 samples, 0.03%)extent_recycle_extract (17 samples, 0.06%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)_rjem_je_arena_extent_alloc_large (691 samples, 2.56%)_r..extent_recycle (679 samples, 2.51%)ex..extent_recycle_split (9 samples, 0.03%)extent_split_interior (7 samples, 0.03%)extent_split_impl (7 samples, 0.03%)extent_lock2 (4 samples, 0.01%)mutex_pool_lock2 (4 samples, 0.01%)arena_decay_tick (8 samples, 0.03%)arena_decay_ticks (8 samples, 0.03%)_rjem_je_arena_decay (8 samples, 0.03%)arena_decay_dirty (8 samples, 0.03%)arena_decay_impl (8 samples, 0.03%)arena_maybe_decay (8 samples, 0.03%)arena_maybe_decay (8 samples, 0.03%)arena_decay_try_purge (8 samples, 0.03%)arena_decay_try_purge (8 samples, 0.03%)arena_decay_to_limit (8 samples, 0.03%)arena_decay_stashed (8 samples, 0.03%)_rjem_je_extent_purge_lazy_wrapper (8 samples, 0.03%)extent_purge_lazy_impl (8 samples, 0.03%)_rjem_je_pages_purge_lazy (8 samples, 0.03%)_rjem_je_pages_purge_lazy (8 samples, 0.03%)__GI_madvise (8 samples, 0.03%)entry_SYSCALL_64_after_hwframe (8 samples, 0.03%)do_syscall_64 (8 samples, 0.03%)__x64_sys_madvise (8 samples, 0.03%)do_madvise.part.0 (8 samples, 0.03%)madvise_free_single_vma (8 samples, 0.03%)walk_page_range (8 samples, 0.03%)__walk_page_range (8 samples, 0.03%)madvise_free_pte_range (8 samples, 0.03%)split_huge_page_to_list (8 samples, 0.03%)try_to_unmap (7 samples, 0.03%)rmap_walk_anon (7 samples, 0.03%)try_to_unmap_one (7 samples, 0.03%)ptep_clear_flush (7 samples, 0.03%)flush_tlb_mm_range (7 samples, 0.03%)on_each_cpu_cond_mask (7 samples, 0.03%)smp_call_function_many_cond (7 samples, 0.03%)imalloc_no_sample (703 samples, 2.60%)im..iallocztm (703 samples, 2.60%)ia..arena_malloc (703 samples, 2.60%)ar..tcache_alloc_large (703 samples, 2.60%)tc.._rjem_je_large_palloc (703 samples, 2.60%)_r..alloc::vec::from_elem (704 samples, 2.61%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (704 samples, 2.61%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (704 samples, 2.61%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (704 samples, 2.61%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (704 samples, 2.61%)<a..alloc::alloc::Global::alloc_impl (704 samples, 2.61%)al..alloc::alloc::alloc_zeroed (704 samples, 2.61%)al.._rjem_calloc (704 samples, 2.61%)_r..imalloc (704 samples, 2.61%)im..imalloc_body (704 samples, 2.61%)im..asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)down_read_trylock (47 samples, 0.17%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)__list_del_entry_valid (8 samples, 0.03%)_raw_spin_lock (19 samples, 0.07%)native_queued_spin_lock_slowpath (19 samples, 0.07%)asm_sysvec_call_function (5 samples, 0.02%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (4 samples, 0.01%)get_page_from_freelist (324 samples, 1.20%)prep_new_page (250 samples, 0.93%)kernel_init_free_pages (244 samples, 0.90%)clear_page_rep (234 samples, 0.87%)asm_sysvec_call_function (24 samples, 0.09%)sysvec_call_function (15 samples, 0.06%)asm_call_sysvec_on_stack (15 samples, 0.06%)__sysvec_call_function (15 samples, 0.06%)flush_smp_call_function_queue (15 samples, 0.06%)llist_reverse_order (3 samples, 0.01%)alloc_pages_vma (340 samples, 1.26%)__alloc_pages_nodemask (335 samples, 1.24%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)alloc_pages_vma (36 samples, 0.13%)__alloc_pages_nodemask (36 samples, 0.13%)get_page_from_freelist (36 samples, 0.13%)prep_new_page (36 samples, 0.13%)kernel_init_free_pages (36 samples, 0.13%)clear_page_rep (36 samples, 0.13%)clear_huge_page (11 samples, 0.04%)clear_subpage (10 samples, 0.04%)clear_page_rep (10 samples, 0.04%)do_huge_pmd_anonymous_page (49 samples, 0.18%)mem_cgroup_charge_statistics.constprop.0 (11 samples, 0.04%)__count_memcg_events.part.0 (6 samples, 0.02%)mem_cgroup_charge (32 samples, 0.12%)try_charge (15 samples, 0.06%)page_counter_try_charge (3 samples, 0.01%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)handle_mm_fault (479 samples, 1.77%)h..page_add_new_anon_rmap (12 samples, 0.04%)asm_exc_page_fault (619 samples, 2.29%)a..exc_page_fault (592 samples, 2.19%)e..do_user_addr_fault (590 samples, 2.19%)d..up_read (50 samples, 0.19%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)llist_reverse_order (3 samples, 0.01%)flush_tlb_func_remote (4 samples, 0.01%)asm_sysvec_call_function (10 samples, 0.04%)sysvec_call_function (9 samples, 0.03%)__sysvec_call_function (9 samples, 0.03%)flush_smp_call_function_queue (9 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)error_entry (8 samples, 0.03%)sync_regs (8 samples, 0.03%)k2o::decode::decode (770 samples, 2.85%)k2..<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,482 samples, 5.49%)<k2o::b..std::time::Instant::now (6 samples, 0.02%)std::sys::unix::time::inner::Instant::now (6 samples, 0.02%)std::sys::unix::time::inner::now (6 samples, 0.02%)__GI___clock_gettime (6 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::start_send (13 samples, 0.05%)core::sync::atomic::AtomicPtr<T>::load (7 samples, 0.03%)core::sync::atomic::atomic_load (7 samples, 0.03%)crossbeam_channel::utils::Spinlock<T>::lock (3 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (3 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (3 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (3 samples, 0.01%)crossbeam_channel::channel::Sender<T>::send (39 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::send (37 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::write (23 samples, 0.09%)crossbeam_channel::waker::SyncWaker::notify (18 samples, 0.07%)crossbeam_channel::waker::Waker::try_select (13 samples, 0.05%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (13 samples, 0.05%)crossbeam_channel::waker::Waker::try_select::{{closure}} (13 samples, 0.05%)crossbeam_channel::context::Context::unpark (11 samples, 0.04%)std::thread::Thread::unpark (11 samples, 0.04%)std::sys_common::thread_parker::futex::Parker::unpark (11 samples, 0.04%)syscall (9 samples, 0.03%)entry_SYSCALL_64_after_hwframe (9 samples, 0.03%)do_syscall_64 (9 samples, 0.03%)__x64_sys_futex (9 samples, 0.03%)do_futex (9 samples, 0.03%)futex_wake (9 samples, 0.03%)wake_up_q (3 samples, 0.01%)try_to_wake_up (3 samples, 0.01%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)__GI___sched_setaffinity_new (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)__set_cpus_allowed_ptr (7 samples, 0.03%)stop_one_cpu (7 samples, 0.03%)_cond_resched (7 samples, 0.03%)__schedule (7 samples, 0.03%)finish_task_switch (7 samples, 0.03%)__mmdrop (7 samples, 0.03%)pgd_free (7 samples, 0.03%)__list_del_entry_valid (7 samples, 0.03%)kfree (3 samples, 0.01%)asm_sysvec_call_function (10 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)__free_one_page (38 samples, 0.14%)__list_del_entry_valid (6 samples, 0.02%)__list_del_entry_valid (8 samples, 0.03%)free_pcppages_bulk (75 samples, 0.28%)_raw_spin_lock (25 samples, 0.09%)native_queued_spin_lock_slowpath (24 samples, 0.09%)__consume_stateless_skb (122 samples, 0.45%)skb_release_data (119 samples, 0.44%)free_unref_page (96 samples, 0.36%)free_unref_page_commit (4 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__skb_recv_udp (4 samples, 0.01%)__slab_free (6 samples, 0.02%)kmem_cache_free (10 samples, 0.04%)flush_tlb_func_remote (6 samples, 0.02%)flush_smp_call_function_queue (13 samples, 0.05%)llist_reverse_order (3 samples, 0.01%)_copy_to_iter (164 samples, 0.61%)copy_user_generic_string (160 samples, 0.59%)asm_sysvec_call_function (17 samples, 0.06%)sysvec_call_function (15 samples, 0.06%)asm_call_sysvec_on_stack (15 samples, 0.06%)__sysvec_call_function (15 samples, 0.06%)__virt_addr_valid (10 samples, 0.04%)flush_tlb_func_remote (3 samples, 0.01%)inet_recvmsg (408 samples, 1.51%)udp_recvmsg (408 samples, 1.51%)skb_copy_datagram_iter (265 samples, 0.98%)__skb_datagram_iter (264 samples, 0.98%)simple_copy_to_iter (74 samples, 0.27%)__check_object_size (74 samples, 0.27%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (6 samples, 0.02%)asm_call_sysvec_on_stack (6 samples, 0.02%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)move_addr_to_user (3 samples, 0.01%)__x64_sys_recvfrom (415 samples, 1.54%)__sys_recvfrom (415 samples, 1.54%)entry_SYSCALL_64_after_hwframe (417 samples, 1.54%)do_syscall_64 (417 samples, 1.54%)main::recv_decode_loop (1,954 samples, 7.24%)main::recv..std::net::udp::UdpSocket::recv_from (421 samples, 1.56%)std::sys_common::net::UdpSocket::recv_from (420 samples, 1.56%)std::sys::unix::net::Socket::recv_from (420 samples, 1.56%)std::sys::unix::net::Socket::recv_from_with_flags (420 samples, 1.56%)__libc_recvfrom (420 samples, 1.56%)asm_sysvec_call_function (4 samples, 0.01%)[unknown] (1,963 samples, 7.27%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (9 samples, 0.03%)__libc_recvfrom (9 samples, 0.03%)entry_SYSCALL_64 (5 samples, 0.02%)recv-decode-4 (1,966 samples, 7.28%)recv-decod..extent_lock2 (3 samples, 0.01%)mutex_pool_lock2 (3 samples, 0.01%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)_rjem_je_extent_alloc_wrapper (6 samples, 0.02%)extent_alloc_retained (6 samples, 0.02%)extent_recycle (6 samples, 0.02%)extent_recycle_split (6 samples, 0.02%)extent_split_interior (6 samples, 0.02%)extent_split_impl (6 samples, 0.02%)asm_exc_page_fault (6 samples, 0.02%)down_read (4 samples, 0.01%)up_read (3 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__mod_lruvec_state (5 samples, 0.02%)__mod_node_page_state (4 samples, 0.01%)__mod_memcg_lruvec_state (5 samples, 0.02%)__mod_memcg_state.part.0 (4 samples, 0.01%)__pagevec_lru_add_fn (29 samples, 0.11%)page_mapping (5 samples, 0.02%)_raw_spin_lock_irqsave (23 samples, 0.09%)native_queued_spin_lock_slowpath (22 samples, 0.08%)_raw_spin_unlock_irqrestore (6 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)lru_add_drain (65 samples, 0.24%)lru_add_drain_cpu (65 samples, 0.24%)pagevec_lru_move_fn (65 samples, 0.24%)release_pages (3 samples, 0.01%)cpumask_any_but (3 samples, 0.01%)_find_next_bit.constprop.0 (3 samples, 0.01%)flush_tlb_func_common.constprop.0 (8 samples, 0.03%)native_flush_tlb_local (3 samples, 0.01%)__default_send_IPI_dest_field (12 samples, 0.04%)default_send_IPI_mask_sequence_phys (15 samples, 0.06%)on_each_cpu_cond_mask (46 samples, 0.17%)smp_call_function_many_cond (46 samples, 0.17%)tlb_is_not_lazy (5 samples, 0.02%)flush_smp_call_function_queue (8 samples, 0.03%)asm_sysvec_call_function (17 samples, 0.06%)sysvec_call_function (10 samples, 0.04%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)cpumask_next (3 samples, 0.01%)_find_next_bit.constprop.0 (3 samples, 0.01%)__default_send_IPI_dest_field (49 samples, 0.18%)default_send_IPI_mask_sequence_phys (58 samples, 0.21%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (6 samples, 0.02%)asm_call_sysvec_on_stack (6 samples, 0.02%)__sysvec_call_function (6 samples, 0.02%)flush_smp_call_function_queue (6 samples, 0.02%)flush_tlb_mm_range (342 samples, 1.27%)smp_call_function_many_cond (280 samples, 1.04%)llist_add_batch (23 samples, 0.09%)__free_one_page (4 samples, 0.01%)free_unref_page (8 samples, 0.03%)free_pcppages_bulk (8 samples, 0.03%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)__list_del_entry_valid (5 samples, 0.02%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)_raw_spin_lock_irqsave (23 samples, 0.09%)native_queued_spin_lock_slowpath (19 samples, 0.07%)_raw_spin_unlock_irqrestore (4 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__free_one_page (21 samples, 0.08%)__list_del_entry_valid (5 samples, 0.02%)free_unref_page_list (50 samples, 0.19%)free_pcppages_bulk (46 samples, 0.17%)_raw_spin_lock (14 samples, 0.05%)native_queued_spin_lock_slowpath (13 samples, 0.05%)uncharge_batch (22 samples, 0.08%)page_counter_uncharge (20 samples, 0.07%)mem_cgroup_uncharge_list (29 samples, 0.11%)uncharge_page (3 samples, 0.01%)tlb_finish_mmu (481 samples, 1.78%)t..release_pages (124 samples, 0.46%)mem_cgroup_update_lru_size (4 samples, 0.01%)tlb_gather_mmu (4 samples, 0.01%)__alloc_pages_nodemask (20 samples, 0.07%)get_page_from_freelist (19 samples, 0.07%)prep_new_page (14 samples, 0.05%)kernel_init_free_pages (14 samples, 0.05%)clear_page_rep (14 samples, 0.05%)__tlb_remove_page_size (21 samples, 0.08%)__get_free_pages (21 samples, 0.08%)asm_sysvec_call_function (4 samples, 0.01%)page_remove_rmap (15 samples, 0.06%)deferred_split_huge_page (3 samples, 0.01%)__x64_sys_madvise (634 samples, 2.35%)_..do_madvise.part.0 (634 samples, 2.35%)d..zap_page_range (627 samples, 2.32%)z..unmap_page_range (75 samples, 0.28%)sync_mm_rss (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (635 samples, 2.35%)e..do_syscall_64 (635 samples, 2.35%)d.._rjem_je_pages_purge_forced (647 samples, 2.40%)_r..__GI_madvise (645 samples, 2.39%)__.._rjem_je_extent_heap_first (3 samples, 0.01%)extents_fit_locked (6 samples, 0.02%)extents_best_fit_locked (6 samples, 0.02%)malloc_mutex_lock (5 samples, 0.02%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_recycle_extract (13 samples, 0.05%)_rjem_je_extent_alloc (5 samples, 0.02%)malloc_mutex_lock (4 samples, 0.01%)malloc_mutex_trylock_final (4 samples, 0.01%)__GI___pthread_mutex_trylock (4 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)extent_lock2 (4 samples, 0.01%)mutex_pool_lock2 (4 samples, 0.01%)malloc_mutex_lock (4 samples, 0.01%)extent_split_impl (10 samples, 0.04%)alloc::vec::from_elem (688 samples, 2.55%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (688 samples, 2.55%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (688 samples, 2.55%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (688 samples, 2.55%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (688 samples, 2.55%)<a..alloc::alloc::Global::alloc_impl (688 samples, 2.55%)al..alloc::alloc::alloc_zeroed (688 samples, 2.55%)al.._rjem_calloc (688 samples, 2.55%)_r..imalloc (688 samples, 2.55%)im..imalloc_body (688 samples, 2.55%)im..imalloc_no_sample (688 samples, 2.55%)im..iallocztm (688 samples, 2.55%)ia..arena_malloc (688 samples, 2.55%)ar..tcache_alloc_large (687 samples, 2.54%)tc.._rjem_je_large_palloc (687 samples, 2.54%)_r.._rjem_je_arena_extent_alloc_large (685 samples, 2.54%)_r..extent_recycle (677 samples, 2.51%)ex..extent_recycle_split (15 samples, 0.06%)extent_split_interior (13 samples, 0.05%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)down_read_trylock (53 samples, 0.20%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__count_memcg_events.part.0 (6 samples, 0.02%)__list_del_entry_valid (5 samples, 0.02%)_raw_spin_lock (22 samples, 0.08%)native_queued_spin_lock_slowpath (20 samples, 0.07%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)flush_tlb_func_remote (5 samples, 0.02%)asm_call_sysvec_on_stack (10 samples, 0.04%)__sysvec_call_function (10 samples, 0.04%)flush_smp_call_function_queue (10 samples, 0.04%)__alloc_pages_nodemask (325 samples, 1.20%)get_page_from_freelist (314 samples, 1.16%)prep_new_page (231 samples, 0.86%)kernel_init_free_pages (227 samples, 0.84%)clear_page_rep (217 samples, 0.80%)asm_sysvec_call_function (22 samples, 0.08%)sysvec_call_function (11 samples, 0.04%)alloc_pages_vma (328 samples, 1.21%)alloc_pages_vma (29 samples, 0.11%)__alloc_pages_nodemask (29 samples, 0.11%)get_page_from_freelist (29 samples, 0.11%)prep_new_page (28 samples, 0.10%)kernel_init_free_pages (28 samples, 0.10%)clear_page_rep (28 samples, 0.10%)do_huge_pmd_anonymous_page (35 samples, 0.13%)clear_huge_page (6 samples, 0.02%)clear_subpage (6 samples, 0.02%)clear_page_rep (6 samples, 0.02%)lru_cache_add (4 samples, 0.01%)get_mem_cgroup_from_mm (4 samples, 0.01%)mem_cgroup_charge_statistics.constprop.0 (5 samples, 0.02%)__count_memcg_events.part.0 (3 samples, 0.01%)mem_cgroup_charge (35 samples, 0.13%)try_charge (20 samples, 0.07%)page_counter_try_charge (6 samples, 0.02%)__mod_lruvec_state (3 samples, 0.01%)__mod_node_page_state (3 samples, 0.01%)handle_mm_fault (459 samples, 1.70%)page_add_new_anon_rmap (8 samples, 0.03%)exc_page_fault (567 samples, 2.10%)e..do_user_addr_fault (563 samples, 2.09%)d..up_read (43 samples, 0.16%)asm_exc_page_fault (596 samples, 2.21%)a..asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)llist_reverse_order (3 samples, 0.01%)error_entry (5 samples, 0.02%)sync_regs (5 samples, 0.02%)k2o::decode::decode (730 samples, 2.70%)k2..<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,422 samples, 5.27%)<k2o::..std::time::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::Instant::now (4 samples, 0.01%)std::sys::unix::time::inner::now (4 samples, 0.01%)__GI___clock_gettime (3 samples, 0.01%)__vdso_clock_gettime (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::try_recv (6 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::try_recv (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_recv (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (12 samples, 0.04%)core::sync::atomic::AtomicPtr<T>::load (9 samples, 0.03%)core::sync::atomic::atomic_load (9 samples, 0.03%)crossbeam_channel::utils::Spinlock<T>::lock (4 samples, 0.01%)crossbeam_utils::backoff::Backoff::snooze (4 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (3 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (3 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (4 samples, 0.01%)crossbeam_channel::waker::Waker::try_select::{{closure}} (4 samples, 0.01%)crossbeam_channel::context::Context::unpark (3 samples, 0.01%)std::thread::Thread::unpark (3 samples, 0.01%)std::sys_common::thread_parker::futex::Parker::unpark (3 samples, 0.01%)crossbeam_channel::channel::Sender<T>::send (37 samples, 0.14%)crossbeam_channel::flavors::list::Channel<T>::send (35 samples, 0.13%)crossbeam_channel::flavors::list::Channel<T>::write (22 samples, 0.08%)crossbeam_channel::waker::SyncWaker::notify (11 samples, 0.04%)crossbeam_channel::waker::Waker::try_select (6 samples, 0.02%)k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)kfree (6 samples, 0.02%)slab_free_freelist_hook.constprop.0 (6 samples, 0.02%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)kfree (13 samples, 0.05%)__free_one_page (32 samples, 0.12%)__list_del_entry_valid (3 samples, 0.01%)free_pcppages_bulk (71 samples, 0.26%)_raw_spin_lock (33 samples, 0.12%)native_queued_spin_lock_slowpath (32 samples, 0.12%)__consume_stateless_skb (125 samples, 0.46%)skb_release_data (112 samples, 0.41%)free_unref_page (90 samples, 0.33%)free_unref_page_commit (3 samples, 0.01%)__skb_recv_udp (4 samples, 0.01%)udp_rmem_release (3 samples, 0.01%)kmem_cache_free (9 samples, 0.03%)flush_tlb_func_remote (4 samples, 0.01%)_copy_to_iter (220 samples, 0.81%)copy_user_generic_string (217 samples, 0.80%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (13 samples, 0.05%)asm_call_sysvec_on_stack (13 samples, 0.05%)__sysvec_call_function (13 samples, 0.05%)flush_smp_call_function_queue (12 samples, 0.04%)llist_reverse_order (3 samples, 0.01%)__virt_addr_valid (5 samples, 0.02%)inet_recvmsg (467 samples, 1.73%)udp_recvmsg (466 samples, 1.73%)skb_copy_datagram_iter (315 samples, 1.17%)__skb_datagram_iter (315 samples, 1.17%)simple_copy_to_iter (81 samples, 0.30%)__check_object_size (80 samples, 0.30%)move_addr_to_user (4 samples, 0.01%)__libc_recvfrom (480 samples, 1.78%)_..entry_SYSCALL_64_after_hwframe (478 samples, 1.77%)e..do_syscall_64 (478 samples, 1.77%)d..__x64_sys_recvfrom (478 samples, 1.77%)_..__sys_recvfrom (478 samples, 1.77%)_..main::recv_decode_loop (1,955 samples, 7.24%)main::recv..std::net::udp::UdpSocket::recv_from (482 samples, 1.79%)s..std::sys_common::net::UdpSocket::recv_from (481 samples, 1.78%)s..std::sys::unix::net::Socket::recv_from (481 samples, 1.78%)s..std::sys::unix::net::Socket::recv_from_with_flags (481 samples, 1.78%)s..[unknown] (1,957 samples, 7.25%)[unknown]recv-decode-5 (1,958 samples, 7.25%)recv-decod..base_alloc_impl (3 samples, 0.01%)_rjem_je_extent_alloc (6 samples, 0.02%)_rjem_je_base_alloc_extent (6 samples, 0.02%)extent_esn_set (3 samples, 0.01%)_rjem_je_extent_alloc (7 samples, 0.03%)_rjem_je_extent_alloc_wrapper (12 samples, 0.04%)extent_alloc_retained (12 samples, 0.04%)extent_recycle (11 samples, 0.04%)extent_recycle_split (10 samples, 0.04%)extent_split_interior (10 samples, 0.04%)extent_split_impl (10 samples, 0.04%)asm_exc_page_fault (4 samples, 0.01%)down_read (8 samples, 0.03%)__list_add_valid (4 samples, 0.01%)__mod_memcg_lruvec_state (4 samples, 0.01%)__mod_memcg_state.part.0 (4 samples, 0.01%)__pagevec_lru_add_fn (20 samples, 0.07%)_raw_spin_lock_irqsave (14 samples, 0.05%)native_queued_spin_lock_slowpath (10 samples, 0.04%)_raw_spin_unlock_irqrestore (5 samples, 0.02%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)lru_add_drain (47 samples, 0.17%)lru_add_drain_cpu (47 samples, 0.17%)pagevec_lru_move_fn (47 samples, 0.17%)release_pages (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (7 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (17 samples, 0.06%)__default_send_IPI_dest_field (16 samples, 0.06%)on_each_cpu_cond_mask (49 samples, 0.18%)smp_call_function_many_cond (48 samples, 0.18%)tlb_is_not_lazy (5 samples, 0.02%)asm_sysvec_call_function (10 samples, 0.04%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (6 samples, 0.02%)__default_send_IPI_dest_field (47 samples, 0.17%)asm_sysvec_call_function (15 samples, 0.06%)sysvec_call_function (9 samples, 0.03%)asm_call_sysvec_on_stack (9 samples, 0.03%)__sysvec_call_function (9 samples, 0.03%)flush_smp_call_function_queue (9 samples, 0.03%)cpumask_next (3 samples, 0.01%)default_send_IPI_mask_sequence_phys (68 samples, 0.25%)llist_add_batch (30 samples, 0.11%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)flush_tlb_mm_range (328 samples, 1.21%)smp_call_function_many_cond (271 samples, 1.00%)free_unref_page (6 samples, 0.02%)free_pcppages_bulk (4 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)__list_del_entry_valid (4 samples, 0.01%)_raw_spin_lock_irqsave (18 samples, 0.07%)native_queued_spin_lock_slowpath (10 samples, 0.04%)asm_sysvec_call_function (3 samples, 0.01%)__free_one_page (21 samples, 0.08%)__list_del_entry_valid (3 samples, 0.01%)free_pcppages_bulk (42 samples, 0.16%)_raw_spin_lock (14 samples, 0.05%)native_queued_spin_lock_slowpath (13 samples, 0.05%)free_unref_page_list (52 samples, 0.19%)uncharge_batch (28 samples, 0.10%)page_counter_uncharge (26 samples, 0.10%)asm_sysvec_call_function (3 samples, 0.01%)mem_cgroup_uncharge_list (31 samples, 0.11%)tlb_finish_mmu (461 samples, 1.71%)release_pages (119 samples, 0.44%)mem_cgroup_update_lru_size (6 samples, 0.02%)tlb_gather_mmu (6 samples, 0.02%)__split_huge_pmd (3 samples, 0.01%)__alloc_pages_nodemask (28 samples, 0.10%)get_page_from_freelist (26 samples, 0.10%)prep_new_page (19 samples, 0.07%)kernel_init_free_pages (19 samples, 0.07%)clear_page_rep (19 samples, 0.07%)__tlb_remove_page_size (30 samples, 0.11%)__get_free_pages (29 samples, 0.11%)__mod_lruvec_state (3 samples, 0.01%)page_remove_rmap (13 samples, 0.05%)entry_SYSCALL_64_after_hwframe (612 samples, 2.27%)e..do_syscall_64 (612 samples, 2.27%)d..__x64_sys_madvise (612 samples, 2.27%)_..do_madvise.part.0 (612 samples, 2.27%)d..zap_page_range (601 samples, 2.23%)z..unmap_page_range (85 samples, 0.31%)sync_mm_rss (7 samples, 0.03%)__GI_madvise (618 samples, 2.29%)_.._rjem_je_pages_purge_forced (620 samples, 2.30%)_..extent_activate_locked (4 samples, 0.01%)extents_remove_locked (4 samples, 0.01%)_rjem_je_extent_heap_first (3 samples, 0.01%)extents_fit_locked (7 samples, 0.03%)extents_best_fit_locked (6 samples, 0.02%)extent_size_quantize_ceil (3 samples, 0.01%)extent_size_quantize_floor (3 samples, 0.01%)sz_psz2ind (3 samples, 0.01%)malloc_mutex_lock (6 samples, 0.02%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_recycle_extract (18 samples, 0.07%)_rjem_je_extent_alloc (6 samples, 0.02%)malloc_mutex_lock (3 samples, 0.01%)malloc_mutex_trylock_final (3 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)malloc_mutex_lock (4 samples, 0.01%)malloc_mutex_trylock_final (4 samples, 0.01%)__GI___pthread_mutex_trylock (3 samples, 0.01%)extent_lock2 (5 samples, 0.02%)mutex_pool_lock2 (5 samples, 0.02%)extent_split_impl (14 samples, 0.05%)_rjem_je_arena_extent_alloc_large (672 samples, 2.49%)_r..extent_recycle (658 samples, 2.44%)ex..extent_recycle_split (18 samples, 0.07%)extent_split_interior (17 samples, 0.06%)alloc::vec::from_elem (681 samples, 2.52%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (681 samples, 2.52%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (681 samples, 2.52%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (681 samples, 2.52%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (681 samples, 2.52%)<a..alloc::alloc::Global::alloc_impl (681 samples, 2.52%)al..alloc::alloc::alloc_zeroed (681 samples, 2.52%)al.._rjem_calloc (681 samples, 2.52%)_r..imalloc (681 samples, 2.52%)im..imalloc_body (681 samples, 2.52%)im..imalloc_no_sample (681 samples, 2.52%)im..iallocztm (681 samples, 2.52%)ia..arena_malloc (681 samples, 2.52%)ar..tcache_alloc_large (679 samples, 2.51%)tc.._rjem_je_large_palloc (679 samples, 2.51%)_r..__irqentry_text_end (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)down_read_trylock (49 samples, 0.18%)__count_memcg_events.part.0 (3 samples, 0.01%)__list_del_entry_valid (9 samples, 0.03%)_raw_spin_lock (25 samples, 0.09%)native_queued_spin_lock_slowpath (23 samples, 0.09%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_func_remote (3 samples, 0.01%)get_page_from_freelist (335 samples, 1.24%)prep_new_page (254 samples, 0.94%)kernel_init_free_pages (253 samples, 0.94%)clear_page_rep (246 samples, 0.91%)asm_sysvec_call_function (25 samples, 0.09%)sysvec_call_function (16 samples, 0.06%)asm_call_sysvec_on_stack (16 samples, 0.06%)__sysvec_call_function (16 samples, 0.06%)flush_smp_call_function_queue (16 samples, 0.06%)llist_reverse_order (8 samples, 0.03%)__alloc_pages_nodemask (340 samples, 1.26%)alloc_pages_vma (344 samples, 1.27%)cgroup_throttle_swaprate (3 samples, 0.01%)kernel_init_free_pages (28 samples, 0.10%)clear_page_rep (28 samples, 0.10%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)alloc_pages_vma (30 samples, 0.11%)__alloc_pages_nodemask (30 samples, 0.11%)get_page_from_freelist (30 samples, 0.11%)prep_new_page (29 samples, 0.11%)clear_huge_page (7 samples, 0.03%)clear_subpage (7 samples, 0.03%)clear_page_rep (6 samples, 0.02%)do_huge_pmd_anonymous_page (39 samples, 0.14%)mem_cgroup_charge_statistics.constprop.0 (6 samples, 0.02%)__count_memcg_events.part.0 (5 samples, 0.02%)rcu_read_unlock_strict (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)page_counter_try_charge (4 samples, 0.01%)mem_cgroup_charge (45 samples, 0.17%)try_charge (27 samples, 0.10%)handle_mm_fault (491 samples, 1.82%)h..page_add_new_anon_rmap (10 samples, 0.04%)__mod_lruvec_state (5 samples, 0.02%)__mod_node_page_state (4 samples, 0.01%)exc_page_fault (590 samples, 2.19%)e..do_user_addr_fault (588 samples, 2.18%)d..up_read (43 samples, 0.16%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)asm_exc_page_fault (630 samples, 2.33%)a..asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)llist_reverse_order (3 samples, 0.01%)k2o::decode::decode (764 samples, 2.83%)k2..error_entry (4 samples, 0.01%)sync_regs (4 samples, 0.01%)<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,449 samples, 5.37%)<k2o::b..std::time::Instant::now (3 samples, 0.01%)crossbeam_channel::channel::Receiver<T>::try_recv (8 samples, 0.03%)crossbeam_channel::flavors::list::Channel<T>::try_recv (5 samples, 0.02%)crossbeam_channel::flavors::list::Channel<T>::start_recv (4 samples, 0.01%)alloc::boxed::Box<T>::new (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (5 samples, 0.02%)crossbeam_channel::channel::Sender<T>::send (17 samples, 0.06%)crossbeam_channel::flavors::list::Channel<T>::send (16 samples, 0.06%)crossbeam_channel::flavors::list::Channel<T>::write (11 samples, 0.04%)crossbeam_channel::waker::SyncWaker::notify (6 samples, 0.02%)crossbeam_channel::waker::Waker::try_select (5 samples, 0.02%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (5 samples, 0.02%)crossbeam_channel::waker::Waker::try_select::{{closure}} (5 samples, 0.02%)crossbeam_channel::context::Context::unpark (5 samples, 0.02%)std::thread::Thread::unpark (5 samples, 0.02%)std::sys_common::thread_parker::futex::Parker::unpark (5 samples, 0.02%)syscall (5 samples, 0.02%)entry_SYSCALL_64_after_hwframe (5 samples, 0.02%)do_syscall_64 (5 samples, 0.02%)__x64_sys_futex (5 samples, 0.02%)do_futex (5 samples, 0.02%)futex_wake (5 samples, 0.02%)wake_up_q (5 samples, 0.02%)try_to_wake_up (5 samples, 0.02%)k2o::helpers::set_cpu_affinity (7 samples, 0.03%)nix::sched::sched_linux_like::sched_setaffinity (7 samples, 0.03%)__GI___sched_setaffinity_new (7 samples, 0.03%)entry_SYSCALL_64_after_hwframe (7 samples, 0.03%)do_syscall_64 (7 samples, 0.03%)__x64_sys_sched_setaffinity (7 samples, 0.03%)sched_setaffinity (7 samples, 0.03%)__set_cpus_allowed_ptr (7 samples, 0.03%)stop_one_cpu (7 samples, 0.03%)_cond_resched (7 samples, 0.03%)__schedule (7 samples, 0.03%)finish_task_switch (7 samples, 0.03%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (7 samples, 0.03%)asm_call_sysvec_on_stack (7 samples, 0.03%)__sysvec_call_function (7 samples, 0.03%)flush_smp_call_function_queue (7 samples, 0.03%)__free_pages_ok (3 samples, 0.01%)free_one_page (3 samples, 0.01%)_raw_spin_lock (3 samples, 0.01%)native_queued_spin_lock_slowpath (3 samples, 0.01%)kfree (7 samples, 0.03%)asm_sysvec_call_function (3 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__free_one_page (29 samples, 0.11%)__list_del_entry_valid (11 samples, 0.04%)__consume_stateless_skb (110 samples, 0.41%)skb_release_data (103 samples, 0.38%)free_unref_page (83 samples, 0.31%)free_pcppages_bulk (70 samples, 0.26%)_raw_spin_lock (25 samples, 0.09%)native_queued_spin_lock_slowpath (23 samples, 0.09%)__skb_recv_udp (3 samples, 0.01%)kmem_cache_free (4 samples, 0.01%)release_sock (5 samples, 0.02%)ip4_datagram_release_cb (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (3 samples, 0.01%)native_flush_tlb_one_user (3 samples, 0.01%)flush_tlb_func_remote (4 samples, 0.01%)_copy_to_iter (216 samples, 0.80%)copy_user_generic_string (213 samples, 0.79%)asm_sysvec_call_function (14 samples, 0.05%)sysvec_call_function (11 samples, 0.04%)asm_call_sysvec_on_stack (11 samples, 0.04%)__sysvec_call_function (11 samples, 0.04%)flush_smp_call_function_queue (11 samples, 0.04%)llist_reverse_order (3 samples, 0.01%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)__virt_addr_valid (11 samples, 0.04%)__check_object_size (74 samples, 0.27%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)inet_recvmsg (449 samples, 1.66%)udp_recvmsg (449 samples, 1.66%)skb_copy_datagram_iter (321 samples, 1.19%)__skb_datagram_iter (321 samples, 1.19%)simple_copy_to_iter (75 samples, 0.28%)move_addr_to_user (3 samples, 0.01%)__x64_sys_recvfrom (458 samples, 1.70%)__sys_recvfrom (458 samples, 1.70%)__libc_recvfrom (459 samples, 1.70%)entry_SYSCALL_64_after_hwframe (459 samples, 1.70%)do_syscall_64 (459 samples, 1.70%)main::recv_decode_loop (1,944 samples, 7.20%)main::recv..std::net::udp::UdpSocket::recv_from (462 samples, 1.71%)std::sys_common::net::UdpSocket::recv_from (460 samples, 1.70%)std::sys::unix::net::Socket::recv_from (460 samples, 1.70%)std::sys::unix::net::Socket::recv_from_with_flags (460 samples, 1.70%)entry_SYSCALL_64 (3 samples, 0.01%)[unknown] (1,949 samples, 7.22%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (5 samples, 0.02%)__libc_recvfrom (5 samples, 0.02%)recv-decode-6 (1,950 samples, 7.22%)recv-decod..extent_recycle_split (3 samples, 0.01%)extent_split_interior (3 samples, 0.01%)extent_split_impl (3 samples, 0.01%)_rjem_je_extent_alloc (3 samples, 0.01%)_rjem_je_extent_alloc (3 samples, 0.01%)_rjem_je_base_alloc_extent (3 samples, 0.01%)extent_recycle (4 samples, 0.01%)_rjem_je_extent_alloc_wrapper (7 samples, 0.03%)extent_alloc_retained (7 samples, 0.03%)asm_exc_page_fault (10 samples, 0.04%)down_read (4 samples, 0.01%)up_read (4 samples, 0.01%)__list_add_valid (5 samples, 0.02%)__pagevec_lru_add_fn (25 samples, 0.09%)_raw_spin_lock_irqsave (16 samples, 0.06%)native_queued_spin_lock_slowpath (13 samples, 0.05%)lru_add_drain (53 samples, 0.20%)lru_add_drain_cpu (53 samples, 0.20%)pagevec_lru_move_fn (52 samples, 0.19%)release_pages (4 samples, 0.01%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)default_send_IPI_mask_sequence_phys (14 samples, 0.05%)__default_send_IPI_dest_field (14 samples, 0.05%)on_each_cpu_cond_mask (46 samples, 0.17%)smp_call_function_many_cond (46 samples, 0.17%)tlb_is_not_lazy (10 samples, 0.04%)flush_tlb_func_remote (3 samples, 0.01%)asm_call_sysvec_on_stack (8 samples, 0.03%)__sysvec_call_function (8 samples, 0.03%)flush_smp_call_function_queue (8 samples, 0.03%)llist_reverse_order (4 samples, 0.01%)asm_sysvec_call_function (12 samples, 0.04%)sysvec_call_function (9 samples, 0.03%)cpumask_next (3 samples, 0.01%)__default_send_IPI_dest_field (60 samples, 0.22%)asm_sysvec_call_function (7 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)default_send_IPI_mask_sequence_phys (71 samples, 0.26%)llist_add_batch (26 samples, 0.10%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)flush_tlb_mm_range (303 samples, 1.12%)smp_call_function_many_cond (249 samples, 0.92%)free_unref_page (9 samples, 0.03%)free_pcppages_bulk (8 samples, 0.03%)_raw_spin_lock (4 samples, 0.01%)native_queued_spin_lock_slowpath (4 samples, 0.01%)__list_del_entry_valid (3 samples, 0.01%)_raw_spin_lock_irqsave (26 samples, 0.10%)native_queued_spin_lock_slowpath (17 samples, 0.06%)_raw_spin_unlock_irqrestore (3 samples, 0.01%)asm_sysvec_call_function (3 samples, 0.01%)__list_add_valid (4 samples, 0.01%)__free_one_page (22 samples, 0.08%)__list_del_entry_valid (5 samples, 0.02%)free_pcppages_bulk (46 samples, 0.17%)_raw_spin_lock (8 samples, 0.03%)native_queued_spin_lock_slowpath (7 samples, 0.03%)free_unref_page_list (55 samples, 0.20%)uncharge_batch (23 samples, 0.09%)page_counter_uncharge (21 samples, 0.08%)mem_cgroup_uncharge_list (24 samples, 0.09%)tlb_finish_mmu (447 samples, 1.66%)release_pages (128 samples, 0.47%)mem_cgroup_update_lru_size (5 samples, 0.02%)tlb_gather_mmu (5 samples, 0.02%)__alloc_pages_nodemask (23 samples, 0.09%)get_page_from_freelist (23 samples, 0.09%)prep_new_page (18 samples, 0.07%)kernel_init_free_pages (18 samples, 0.07%)clear_page_rep (17 samples, 0.06%)__tlb_remove_page_size (25 samples, 0.09%)__get_free_pages (25 samples, 0.09%)page_remove_rmap (15 samples, 0.06%)entry_SYSCALL_64_after_hwframe (581 samples, 2.15%)e..do_syscall_64 (581 samples, 2.15%)d..__x64_sys_madvise (579 samples, 2.14%)_..do_madvise.part.0 (579 samples, 2.14%)d..zap_page_range (571 samples, 2.11%)z..unmap_page_range (64 samples, 0.24%)sync_mm_rss (5 samples, 0.02%)_rjem_je_pages_purge_forced (596 samples, 2.21%)_..__GI_madvise (596 samples, 2.21%)_..extent_activate_locked (3 samples, 0.01%)extents_remove_locked (3 samples, 0.01%)bitmap_ffu (4 samples, 0.01%)ffs_lu (4 samples, 0.01%)extents_fit_locked (8 samples, 0.03%)extents_best_fit_locked (8 samples, 0.03%)malloc_mutex_lock (6 samples, 0.02%)malloc_mutex_trylock_final (5 samples, 0.02%)__GI___pthread_mutex_trylock (5 samples, 0.02%)extent_recycle_extract (19 samples, 0.07%)_rjem_je_extent_avail_first (3 samples, 0.01%)_rjem_je_extent_alloc (5 samples, 0.02%)extent_lock2 (3 samples, 0.01%)mutex_pool_lock2 (3 samples, 0.01%)extent_split_impl (15 samples, 0.06%)extent_unlock2 (4 samples, 0.01%)mutex_pool_unlock2 (4 samples, 0.01%)malloc_mutex_unlock (4 samples, 0.01%)__pthread_mutex_unlock_usercnt (3 samples, 0.01%)_rjem_je_large_palloc (652 samples, 2.41%)_r.._rjem_je_arena_extent_alloc_large (650 samples, 2.41%)_r..extent_recycle (640 samples, 2.37%)ex..extent_recycle_split (23 samples, 0.09%)extent_split_interior (20 samples, 0.07%)alloc::vec::from_elem (659 samples, 2.44%)al..<T as alloc::vec::spec_from_elem::SpecFromElem>::from_elem (659 samples, 2.44%)<T..alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in (658 samples, 2.44%)al..alloc::raw_vec::RawVec<T,A>::allocate_in (658 samples, 2.44%)al..<alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed (658 samples, 2.44%)<a..alloc::alloc::Global::alloc_impl (658 samples, 2.44%)al..alloc::alloc::alloc_zeroed (657 samples, 2.43%)al.._rjem_calloc (656 samples, 2.43%)_r..imalloc (653 samples, 2.42%)im..imalloc_body (653 samples, 2.42%)im..imalloc_no_sample (653 samples, 2.42%)im..iallocztm (653 samples, 2.42%)ia..arena_malloc (653 samples, 2.42%)ar..tcache_alloc_large (653 samples, 2.42%)tc..asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)down_read_trylock (47 samples, 0.17%)__count_memcg_events.part.0 (10 samples, 0.04%)_raw_spin_lock (4 samples, 0.01%)__list_del_entry_valid (15 samples, 0.06%)_raw_spin_lock (12 samples, 0.04%)native_queued_spin_lock_slowpath (12 samples, 0.04%)asm_sysvec_call_function (6 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)kernel_init_free_pages (239 samples, 0.89%)clear_page_rep (235 samples, 0.87%)asm_sysvec_call_function (18 samples, 0.07%)sysvec_call_function (12 samples, 0.04%)asm_call_sysvec_on_stack (12 samples, 0.04%)__sysvec_call_function (12 samples, 0.04%)flush_smp_call_function_queue (11 samples, 0.04%)llist_reverse_order (5 samples, 0.02%)__alloc_pages_nodemask (324 samples, 1.20%)get_page_from_freelist (315 samples, 1.17%)prep_new_page (243 samples, 0.90%)alloc_pages_vma (330 samples, 1.22%)asm_sysvec_call_function (5 samples, 0.02%)sysvec_call_function (4 samples, 0.01%)asm_call_sysvec_on_stack (4 samples, 0.01%)__sysvec_call_function (4 samples, 0.01%)flush_smp_call_function_queue (4 samples, 0.01%)cgroup_throttle_swaprate (4 samples, 0.01%)alloc_pages_vma (32 samples, 0.12%)__alloc_pages_nodemask (32 samples, 0.12%)get_page_from_freelist (32 samples, 0.12%)prep_new_page (29 samples, 0.11%)kernel_init_free_pages (29 samples, 0.11%)clear_page_rep (29 samples, 0.11%)do_huge_pmd_anonymous_page (41 samples, 0.15%)clear_huge_page (9 samples, 0.03%)clear_subpage (9 samples, 0.03%)clear_page_rep (9 samples, 0.03%)get_mem_cgroup_from_mm (8 samples, 0.03%)rcu_read_unlock_strict (3 samples, 0.01%)mem_cgroup_charge (43 samples, 0.16%)try_charge (15 samples, 0.06%)__mod_lruvec_state (5 samples, 0.02%)__mod_node_page_state (5 samples, 0.02%)handle_mm_fault (496 samples, 1.84%)h..page_add_new_anon_rmap (13 samples, 0.05%)do_user_addr_fault (594 samples, 2.20%)d..up_read (42 samples, 0.16%)asm_exc_page_fault (631 samples, 2.34%)a..exc_page_fault (596 samples, 2.21%)e..flush_tlb_func_remote (5 samples, 0.02%)asm_sysvec_call_function (15 samples, 0.06%)sysvec_call_function (14 samples, 0.05%)__sysvec_call_function (14 samples, 0.05%)flush_smp_call_function_queue (14 samples, 0.05%)llist_reverse_order (5 samples, 0.02%)error_entry (8 samples, 0.03%)sync_regs (6 samples, 0.02%)k2o::decode::decode (788 samples, 2.92%)k2..<k2o::block::K2ISBlock as k2o::block::K2Block>::from_bytes (1,450 samples, 5.37%)<k2o::b..std::time::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::Instant::now (3 samples, 0.01%)std::sys::unix::time::inner::now (3 samples, 0.01%)__GI___clock_gettime (3 samples, 0.01%)crossbeam_channel::flavors::list::Channel<T>::start_send (3 samples, 0.01%)core::sync::atomic::AtomicPtr<T>::load (3 samples, 0.01%)core::sync::atomic::atomic_load (3 samples, 0.01%)crossbeam_channel::utils::Spinlock<T>::lock (5 samples, 0.02%)crossbeam_utils::backoff::Backoff::snooze (4 samples, 0.01%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.01%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.01%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (3 samples, 0.01%)crossbeam_channel::channel::Sender<T>::send (26 samples, 0.10%)crossbeam_channel::flavors::list::Channel<T>::send (24 samples, 0.09%)crossbeam_channel::flavors::list::Channel<T>::write (21 samples, 0.08%)crossbeam_channel::waker::SyncWaker::notify (11 samples, 0.04%)crossbeam_channel::waker::Waker::try_select (4 samples, 0.01%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (4 samples, 0.01%)crossbeam_channel::waker::Waker::try_select::{{closure}} (4 samples, 0.01%)crossbeam_channel::context::Context::unpark (4 samples, 0.01%)std::thread::Thread::unpark (4 samples, 0.01%)std::sys_common::thread_parker::futex::Parker::unpark (4 samples, 0.01%)syscall (4 samples, 0.01%)entry_SYSCALL_64_after_hwframe (3 samples, 0.01%)do_syscall_64 (3 samples, 0.01%)__x64_sys_futex (3 samples, 0.01%)do_futex (3 samples, 0.01%)futex_wake (3 samples, 0.01%)k2o::helpers::set_cpu_affinity (6 samples, 0.02%)nix::sched::sched_linux_like::sched_setaffinity (6 samples, 0.02%)__GI___sched_setaffinity_new (6 samples, 0.02%)entry_SYSCALL_64_after_hwframe (6 samples, 0.02%)do_syscall_64 (6 samples, 0.02%)__x64_sys_sched_setaffinity (6 samples, 0.02%)sched_setaffinity (6 samples, 0.02%)cpuset_cpus_allowed (6 samples, 0.02%)_raw_spin_lock_irqsave (6 samples, 0.02%)put_cpu_partial (3 samples, 0.01%)unfreeze_partials (3 samples, 0.01%)kfree (8 samples, 0.03%)asm_sysvec_call_function (4 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__list_add_valid (3 samples, 0.01%)__free_one_page (34 samples, 0.13%)__list_del_entry_valid (6 samples, 0.02%)__consume_stateless_skb (112 samples, 0.41%)skb_release_data (104 samples, 0.39%)free_unref_page (78 samples, 0.29%)free_pcppages_bulk (64 samples, 0.24%)_raw_spin_lock (21 samples, 0.08%)native_queued_spin_lock_slowpath (21 samples, 0.08%)__skb_recv_udp (7 samples, 0.03%)flush_tlb_func_common.constprop.0 (4 samples, 0.01%)flush_smp_call_function_queue (12 samples, 0.04%)llist_reverse_order (4 samples, 0.01%)_copy_to_iter (193 samples, 0.71%)copy_user_generic_string (186 samples, 0.69%)asm_sysvec_call_function (19 samples, 0.07%)sysvec_call_function (14 samples, 0.05%)asm_call_sysvec_on_stack (14 samples, 0.05%)__sysvec_call_function (14 samples, 0.05%)asm_sysvec_call_function (3 samples, 0.01%)sysvec_call_function (3 samples, 0.01%)asm_call_sysvec_on_stack (3 samples, 0.01%)__sysvec_call_function (3 samples, 0.01%)flush_smp_call_function_queue (3 samples, 0.01%)__virt_addr_valid (5 samples, 0.02%)inet_recvmsg (444 samples, 1.64%)udp_recvmsg (443 samples, 1.64%)skb_copy_datagram_iter (304 samples, 1.13%)__skb_datagram_iter (302 samples, 1.12%)simple_copy_to_iter (78 samples, 0.29%)__check_object_size (78 samples, 0.29%)asm_sysvec_call_function (8 samples, 0.03%)sysvec_call_function (5 samples, 0.02%)asm_call_sysvec_on_stack (5 samples, 0.02%)__sysvec_call_function (5 samples, 0.02%)flush_smp_call_function_queue (5 samples, 0.02%)__libc_recvfrom (451 samples, 1.67%)entry_SYSCALL_64_after_hwframe (447 samples, 1.66%)do_syscall_64 (447 samples, 1.66%)__x64_sys_recvfrom (446 samples, 1.65%)__sys_recvfrom (446 samples, 1.65%)main::recv_decode_loop (1,939 samples, 7.18%)main::recv..std::net::udp::UdpSocket::recv_from (454 samples, 1.68%)std::sys_common::net::UdpSocket::recv_from (454 samples, 1.68%)std::sys::unix::net::Socket::recv_from (454 samples, 1.68%)std::sys::unix::net::Socket::recv_from_with_flags (454 samples, 1.68%)[unknown] (1,945 samples, 7.20%)[unknown]std::sys::unix::net::Socket::recv_from_with_flags (6 samples, 0.02%)__libc_recvfrom (6 samples, 0.02%)entry_SYSCALL_64 (5 samples, 0.02%)all (27,001 samples, 100%)recv-decode-7 (1,947 samples, 7.21%)recv-decod.. \ No newline at end of file diff --git a/k2o/rust-toolchain.toml b/k2o/rust-toolchain.toml new file mode 100644 index 00000000..292fe499 --- /dev/null +++ b/k2o/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" diff --git a/k2o/rustfmt.toml b/k2o/rustfmt.toml new file mode 100644 index 00000000..e69de29b diff --git a/k2o/src/acquisition.rs b/k2o/src/acquisition.rs new file mode 100644 index 00000000..d9e5aa91 --- /dev/null +++ b/k2o/src/acquisition.rs @@ -0,0 +1,563 @@ +use std::{ + collections::HashSet, + time::{Duration, Instant}, +}; + +use common::{background_thread::AcquisitionSize, tracing::get_tracer}; +use crossbeam::channel::{Receiver, RecvError, Select, SelectedOperation, Sender}; +use human_bytes::human_bytes; +use ipc_test::SharedSlabAllocator; +use log::{error, info, warn}; +use opentelemetry::{ + trace::{self, Span, TraceContextExt, Tracer}, + Context, Key, +}; +use partialdebug::placeholder::PartialDebug; + +use crate::{ + assemble::AssemblyResult, + control::AcquisitionState, + events::{AcquisitionParams, EventBus, EventMsg, EventReceiver, Events}, + frame::{FrameMeta, GenericFrame, K2Frame}, + ordering::{FrameOrdering, FrameOrderingResult, FrameWithIdx}, +}; + +const PRE_ALLOC_CHUNKS: usize = 400; // pre-allocate chunks of this number of frames + +enum HandleFramesResult { + Done { dropped: usize }, + Aborted { dropped: usize }, + Shutdown, +} + +#[derive(PartialDebug)] +pub enum AcquisitionResult { + Frame(F, u32), + DroppedFrame(F, u32), + DroppedFrameOutside(F), + DoneSuccess { + dropped: usize, + acquisition_id: usize, + }, + DoneAborted { + dropped: usize, + acquisition_id: usize, + }, + + /// This is the result if some threads upstream closed their end of the + /// channel and we get a receive error, while an acquisition is running - + /// the system is probably shutting down (or crashing). + DoneShuttingDown { + acquisition_id: usize, + }, + + /// This is the result if some threads upstream closed their end of the + /// channel while no current acquisition is known + ShutdownIdle, +} + +impl AcquisitionResult { + pub fn unpack(self) -> Option { + match self { + AcquisitionResult::Frame(f, _) => Some(f), + AcquisitionResult::DroppedFrame(f, _) => Some(f), + AcquisitionResult::DroppedFrameOutside(f) => Some(f), + AcquisitionResult::DoneSuccess { + dropped: _, + acquisition_id: _, + } => None, + AcquisitionResult::DoneAborted { + dropped: _, + acquisition_id: _, + } => None, + AcquisitionResult::DoneShuttingDown { acquisition_id: _ } => None, + AcquisitionResult::ShutdownIdle => None, + } + } + + pub fn get_frame(&self) -> Option<&F> { + match self { + AcquisitionResult::Frame(f, _) => Some(f), + AcquisitionResult::DroppedFrame(f, _) => Some(f), + AcquisitionResult::DroppedFrameOutside(f) => Some(f), + AcquisitionResult::DoneSuccess { + dropped: _, + acquisition_id: _, + } => None, + AcquisitionResult::DoneAborted { + dropped: _, + acquisition_id: _, + } => None, + AcquisitionResult::DoneShuttingDown { acquisition_id: _ } => None, + AcquisitionResult::ShutdownIdle => None, + } + } +} + +pub fn frame_in_acquisition( + frame_id: u32, + ref_frame_id: u32, + params: &AcquisitionParams, +) -> Option { + let frame_idx_raw: i64 = frame_id as i64 - ref_frame_id as i64; + let upper_limit = match params.size { + AcquisitionSize::Continuous => u32::MAX, + AcquisitionSize::NumFrames(n) => n.try_into().expect("too many frames in acquisition size"), + AcquisitionSize::Auto => u32::MAX, // FIXME: is this the correct default? + }; + if frame_idx_raw >= 0 && frame_idx_raw < upper_limit as i64 { + Some(frame_idx_raw as u32) + } else { + None + } +} + +/// Take `result` and either directly send it on to the `next_hop_tx` channel, +/// or buffer it in `ordering`. +fn next_hop_ordered( + ordering: &mut FrameOrdering, + next_hop_tx: &Sender>, + result: FrameWithIdx, +) { + match ordering.handle_frame(result) { + FrameOrderingResult::Dropped => {} + FrameOrderingResult::Buffered => {} + FrameOrderingResult::NextFrame(result) => { + let result: AcquisitionResult = result.into(); + next_hop_tx.send(result).unwrap(); + } + } + + // possibly send out buffered frames: + while let Some(buffered_result) = ordering.maybe_get_next_frame() { + let buffered_result: AcquisitionResult = buffered_result.into(); + next_hop_tx.send(buffered_result).unwrap(); + } +} + +// TODO: maybe need a drain state which we enter in case of errors, to get +// rid of frames in the pipeline that belong to a canceled acquisition or we could add +// an "acquisition generation" as metadata to the messages, so we can safely +// discard frames that don't belong to whatever acquisition we think we are +// currently working on + +struct FrameHandler<'a, F: K2Frame> { + acquisition_id: usize, + + channel: &'a Receiver>, + next_hop_tx: &'a Sender>, + events_rx: &'a EventReceiver, + shm: &'a mut SharedSlabAllocator, + params: AcquisitionParams, + ref_frame_id: u32, + ordering: FrameOrdering, + + counter: usize, + dropped: usize, + dropped_outside: usize, + dropped_frame_ids: HashSet, + + ref_ts: Instant, + ref_bytes_written: usize, +} + +impl<'a, F: K2Frame> FrameHandler<'a, F> { + #[allow(clippy::too_many_arguments)] + fn new( + acquisition_id: usize, + channel: &'a Receiver>, + next_hop_tx: &'a Sender>, + events_rx: &'a EventReceiver, + shm: &'a mut SharedSlabAllocator, + params: AcquisitionParams, + ref_frame_id: u32, + ) -> Self { + FrameHandler { + acquisition_id, + channel, + next_hop_tx, + events_rx, + shm, + params, + ref_frame_id, + ordering: FrameOrdering::new(0), + counter: 0, + dropped: 0, + dropped_outside: 0, + dropped_frame_ids: HashSet::new(), + ref_ts: Instant::now(), + ref_bytes_written: 0, + } + } + + #[must_use] + fn handle_frames(mut self) -> HandleFramesResult { + let tracer = get_tracer(); + let mut span = tracer.start("handle_frames"); + span.add_event( + "start", + vec![Key::new("ref_frame_id").i64(self.ref_frame_id as i64)], + ); + let _guard = trace::mark_span_as_active(span); + let mut sel = Select::new(); + let op_events = sel.recv(self.events_rx); + let op_frames = sel.recv(self.channel); + + let frame_shape = F::get_shape_for_binning(&self.params.binning); + let pixel_size_bytes = F::get_pixel_size_bytes(); + + loop { + let oper = sel.select(); + match oper.index() { + i if i == op_events => match oper.recv(self.events_rx) { + Ok(EventMsg::Shutdown {}) => return HandleFramesResult::Shutdown, + Ok(EventMsg::CancelAcquisition { acquisition_id: _ }) => { + return HandleFramesResult::Aborted { + dropped: self.dropped, + } + } + Ok(_) => continue, + Err(RecvError) => { + return HandleFramesResult::Shutdown; + } + }, + i if i == op_frames => { + // FIXME: if we are in `AcquisitionSync::Immediately` mode, + // we need to handle wrap-around (or reset) of frame IDs gracefully. + // so 1) we need to detect the wrap-around, and 2) generate a derived + // frame index, which takes this wrap around into account. We may need + // to keep a "generation" counter, which is incremented for each + // wrap-around or reset. Note that frames may be retired from the + // pipeline out-of-order, which the logic needs to account for. + match self.handle_frame(oper) { + Some(result) => return result, + None => continue, + } + } + _ => unreachable!(), + } + } + } + + #[must_use] + fn handle_frame(&mut self, oper: SelectedOperation) -> Option { + let cx = Context::current(); + let span = cx.span(); + + match oper.recv(self.channel) { + Ok(AssemblyResult::AssembledFrame(frame)) => { + let frame_id = frame.get_frame_id(); + span.add_event( + "handle_assembled_frame", + vec![Key::new("frame_id").i64(frame_id as i64)], + ); + if frame.get_acquisition_id() == self.acquisition_id { + self.handle_assembled_frame(frame) + } else { + warn!("dropped assembled frame from unrelated acquisition"); + frame.free_payload(self.shm); + None + } + } + Ok(AssemblyResult::AssemblyTimeout { frame, frame_id }) => { + span.add_event("timeout", vec![Key::new("frame_id").i64(frame_id as i64)]); + let frame_meta = frame.get_meta(); + if frame.get_acquisition_id() == self.acquisition_id { + self.timeout(frame_id, frame); + } else { + warn!("dropped frame from unrelated acquisition"); + frame.free_payload(self.shm); + } + + // handle the case that the last frame was dropped: + if let AcquisitionSize::NumFrames(num) = self.params.size { + if self.counter == num as usize { + if self.counter % 100 != 0 { + self.print_stats(&frame_meta); + } + return Some(HandleFramesResult::Done { + dropped: self.dropped, + }); + } + } + None + } + Err(RecvError) => Some(HandleFramesResult::Shutdown), + } + } + + #[must_use] + fn handle_assembled_frame(&mut self, frame: F) -> Option { + let frame_idx_raw: i64 = frame.get_frame_id() as i64 - self.ref_frame_id as i64; + let upper_limit = match self.params.size { + AcquisitionSize::Continuous => u32::MAX, + AcquisitionSize::NumFrames(n) => { + n.try_into().expect("too many frames in acqusition size") + } + AcquisitionSize::Auto => u32::MAX, + }; + if frame_idx_raw >= 0 && (frame_idx_raw as usize) % PRE_ALLOC_CHUNKS == 0 { + // pre-allocate in chunks of PRE_ALLOC_CHUNKS frames + let new_size = core::cmp::min(upper_limit as usize, self.counter + PRE_ALLOC_CHUNKS); + } + if let Some(frame_idx) = + frame_in_acquisition(frame.get_frame_id(), self.ref_frame_id, &self.params) + { + let out_frame_idx_base = frame_idx * F::get_num_subframes(&self.params.binning); + let frame_shape = F::get_shape_for_binning(&self.params.binning); + let pixel_size_bytes = F::get_pixel_size_bytes(); + let frame_size_bytes = frame_shape.0 * frame_shape.1 * pixel_size_bytes; + for subframe_idx in frame.subframe_indexes(&self.params.binning) { + let subframe = frame.get_subframe(subframe_idx, &self.params.binning, self.shm); + // writer.write_frame(&subframe, out_frame_idx_base + subframe_idx); + self.ref_bytes_written += frame_size_bytes; + self.counter += 1; + } + let frame_meta = frame.get_meta(); + if self.counter % 100 == 0 { + self.print_stats(&frame_meta); + } + if let AcquisitionSize::NumFrames(num) = self.params.size { + // FIXME: NumFrames should always be a + // multiple of the number of subframes, + // otherwise this check can fail! + if self.counter == num as usize { + if self.counter % 100 != 0 { + self.print_stats(&frame_meta); + } + let result = FrameWithIdx::Frame(frame.into_generic(), frame_idx); + next_hop_ordered(&mut self.ordering, self.next_hop_tx, result); + self.ordering.dump_if_nonempty(); + if !self.ordering.is_empty() { + info!("self.counter = {}, num = {}", self.counter, num); + } + assert!(self.ordering.is_empty()); + return Some(HandleFramesResult::Done { + dropped: self.dropped, + }); + } + } + let result = FrameWithIdx::Frame(frame.into_generic(), frame_idx); + next_hop_ordered(&mut self.ordering, self.next_hop_tx, result); + None + } else { + self.dropped_outside += 1; + frame.free_payload(self.shm); + None + } + } + + fn timeout(&mut self, frame_id: u32, frame: F) { + let ctx = Context::current(); + if let Some(frame_idx) = frame_in_acquisition(frame_id, self.ref_frame_id, &self.params) { + ctx.span().add_event( + "timeout_in_acquisition", + vec![Key::new("frame_id").i64(frame_id as i64)], + ); + self.dropped += 1; + // only increment the counter if we haven't seen this frame ID before: + if self.dropped_frame_ids.insert(frame.get_frame_id()) { + self.counter += 1; // FIXME: might need to increment by number of subframes? + } + let result = FrameWithIdx::DroppedFrame(frame.into_generic(), frame_idx); + next_hop_ordered(&mut self.ordering, self.next_hop_tx, result); + } else { + ctx.span().add_event( + "timeout_outside_acquisition", + vec![Key::new("frame_id").i64(frame_id as i64)], + ); + self.dropped_outside += 1; + frame.free_payload(self.shm); + } + } + + fn print_stats(&mut self, frame_meta: &FrameMeta) { + let now = Instant::now(); + let latency = frame_meta.get_created_timestamp().elapsed(); + let channel_size = self.channel.len(); + let delta_t = now - self.ref_ts; + let throughput = { + if delta_t > Duration::ZERO { + let bytes_per_second = self.ref_bytes_written as f64 / delta_t.as_secs_f64(); + human_bytes(bytes_per_second) + } else { + String::from("") + } + }; + let fps = { + if delta_t > Duration::ZERO { + format!("{}", 100.0 / delta_t.as_secs_f64()) + } else { + String::from("") + } + }; + info!("acq#{} frame counter={} frame_id={} dropped={} dropped_outside={}, latency first block -> frame written={:?} channel.len()={} write throughput={}/s fps={}", + frame_meta.get_acquisition_id(), self.counter, frame_meta.get_frame_id(), + self.dropped, self.dropped_outside, latency, channel_size, + throughput, fps + ); + + self.ref_ts = Instant::now(); + self.ref_bytes_written = 0; + } +} + +/// +/// Instantiate a writer, receive and write N frames, and forward frames +/// to the next hop channel. This is started in a background thread. +/// +/// Filters out frames that don't belong to the current acquisition. +/// + +pub fn acquisition_loop( + channel: &Receiver>, + next_hop_tx: &Sender>, + events_rx: &EventReceiver, + events: &Events, + mut shm: SharedSlabAllocator, +) { + let tracer = get_tracer(); + + tracer.in_span("acquisition_loop", |cx| { + let span = cx.span(); + + let mut state: AcquisitionState = AcquisitionState::default(); + + let mut sel = Select::new(); + let op_events = sel.recv(events_rx); + let op_frames = sel.recv(channel); + + loop { + let oper = sel.select(); + match oper.index() { + i if i == op_events => { + let msg_result = oper.recv(events_rx); + match msg_result { + Ok(EventMsg::Arm { params, acquisition_id }) => { + state = AcquisitionState::Armed { + params: params.clone(), + acquisition_id, + }; + + // Forward the start event for sectors, making sure we get the + // `AcquisitionStartedSector` event only after we are in `Armed` state. + // If instead the sectors would react to `StartAcquisition` like + // we do here, we could possibly get the response from the + // sectors before we are transitioning to the `Armed` state, + // meaning we don't have the acquisition parameters yet etc... + events.send(&EventMsg::ArmSectors { params, acquisition_id}); + } + Ok(EventMsg::AcquisitionStartedSector { + sector_id: _, + frame_id, + acquisition_id: acquisition_id_outer, + }) => { + match state { + AcquisitionState::Armed { params , acquisition_id } => { + if acquisition_id != acquisition_id_outer { + error!("acquisition id mismatch; {acquisition_id} != {acquisition_id_outer}"); + } + state = AcquisitionState::AcquisitionStarted { + params: params.clone(), + frame_id, + acquisition_id, + }; + events.send(&EventMsg::AcquisitionStarted { + frame_id, + params: params.clone(), + acquisition_id, + }); + info!("acquisition started, first frame_id = {}", frame_id); + + Context::current() + .span() + .add_event("AcquisitionStarted", vec![]); + let fh = FrameHandler::new( + acquisition_id, + channel, + next_hop_tx, + events_rx, + &mut shm, + params, + frame_id, + ); + let write_result = fh.handle_frames(); + info!("handle_frames done."); + events.send(&EventMsg::AcquisitionEnded { acquisition_id }); + Context::current() + .span() + .add_event("AcquisitionEnded", vec![]); + match write_result { + HandleFramesResult::Done { dropped } => { + next_hop_tx + .send(AcquisitionResult::DoneSuccess { dropped, acquisition_id }) + .unwrap(); + continue; + } + HandleFramesResult::Aborted { dropped } => { + next_hop_tx + .send(AcquisitionResult::DoneAborted { dropped, acquisition_id }) + .unwrap(); + continue; + } + HandleFramesResult::Shutdown => { + next_hop_tx.send(AcquisitionResult::DoneShuttingDown { acquisition_id }).unwrap(); + break; + } + } + } + AcquisitionState::AcquisitionStarted { + params: _, + frame_id: _, + acquisition_id, + } => { + // we are only interested in the event from the first sector that starts the acquisition: + warn!( + "ignoring AcuisitionStartedSector in AcquisitionStarted state for acq#{acquisition_id}" + ); + } + AcquisitionState::Idle + | AcquisitionState::AcquisitionFinishing { params: _, frame_id: _, acquisition_id: _ } + | AcquisitionState::Startup + | AcquisitionState::Shutdown => { + panic!( + "AcquisitionStartedSector received in invalid state {state:?}" + ); + } + } + } + Ok(EventMsg::Shutdown {}) => break, + Ok(_) => continue, + Err(RecvError) => { + next_hop_tx.send(AcquisitionResult::ShutdownIdle).unwrap(); + break; + } + } + } + i if i == op_frames => { + match oper.recv(channel) { + Ok(AssemblyResult::AssembledFrame(frame)) => { + let frame_id = frame.get_frame_id(); + frame.free_payload(&mut shm); + span.add_event("DroppedFrameOutside", vec![ + Key::new("frame_id").i64(frame_id as i64), + ]); + } + Ok(AssemblyResult::AssemblyTimeout { frame, frame_id: _ }) => { + // timeout outside of an acquisition - not so interesting + // to count this as an event + let frame_id = frame.get_frame_id(); + frame.free_payload(&mut shm); + span.add_event("AssemblyTimeout", vec![ + Key::new("frame_id").i64(frame_id as i64), + ]); + continue; + } + Err(RecvError) => break, + } + } + _ => unreachable!(), + } + } + }); +} diff --git a/k2o/src/assemble.rs b/k2o/src/assemble.rs new file mode 100644 index 00000000..42fd7061 --- /dev/null +++ b/k2o/src/assemble.rs @@ -0,0 +1,472 @@ +use std::{ + collections::HashMap, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::{Duration, Instant}, +}; + +use crossbeam::channel::{unbounded, Receiver, RecvTimeoutError, SendError, Sender}; +use ipc_test::SharedSlabAllocator; +use log::{debug, error, info, warn}; +use opentelemetry::Context; + +use crate::{ + block::{BlockRouteInfo, K2Block}, + events::{EventMsg, EventReceiver}, + frame::{FrameForWriting, K2Frame}, + helpers::{make_realtime, set_cpu_affinity, CPU_AFF_ASSEMBLY}, +}; + +pub struct PendingFrames { + pub frames: HashMap, + timeout: Duration, +} + +impl PendingFrames { + pub fn new(timeout: Duration) -> Self { + PendingFrames { + frames: HashMap::new(), + timeout, + } + } + + pub fn assign_block(&mut self, block: &B, shm: &mut SharedSlabAllocator) { + let frame = match self.frames.get_mut(&block.get_frame_id()) { + None => { + let frame = + F::FrameForWriting::empty_from_block(block, shm, block.get_acquisition_id()); + self.frames.insert(block.get_frame_id(), frame); + self.frames.get_mut(&block.get_frame_id()).unwrap() + } + Some(frame) => frame, + }; + // in case we have an existing frame, the acquisition id must match + // (which is always the case if we allocate a new FrameForWriting): + if frame.get_acquisition_id() != block.get_acquisition_id() { + debug!( + "dropping block; block acquisition id {} != frame acquisition id {} (frame id {})", + block.get_acquisition_id(), + frame.get_acquisition_id(), + frame.get_frame_id(), + ); + // the block is from a different acquisition, drop it. + return; + } + frame.assign_block(block); + } + + /// call a callback function `cb` on finished frames and remove from list of pending frames + /// as we keep the finished data around by default, it's possible to call this function + /// only for every N received blocks, or only if a certain time has passed, without losing + /// data (possibly small performance loss because of data locality, if you wait for too long) + pub fn retire_finished Result<(), E>>( + &mut self, + shm: &mut SharedSlabAllocator, + cb: CB, + ) -> Result<(), E> { + let mut to_remove: Vec = Vec::with_capacity(16); + + for (_, frame) in self.frames.iter() { + if frame.is_finished() { + to_remove.push(frame.get_frame_id()); + } + } + + for frame_id in to_remove { + let frame_for_writing = self.frames.remove(&frame_id).unwrap(); + let frame = frame_for_writing.writing_done(shm); + cb(frame, shm)?; + } + + Ok(()) + } + + pub fn retire_timed_out Result<(), E>>( + &mut self, + shm: &mut SharedSlabAllocator, + cb: CB, + ) -> Result<(), E> { + let mut to_remove: Vec = Vec::with_capacity(16); + let now = Instant::now(); + + for (_, frame) in self.frames.iter() { + let delta = now - frame.get_modified_timestamp(); + if !frame.is_finished() && delta > self.timeout { + let tracker = frame.get_tracker(); + let num_missing = tracker.iter().filter(|have_block| !**have_block).count(); + warn!( + "dropping frame {}, num_missing: {:?} of {}", + frame.get_frame_id(), + num_missing, + tracker.len() + ); + to_remove.push(frame.get_frame_id()); + } + } + + for frame_id in to_remove { + let frame_for_writing = self.frames.remove(&frame_id).unwrap(); + let frame = frame_for_writing.writing_done(shm); + cb(frame)?; + } + + Ok(()) + } + + pub fn num_finished(&self) -> usize { + return self + .frames + .iter() + .filter(|(_, frame)| frame.is_finished()) + .count(); + } + + pub fn num_unfinished(&self) -> usize { + return self + .frames + .iter() + .filter(|(_, frame)| !frame.is_finished()) + .count(); + } +} + +#[derive(Debug)] +enum AssemblyError { + Disconnected, +} + +pub enum AssemblyResult { + AssembledFrame(F), + AssemblyTimeout { frame: F, frame_id: u32 }, +} + +fn assembly_worker( + blocks_rx: Receiver, + frames_tx: Sender>, + recycle_blocks_tx: &Sender, + stop_event: Arc, + handle_path: &str, + timeout: &Duration, + realtime: bool, +) -> Result<(), AssemblyError> { + let mut pending: PendingFrames = PendingFrames::new(*timeout); + let mut shm = SharedSlabAllocator::connect(handle_path).expect("connect to SHM"); + + if realtime { + match make_realtime(5) { + Ok(prio) => info!("successfully enabled realtime priority {prio}"), + Err(e) => error!("failed to set realtime priority: {e:?}"), + } + } + + loop { + match blocks_rx.recv_timeout(Duration::from_millis(100)) { + Ok(block) => { + pending.assign_block(&block, &mut shm); + recycle_blocks_tx.send(block).unwrap(); + } + Err(RecvTimeoutError::Timeout) => { + if stop_event.load(Ordering::Relaxed) { + // FIXME: do we need to do anything with accumulated data? + break; + } + } + Err(RecvTimeoutError::Disconnected) => { + // the other end has gone away, so we can quit, too. + break; + } + } + + pending.retire_finished(&mut shm, |frame, _| { + if let Err(SendError(_)) = frames_tx.send(AssemblyResult::AssembledFrame(frame)) { + // can't retire frames if the other end is disconnected, so we die, too: + return Err(AssemblyError::Disconnected); + } + Ok(()) + })?; + + pending.retire_timed_out(&mut shm, |frame: F| { + let frame_id = frame.get_frame_id(); + if let Err(SendError(_)) = + frames_tx.send(AssemblyResult::AssemblyTimeout { frame, frame_id }) + { + // can't handle timed out frames if the other end is disconnected, so we die, too: + return Err(AssemblyError::Disconnected); + } + Ok(()) + })?; + } + + Ok(()) +} + +pub fn assembler_main( + blocks_rx: &Receiver<(B, BlockRouteInfo)>, + frames_tx: &Sender>, + recycle_blocks_tx: &Sender, + events_rx: EventReceiver, + shm: SharedSlabAllocator, + timeout: &Duration, + realtime: bool, +) { + let pool_size = 5; + let mut worker_channels: Vec> = Vec::with_capacity(pool_size); + + let stop_event = Arc::new(AtomicBool::new(false)); + + let ctx = Context::current(); + + // warmup for the block queue: + for _ in 0..2048 { + recycle_blocks_tx.send(B::empty(0, 0)).unwrap(); + } + + if realtime { + match make_realtime(5) { + Ok(prio) => info!("successfully enabled realtime priority {prio}"), + Err(e) => error!("failed to set realtime priority: {e:?}"), + } + } + + crossbeam::scope(|s| { + for idx in 0..pool_size { + let asm_worker_ctx = ctx.clone(); + let (tx, rx) = unbounded::(); + + let this_stop_event = Arc::clone(&stop_event); + + let shm_handle = shm.get_handle(); + + s.builder() + .name(format!("asm-frame-{idx}")) + .spawn(move |_| { + asm_worker_ctx.attach(); + set_cpu_affinity(CPU_AFF_ASSEMBLY + idx); + if assembly_worker::( + rx.clone(), + frames_tx.clone(), + &recycle_blocks_tx.clone(), + this_stop_event, + &shm_handle.os_handle, + timeout, + realtime, + ) + .is_err() + { + warn!("disconnect in asm-frame"); + } + }) + .expect("could not spawn asm-frame"); + worker_channels.push(tx); + } + + loop { + match blocks_rx.recv_timeout(Duration::from_millis(100)) { + Ok((block, block_route)) => { + let frame_id = block_route.get_frame_id(); + let chan = worker_channels[(frame_id as usize) % pool_size].clone(); + if chan.send(block).is_err() { + error!("assembly thread died, stopping"); + stop_event.store(true, Ordering::Relaxed); + break; + } + } + Err(RecvTimeoutError::Disconnected) => { + stop_event.store(true, Ordering::Relaxed); + break; + } + // FIXME: might want to be a bit more eager here to make shutdown faster: + Err(RecvTimeoutError::Timeout) => { + if let Ok(msg) = events_rx.try_recv() { + if msg == (EventMsg::Shutdown {}) { + stop_event.store(true, Ordering::Relaxed); + break; + } + } + } + } + } + }) + .unwrap(); +} + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use ipc_test::SharedSlabAllocator; + use ndarray::s; + use ndarray::ArrayView; + use tempfile::tempdir; + + use crate::assemble::PendingFrames; + use crate::block::K2Block; + use crate::block_is::K2ISBlock; + use crate::decode::HEADER_SIZE; + use crate::events::Binning; + use crate::frame::FrameForWriting; + use crate::frame_is::K2ISFrame; + use crate::frame_is::K2ISFrameForWriting; + + use super::K2Frame; + + const PACKET_SIZE: usize = 0x5758; + const DECODED_SIZE: usize = (PACKET_SIZE - HEADER_SIZE) * 2 / 3; + + fn make_test_data() -> Vec { + let mut original_values: Vec = Vec::new(); + original_values.extend((0u16..=0xFFF).cycle().take(DECODED_SIZE)); + original_values + } + + #[test] + fn k2frame_assign_blocks_happy_case() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("stuff.socket"); + + const FRAME_ID: u32 = 42; + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + let mut frame: K2ISFrameForWriting = K2ISFrameForWriting::empty(FRAME_ID, &mut ssa, 0); + + assert!(!frame.is_finished()); + + let payload = &make_test_data(); + let payload_view = ArrayView::from_shape((930, 16), &payload[..]).unwrap(); + + for y_idx in 0..2 { + for x_idx in 0..128 { + let start_x = x_idx * 16; + let start_y = y_idx * 930; + + let block: K2ISBlock = + K2ISBlock::from_vec_and_pos(payload, start_x, start_y, FRAME_ID, 0); + frame.assign_block(&block); + } + } + + frame.dump_finished_state(); + + assert!(frame.is_finished()); + + let frame_arr = frame.as_array(); + + // all slices contain the test data pattern: + for y_idx in 0..2 { + for x_idx in 0..128 { + let start_x = x_idx * 16; + let start_y = y_idx * 930; + + let slice: ndarray::ArrayBase, ndarray::Dim<[usize; 2]>> = + frame_arr.slice(s![start_y..start_y + 930, start_x..start_x + 16]); + assert!(payload_view.abs_diff_eq(&slice, 0)); + + println!("{payload_view}"); + } + } + } + + #[test] + fn pending_frames_assign_blocks_happy_case() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("stuff.socket"); + + const FRAME_ID: u32 = 42; + let mut pending_frames: PendingFrames = + PendingFrames::new(Duration::from_millis(100)); + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + assert_eq!(pending_frames.num_finished(), 0); + assert_eq!(pending_frames.num_unfinished(), 0); + + let payload = &make_test_data(); + let payload_view = ArrayView::from_shape((930, 16), &payload[..]).unwrap(); + + for y_idx in 0..2 { + for x_idx in 0..128 { + let start_x = x_idx * 16; + let start_y = y_idx * 930; + + let block: K2ISBlock = + K2ISBlock::from_vec_and_pos(payload, start_x, start_y, FRAME_ID, 0); + pending_frames.assign_block(&block, &mut ssa); + } + } + + assert_eq!(pending_frames.num_finished(), 1); + assert_eq!(pending_frames.num_unfinished(), 0); + + pending_frames + .retire_finished(&mut ssa, |frame, ssa| { + let subframe = frame.get_subframe(0, &Binning::Bin1x, ssa); + subframe.apply_to_payload_array(|frame_arr| { + // all slices contain the test data pattern: + for y_idx in 0..2 { + for x_idx in 0..128 { + let start_x = x_idx * 16; + let start_y = y_idx * 930; + let slice = + frame_arr.slice(s![start_y..start_y + 930, start_x..start_x + 16]); + assert!(payload_view.abs_diff_eq(&slice, 0)); + println!("{payload_view}"); + } + } + }); + + Ok::<_, ()>(()) + }) + .unwrap(); + } + + #[test] + fn assemly_single_block() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("stuff.socket"); + + const FRAME_ID: u32 = 42; + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + let mut pending_frames: PendingFrames = + PendingFrames::new(Duration::from_millis(100)); + + assert_eq!(pending_frames.num_finished(), 0); + assert_eq!(pending_frames.num_unfinished(), 0); + + let payload = &make_test_data(); + + let start_x = 2032; + let start_y = 930; + + let block: K2ISBlock = K2ISBlock::from_vec_and_pos(payload, start_x, start_y, FRAME_ID, 0); + assert_eq!(block.get_x_end(), 2047); + assert_eq!(block.get_y_end(), 1859); + pending_frames.assign_block(&block, &mut ssa); + + assert_eq!(pending_frames.num_finished(), 0); + assert_eq!(pending_frames.num_unfinished(), 1); + + pending_frames + .retire_finished(&mut ssa, |_, _| -> Result<(), ()> { + panic!("this should not be called, as we don't have any finished frames yet"); + }) + .unwrap(); + } +} diff --git a/k2o/src/bin/decode_only.rs b/k2o/src/bin/decode_only.rs new file mode 100644 index 00000000..4729b75f --- /dev/null +++ b/k2o/src/bin/decode_only.rs @@ -0,0 +1,12 @@ +use k2o::decode::decode_unrolled; +use k2o::decode::HEADER_SIZE; + +fn main() { + const PACKET_SIZE: usize = 0x5758; + const DECODED_SIZE: usize = (PACKET_SIZE - HEADER_SIZE) * 2 / 3; + let input: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let mut out: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + for _ in 0..32 * 400 * 8 * 4 * 2 { + decode_unrolled::(&input, &mut out); + } +} diff --git a/k2o/src/bin/main.rs b/k2o/src/bin/main.rs new file mode 100644 index 00000000..ce22e825 --- /dev/null +++ b/k2o/src/bin/main.rs @@ -0,0 +1,237 @@ +extern crate crossbeam; +extern crate jemallocator; + +use std::path::Path; +use std::time::Duration; + +use clap::Parser; +use common::background_thread::AcquisitionSize; +use common::tracing::tracing_from_env; +use crossbeam::channel::{unbounded, RecvTimeoutError}; +use ipc_test::SharedSlabAllocator; +use k2o::acquisition::{acquisition_loop, AcquisitionResult}; +use k2o::assemble::{assembler_main, AssemblyResult}; +use k2o::block::BlockRouteInfo; +use k2o::block::K2Block; +use k2o::block_is::K2ISBlock; +use k2o::block_summit::K2SummitBlock; +use k2o::cli_args::{Args, Mode}; +use k2o::control::control_loop; +use k2o::events::{AcquisitionParams, AcquisitionSync, Events, MessagePump}; +use k2o::events::{ChannelEventBus, EventBus, EventMsg}; +use k2o::frame::K2Frame; +use k2o::frame_is::K2ISFrame; +use k2o::frame_summit::K2SummitFrame; +use k2o::helpers::CPU_AFF_WRITER; +use k2o::helpers::{recv_and_get_init, set_cpu_affinity}; +use k2o::recv::{recv_decode_loop, RecvConfig}; +use log::info; + +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + +fn start_threads< + const PACKET_SIZE: usize, // FIXME: use B::PACKET_SIZE instead + F: K2Frame, + B: K2Block, +>( + args: &Args, + events: &Events, + pump: &Option, +) { + let ids = 0..=7u8; + + let (recycle_blocks_tx, recycle_blocks_rx) = unbounded::(); + + // make sure this is created before the other threads are started, so we don't + // miss any events! + let shm_path = Path::new(&args.shm_path); + let slot_size: usize = F::get_size_bytes(); + + info!("Initializing shared memory..."); + let shm = SharedSlabAllocator::new(1000, slot_size, true, shm_path).expect("create shm"); + info!("Shared memory initialized."); + + crossbeam::scope(|s| { + let (assembly_tx, assembly_rx) = unbounded::<(B, BlockRouteInfo)>(); + for sector_id in ids { + let port: u32 = 2001 + (sector_id as u32); + let tx = assembly_tx.clone(); + let recycle_clone_rx = recycle_blocks_rx.clone(); + let recycle_clone_tx = recycle_blocks_tx.clone(); + let events_rx = events.subscribe(); + let local_addr = if sector_id < 4 { + "192.168.10.99" + } else { + "192.168.10.98" + } + .to_string(); + + s.builder() + .name(format!("recv-decode-{}", sector_id)) + .spawn(move |_| { + recv_decode_loop::( + sector_id, + port, + &tx, + &recycle_clone_rx, + &recycle_clone_tx, + &events_rx, + events, + local_addr, + None, + &RecvConfig::new(true), + ); + }) + .expect("could not spawn recv+decode thread"); + } + + let (full_frames_tx, full_frames_rx) = unbounded::>(); + let (recycle_frames_tx, recycle_frames_rx) = unbounded(); + + let asm_events_rx = events.subscribe(); + let shm_handle = shm.get_handle().os_handle; + + // assembly main thread: + s.builder() + .name("assembly".to_string()) + .spawn({ + let shm_handle = shm_handle.clone(); + move |_| { + //set_cpu_affinity(CPU_AFF_ASSEMBLY); + //frame_assembler(&assembly_rx, &full_frames_tx); + let asm_shm = SharedSlabAllocator::connect(&shm_handle).unwrap(); + + assembler_main( + &assembly_rx, + &full_frames_tx, + &recycle_blocks_tx, + asm_events_rx, + asm_shm, + &Duration::from_millis(100), + true, + ); + } + }) + .expect("could not spawn assembly thread"); + + // writer thread(s): + let w1rx = full_frames_rx; + let writer_events_rx = events.subscribe(); + s.builder() + .name("ff_writer".to_string()) + .spawn({ + let shm_handle = shm_handle.clone(); + move |_| { + set_cpu_affinity(CPU_AFF_WRITER); + + let writer_shm = SharedSlabAllocator::connect(&shm_handle).unwrap(); + + acquisition_loop( + &w1rx, + &recycle_frames_tx, + &writer_events_rx, + events, + writer_shm, + ); + } + }) + .expect("could not spawn ff_writer thread"); + + s.builder() + .name("retire_thread".to_string()) + .spawn({ + // let shm_handle = shm_handle.clone(); + move |_| { + let mut shm = SharedSlabAllocator::connect(&shm_handle).unwrap(); + loop { + match recycle_frames_rx.recv_timeout(Duration::from_millis(100)) { + Ok(AcquisitionResult::Frame(frame, _)) + | Ok(AcquisitionResult::DroppedFrame(frame, _)) + | Ok(AcquisitionResult::DroppedFrameOutside(frame)) => { + frame.free_payload(&mut shm) + } + Ok(AcquisitionResult::DoneAborted { .. }) + | Ok(AcquisitionResult::DoneSuccess { .. }) + | Ok(AcquisitionResult::ShutdownIdle) + | Ok(AcquisitionResult::DoneShuttingDown { .. }) => { + events.send(&EventMsg::Shutdown); + info!("retire thread closing"); + break; + } + Err(RecvTimeoutError::Timeout) => { + continue; + } + Err(RecvTimeoutError::Disconnected) => { + info!("retire thread closing"); + break; + } + } + } + } + }) + .unwrap(); + + events.send(&EventMsg::Init {}); + + events.send(&EventMsg::Arm { + params: AcquisitionParams { + size: AcquisitionSize::NumFrames(1800), + // size: AcquisitionSize::Continuous, + //sync: AcquisitionSync::WaitForSync, + sync: AcquisitionSync::Immediately, + binning: k2o::events::Binning::Bin1x, + }, + acquisition_id: 0, + }); + + control_loop(events, pump) + }) + .unwrap(); +} + +pub fn main() { + let args = Args::parse(); + + let env = env_logger::Env::default() + .filter_or("LIBERTEM_K2IS_LOG_LEVEL", "info") + .write_style_or("LIBERTEM_K2IS_LOG_STYLE", "always"); + env_logger::init_from_env(env); + + tracing_from_env("k2o".to_owned()); + + let mode = match args.mode { + None => { + info!("auto-initializing mode..."); + let packet_size = recv_and_get_init().unwrap() as usize; + match packet_size { + K2ISBlock::PACKET_SIZE => Mode::IS, + K2SummitBlock::PACKET_SIZE => Mode::Summit, + _ => panic!("unknown packet size: {}", packet_size), + } + } + Some(mode) => mode, + }; + + let events: Events = ChannelEventBus::new(); + let pump = MessagePump::new(&events); + + match mode { + Mode::IS => { + info!("IS mode..."); + start_threads::<{ K2ISBlock::PACKET_SIZE }, K2ISFrame, K2ISBlock>( + &args, + &events, + &Some(pump), + ); + } + Mode::Summit => { + info!("Summit mode..."); + start_threads::<{ K2SummitBlock::PACKET_SIZE }, K2SummitFrame, K2SummitBlock>( + &args, + &events, + &Some(pump), + ); + } + } +} diff --git a/k2o/src/bin/main_async.rs b/k2o/src/bin/main_async.rs new file mode 100644 index 00000000..d5fffc9f --- /dev/null +++ b/k2o/src/bin/main_async.rs @@ -0,0 +1,126 @@ +extern crate crossbeam; + +use k2o::{block::K2Block, block_is::K2ISBlock}; +use std::net::Ipv4Addr; +use tokio::sync::mpsc; +use tokio::task::JoinHandle; + +use k2o::decode::{decode_packet_size, HEADER_SIZE}; + +async fn create_mcast_socket_tokio(port: u32, group: &str, local: &str) -> tokio::net::UdpSocket { + // Compared to Python version, we create a bound socket here (we don't + // really need one, but shouldn't hurt) + let group_w_port = format!("{group}:{port}", group = group, port = port); + let socket = tokio::net::UdpSocket::bind(&group_w_port) + .await + .unwrap_or_else(|err| { + panic!("couldn't bind to {}: {:?}", group_w_port, err); + }); + + // I'm leaving out the step of setting SO_REUSEADDR and SO_REUSEPORT, as I + // think we don't need them - we have to "route" all packets from/to a single port + // to the same process anyways, we can't distribute packets to different procesess. + let group_addr: Ipv4Addr = group.parse().expect("failed to parse group address"); + let local_addr: Ipv4Addr = local.parse().expect("failed to parse local address"); + + // Compared to the Python version, we are using the address of the local interface here, + // instead of using the interface index. Let's see if this works out! + socket + .join_multicast_v4(group_addr, local_addr) + .unwrap_or_else(|err| { + panic!( + "could not join multicast group {} on local addr {}: {:?}", + group_addr, local_addr, err + ); + }); + + socket +} + +pub async fn recv_decode_loop( + channel: &'static mpsc::Sender, +) -> Vec> { + let ids = 0..=7; + + let join_handles = ids.map(|id| { + let port: u32 = 2001 + id; + // let cpu = (10 + id) as usize; + tokio::spawn(async move { + /*let mut cpu_set = CpuSet::new(); + cpu_set.set(cpu).expect("could not set CPU affinity!"); + nix::sched::sched_setaffinity(Pid::from_raw(0), &cpu_set) + .expect("could not set CPU affinity!");*/ + + let socket = create_mcast_socket_tokio(port, "225.1.1.1", "192.168.10.99").await; + + let mut buf: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let mut pls: u64; + let mut counter: i64 = 0; + loop { + pls = 0; + let (number_of_bytes, _src_addr) = + socket.recv_from(&mut buf).await.expect("recv_from failed"); + assert_eq!(number_of_bytes, PACKET_SIZE); + let block: K2ISBlock = K2ISBlock::from_bytes(&buf, id as u8, 0); + block.validate(); + channel.send(block).await.unwrap(); + /* + for x in &block.payload { + pls = pls + (*x as u64); + } + counter += 1; + if counter % 1000 == 0 { + println!("counter={} pls={} frame_id={} port={}", counter, pls, block.frame_id, port); + } + */ + } + // return (); // not really, because it will never execute because of the infinite loop above + }) + }); + Vec::from_iter(join_handles) +} + +/// +/// Receive a single packet and read the PACKET_SIZE from it +/// +async fn recv_and_get_packet_size() -> u32 { + // finding the PACKET_SIZE: we just have a look at the first packet from the first sector + const PORT: u32 = 2001; + let socket = create_mcast_socket_tokio(PORT, "225.1.1.1", "192.168.10.99").await; + let mut buf: [u8; HEADER_SIZE] = [0; HEADER_SIZE]; + let (number_of_bytes, _src_addr) = socket.recv_from(&mut buf).await.expect("recv_from failed"); + assert_eq!(number_of_bytes, HEADER_SIZE); + decode_packet_size(&buf) +} + +#[tokio::main] +pub async fn main() { + let packet_size = recv_and_get_packet_size().await; + + /* + println!("packet_size = {}", packet_size); + + let (tx, mut rx) = mpsc::channel(1024); + let (tx_is, mut rx_is) = mpsc::channel::>(1024); + + if packet_size == 0x5758 { // IS mode + let join_handles: Vec> = recv_decode_loop::<0x5758, 14880>(&tx_is).await; + while let Some(block) = rx_is.recv().await { + + } + futures::future::join_all(join_handles).await; + } else if packet_size == 0xc028 { // Summit mode + // FIXME: this is proably not correct - it looks like this mode uses a different encoding + // from the block header, the payload size per block is 32*768 = 24576 + // + // From the PACKET_SIZE, if we assume 12bit encoding like in IS mode, + // we have DECODED_SIZE = (PACKET_SIZE-HEADER_SIZE)*2/3 = (0xc028-40)*2/3 = 32768 + // + // If we instead assume u16 "encoding", we get (0xc028-40)/2 = 24576 as expected + let join_handles = recv_decode_loop::<0xc028, 24576>(&tx).await; + futures::future::join_all(join_handles).await; + } else { + panic!("Unknown packet size, aborting") + } + */ +} diff --git a/k2o/src/bin/read.rs b/k2o/src/bin/read.rs new file mode 100644 index 00000000..82a3dc93 --- /dev/null +++ b/k2o/src/bin/read.rs @@ -0,0 +1,20 @@ +use std::fs::OpenOptions; + +use memmap2::{MmapMut, MmapOptions}; +use ndarray_npy::{write_zeroed_npy, ViewMutNpyExt}; + +pub fn main() { + let filename = "/cachedata/alex/foo.npy"; + let file = OpenOptions::new() + .read(true) + .write(true) + .open(filename) + .unwrap(); + + let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() }; + + let shape = (4000, 1860, 2048); + let mut view = ndarray::ArrayViewMut3::::view_mut_npy(&mut mmap).unwrap(); + + println!("sum={}", view.sum()); +} diff --git a/k2o/src/bin/stuff.rs b/k2o/src/bin/stuff.rs new file mode 100644 index 00000000..c12226b5 --- /dev/null +++ b/k2o/src/bin/stuff.rs @@ -0,0 +1,31 @@ +use k2o::helpers::preallocate; + +fn main() { + preallocate("/tmp/stuff", 1024, 7, k2o::helpers::AllocateMode::ZeroFill); +} + +trait Thing { + fn do_thingy_things(self); +} + +trait Builder { + fn build_thing(how_deep: u32) -> Box; +} + +struct Builder1 {} + +struct Thing1 { + how_deep: u32, +} + +impl Thing for Thing1 { + fn do_thingy_things(self) { + println!("I'm doing thingy things here, look at me!"); + } +} + +impl Builder for Builder1 { + fn build_thing(how_deep: u32) -> Box { + Box::new(Thing1 { how_deep }) + } +} diff --git a/k2o/src/bin/timestamp_recorder.rs b/k2o/src/bin/timestamp_recorder.rs new file mode 100644 index 00000000..69f72e8a --- /dev/null +++ b/k2o/src/bin/timestamp_recorder.rs @@ -0,0 +1,212 @@ +use std::{ + collections::HashMap, + time::{Duration, Instant}, +}; + +use clap::Parser; +use common::background_thread::AcquisitionSize; +use crossbeam::channel::unbounded; +use k2o::{ + block::{BlockRouteInfo, K2Block}, + block_is::K2ISBlock, + block_summit::K2SummitBlock, + events::{AcquisitionParams, AcquisitionSync, ChannelEventBus, EventBus, EventMsg, Events}, + recv::{recv_decode_loop, RecvConfig}, +}; + +fn mean(data: &[u128]) -> Option { + let sum = data.iter().sum::() as f32; + let count = data.len(); + + match count { + positive if positive > 0 => Some(sum / count as f32), + _ => None, + } +} + +fn std_deviation(data: &[u128]) -> Option { + match (mean(data), data.len()) { + (Some(data_mean), count) if count > 0 => { + let variance = data + .iter() + .map(|value| { + let diff = data_mean - (*value as f32); + + diff * diff + }) + .sum::() + / count as f32; + + Some(variance.sqrt()) + } + _ => None, + } +} + +fn start_threads< + const PACKET_SIZE: usize, // FIXME: use B::PACKET_SIZE here + B: K2Block, +>( + events: &Events, + duration: u64, +) { + let ids = 0..=7u8; + + let (recycle_blocks_tx, recycle_blocks_rx) = unbounded::(); + + crossbeam::scope(|s| { + let (decoded_tx, decoded_rx) = unbounded::<(B, BlockRouteInfo)>(); + for sector_id in ids { + let port: u32 = 2001 + (sector_id as u32); + let tx = decoded_tx.clone(); + let recycle_clone_rx = recycle_blocks_rx.clone(); + let recycle_clone_tx = recycle_blocks_tx.clone(); + let events_rx = events.subscribe(); + let local_addr = if sector_id < 4 { + "192.168.10.99".to_string() + } else { + "192.168.10.98".to_string() + }; + + s.builder() + .name(format!("recv-decode-{}", sector_id)) + .spawn(move |_| { + recv_decode_loop::( + sector_id, + port, + &tx, + &recycle_clone_rx, + &recycle_clone_tx, + &events_rx, + events, + local_addr, + None, + &RecvConfig::new(true), + ); + }) + .expect("could not spawn recv+decode thread"); + } + + // "warmup" + for _ in 0..1024 { + recycle_blocks_tx.send(B::empty(0, 0)).unwrap(); + } + + events.send(&EventMsg::ArmSectors { + params: AcquisitionParams { + size: AcquisitionSize::Continuous, + sync: AcquisitionSync::Immediately, + binning: k2o::events::Binning::Bin1x, + }, + acquisition_id: 0, + }); + + let mut stats: HashMap, _> = HashMap::new(); + + let deadline = Instant::now() + Duration::from_secs(duration); + + while let Ok((block, _)) = decoded_rx.recv_timeout(Duration::from_millis(500)) { + let ts = block.get_decoded_timestamp(); + let frame_id = block.get_frame_id(); + stats + .entry(frame_id) + .and_modify(|timestamps| timestamps.push(ts)) + .or_insert_with(|| vec![ts]); + recycle_blocks_tx.send(block).unwrap(); + + if Instant::now() > deadline { + break; + } + } + + events.send(&EventMsg::Shutdown); + + // reference timestamp: the first one + let ref_ts = stats + .values() + .map(|timestamps| { + timestamps + .iter() + .min() + .expect("timestamps are not empty, by construction") + }) + .min() + .expect("stats map should not be empty"); + + // could visualize with a box plot. but really just want a bunch of + // numbers to quantify this! average of standard deviations (given equal sample size): + // sqrt((s_1^2 + s_2^2 + ... + s_k^2) / k) + + let frame_times: Vec = stats + .values() + .map(|timestamps| { + let min_instant = timestamps.iter().min().unwrap(); + let max_instant = timestamps.iter().max().unwrap(); + max_instant.duration_since(*min_instant).as_secs_f32() + }) + .filter(|ts| *ts != 0.0) + .collect(); + + println!("frame times: {:?}", frame_times); + println!( + "max frame time: {}", + frame_times + .iter() + .max_by(|a, b| a.partial_cmp(b).unwrap()) + .unwrap() + ); + println!( + "min frame time: {}", + frame_times + .iter() + .min_by(|a, b| a.partial_cmp(b).unwrap()) + .unwrap() + ); + + let stds: Vec = stats + .values() + .map(|timestamps| { + let durations = timestamps.iter().map(|ts| ts.duration_since(*ref_ts)); + let micros: Vec = durations.map(|dur| dur.as_micros()).collect(); + + std_deviation(µs[..]).expect("micros are not empty, by construction") + }) + .collect(); + + let sum_stds: f32 = stds.iter().map(|s| s * s).sum(); + let mean_std = (sum_stds / stds.len() as f32).sqrt(); + println!("mean of std is {mean_std}"); + }) + .unwrap(); +} + +#[derive(clap::ValueEnum, Clone, Copy, Debug)] +pub enum Mode { + IS, + Summit, +} + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +pub struct Args { + /// Camera mode + #[clap(short, long, value_enum, default_value = "is")] + pub mode: Mode, + + /// Duration to run the experiment, in seconds + #[clap(short, long, default_value = "10")] + pub duration: u64, +} + +pub fn main() { + let events: Events = ChannelEventBus::new(); + + let args = Args::parse(); + + match args.mode { + Mode::IS => start_threads::<{ K2ISBlock::PACKET_SIZE }, K2ISBlock>(&events, args.duration), + Mode::Summit => { + start_threads::<{ K2SummitBlock::PACKET_SIZE }, K2SummitBlock>(&events, args.duration) + } + } +} diff --git a/k2o/src/block.rs b/k2o/src/block.rs new file mode 100644 index 00000000..cd829cd5 --- /dev/null +++ b/k2o/src/block.rs @@ -0,0 +1,64 @@ +use std::time::Instant; + +use ndarray::{ArrayBase, Dim, ViewRepr}; + +pub trait K2Block: Send { + const PACKET_SIZE: usize; + const DECODED_SIZE: usize; + const BLOCK_WIDTH: usize; + const BLOCK_HEIGHT: usize; + const SECTOR_WIDTH: usize; + const SECTOR_HEIGHT: usize; + const BLOCKS_PER_SECTOR: u8; + + fn from_bytes(bytes: &[u8], sector_id: u8, acquisition_id: usize) -> Self; + fn replace_with(&mut self, bytes: &[u8], sector_id: u8, acquisition_id: usize); + fn as_array(&self) -> ArrayBase, Dim<[usize; 2]>>; + fn as_vec(&self) -> &Vec; + fn empty(first_frame_id: u32, acquisition_id: usize) -> Self; + fn get_flags(&self) -> u8; + fn sync_is_set(&self) -> bool { + (self.get_flags() & 0x01) == 0x01 + } + fn get_sector_width(&self) -> u16; + fn get_sector_height(&self) -> u16; + fn get_x_start(&self) -> u16; + fn get_y_start(&self) -> u16; + fn get_x_end(&self) -> u16; + fn get_y_end(&self) -> u16; + fn get_x_offset(&self) -> u16 { + self.get_sector_width() * (self.get_sector_id() as u16) + } + fn get_frame_id(&self) -> u32; + fn get_sector_id(&self) -> u8; + fn get_decoded_timestamp(&self) -> Instant; + fn get_acquisition_id(&self) -> usize; + fn validate(&self); +} + +/// routing info, extracted from the block itself +/// why? to have the block itself and routing info separately +/// so they don't cause cache contention issues (example: if we have a single thread that +/// routes blocks around, we don't want to forcibly move parts of the block +/// itself to the core that is running said thread) +#[derive(Clone, Copy)] +pub struct BlockRouteInfo { + frame_id: u32, + sector_id: u8, +} + +impl BlockRouteInfo { + pub fn new(block: &B) -> BlockRouteInfo { + BlockRouteInfo { + frame_id: block.get_frame_id(), + sector_id: block.get_sector_id(), + } + } + pub fn get_frame_id(&self) -> u32 { + self.frame_id + } + + pub fn get_sector_id(&self) -> u8 { + self.sector_id + } +} diff --git a/k2o/src/block_is.rs b/k2o/src/block_is.rs new file mode 100644 index 00000000..f2a90c4b --- /dev/null +++ b/k2o/src/block_is.rs @@ -0,0 +1,247 @@ +use std::time::Instant; + +use ndarray::{ArrayBase, ArrayView, Dim, ViewRepr}; + +use crate::{ + block::K2Block, + decode::{decode, decode_u16, decode_u32}, +}; + +#[derive(Debug)] +pub struct K2ISBlock { + sync: u32, // should be constant 0xFFFF0055 + // padding1: [u8; 4], + version: u8, + flags: u8, + // padding2: [u8; 6], + block_count: u32, + + /// sector width + width: u16, + + /// sector height + height: u16, + + frame_id: u32, + + /// start index in x direction + pixel_x_start: u16, + + /// start index in y direction + pixel_y_start: u16, + + /// end index in x direction, inclusive + pixel_x_end: u16, + + /// end index in y direction, inclusive + pixel_y_end: u16, + + block_size: u32, // for IS mode: fixed 0x5758; can be different in summit mode (0xc028) + payload: Vec, // the already decoded payload + sector_id: u8, // not part of the actual data received, added as "metadata" + decode_timestamp: Instant, + // TODO: receive timestamp as an Instant + acquisition_id: usize, +} + +impl K2ISBlock { + /// return a dummy block with specified fields, matching IS specs + /// NOTE: only meant for testing! + pub fn empty_for_pos(x: u16, y: u16, frame_id: u32, acquisition_id: usize) -> K2ISBlock { + let payload: Vec = vec![0; Self::DECODED_SIZE]; + K2ISBlock { + sync: 0xFFFF0055, + version: 1, + flags: 0x01, + block_count: 0, + width: 256, + height: 1860, + frame_id, + pixel_x_start: x, + pixel_y_start: y, + pixel_x_end: x + 16 - 1, + pixel_y_end: y + 930 - 1, + block_size: 0x5758, + payload, + sector_id: 0, + decode_timestamp: Instant::now(), + acquisition_id, + } + } + + /// return a block for the given input data and specified position + /// NOTE: not optimized for performance - creates a copy of the data + /// only use for testing! + pub fn from_vec_and_pos( + data: &[u16], + x: u16, + y: u16, + frame_id: u32, + acquisition_id: usize, + ) -> K2ISBlock { + let payload = data.to_vec(); // create an owned copy here + K2ISBlock { + sync: 0xFFFF0055, + version: 1, + flags: 0x01, + block_count: 0, + width: 256, + height: 1860, + frame_id, + pixel_x_start: x, + pixel_y_start: y, + pixel_x_end: x + 16 - 1, + pixel_y_end: y + 930 - 1, + block_size: 0x5758, + payload, + sector_id: 0, + decode_timestamp: Instant::now(), + acquisition_id, + } + } +} + +impl K2Block for K2ISBlock { + fn from_bytes(bytes: &[u8], sector_id: u8, acquisition_id: usize) -> K2ISBlock { + // FIXME: we don't really need to initialize the vector, as it will be overwritten by `decode` just below... + // FIXME: use MaybeUninit stuff from nightly? + let mut payload = vec![0; Self::DECODED_SIZE]; + + // println!("{}", payload.len()); + // payload.fill(0); + // println!("{}", payload.len()); + decode::<{ Self::PACKET_SIZE }>(bytes, &mut payload); + + K2ISBlock { + sync: decode_u32(&bytes[0..4]), + version: bytes[8], + flags: bytes[9], + block_count: decode_u32(&bytes[16..20]), + width: decode_u16(&bytes[20..22]), + height: decode_u16(&bytes[22..24]), + frame_id: decode_u32(&bytes[24..28]), + pixel_x_start: decode_u16(&bytes[28..30]), + pixel_y_start: decode_u16(&bytes[30..32]), + pixel_x_end: decode_u16(&bytes[32..34]), + pixel_y_end: decode_u16(&bytes[34..36]), + block_size: decode_u32(&bytes[36..40]), + payload, + sector_id, + decode_timestamp: Instant::now(), + acquisition_id, + } + } + + fn replace_with(&mut self, bytes: &[u8], sector_id: u8, acquisition_id: usize) { + decode::<{ Self::PACKET_SIZE }>(bytes, &mut self.payload); + + self.sync = decode_u32(&bytes[0..4]); + self.version = bytes[8]; + self.flags = bytes[9]; + self.block_count = decode_u32(&bytes[16..20]); + self.width = decode_u16(&bytes[20..22]); + self.height = decode_u16(&bytes[22..24]); + self.frame_id = decode_u32(&bytes[24..28]); + self.pixel_x_start = decode_u16(&bytes[28..30]); + self.pixel_y_start = decode_u16(&bytes[30..32]); + self.pixel_x_end = decode_u16(&bytes[32..34]); + self.pixel_y_end = decode_u16(&bytes[34..36]); + self.block_size = decode_u32(&bytes[36..40]); + self.sector_id = sector_id; + self.decode_timestamp = Instant::now(); + self.acquisition_id = acquisition_id; + } + + fn as_array(&self) -> ArrayBase, Dim<[usize; 2]>> { + let height = self.pixel_y_end - self.pixel_y_start + 1; + let width = self.pixel_x_end - self.pixel_x_start + 1; + let view = + ArrayView::from_shape((height as usize, width as usize), &self.payload[..]).unwrap(); + view + } + + fn as_vec(&self) -> &Vec { + &self.payload + } + + /// return a dummy block, matching IS specs + /// NOTE: only meant for testing! + fn empty(first_frame_id: u32, acquisition_id: usize) -> Self { + let payload: Vec = vec![0; Self::DECODED_SIZE]; + K2ISBlock { + sync: 0xFFFF0055, + version: 1, + flags: 0x01, + block_count: 0, + width: 256, + height: 1860, + frame_id: first_frame_id, + pixel_x_start: 0, + pixel_y_start: 0, + pixel_x_end: 15, + pixel_y_end: 929, + block_size: 0x5758, + payload, + sector_id: 0, + decode_timestamp: Instant::now(), + acquisition_id, + } + } + + fn get_flags(&self) -> u8 { + self.flags + } + + fn get_sector_width(&self) -> u16 { + self.width + } + + fn get_sector_height(&self) -> u16 { + self.height + } + + fn get_x_start(&self) -> u16 { + self.pixel_x_start + } + + fn get_y_start(&self) -> u16 { + self.pixel_y_start + } + + fn get_x_end(&self) -> u16 { + self.pixel_x_end + } + + fn get_y_end(&self) -> u16 { + self.pixel_y_end + } + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn get_sector_id(&self) -> u8 { + self.sector_id + } + + const PACKET_SIZE: usize = 0x5758; + const DECODED_SIZE: usize = 14880; + const BLOCK_WIDTH: usize = 16; + const BLOCK_HEIGHT: usize = 930; + const SECTOR_WIDTH: usize = 256; + const SECTOR_HEIGHT: usize = 2 * 930; + const BLOCKS_PER_SECTOR: u8 = 32; + + fn get_decoded_timestamp(&self) -> Instant { + self.decode_timestamp + } + + fn validate(&self) { + assert_eq!(self.sync, 0xFFFF0055); + assert_eq!(self.block_size, 0x5758) + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} diff --git a/k2o/src/block_summit.rs b/k2o/src/block_summit.rs new file mode 100644 index 00000000..9c09d32b --- /dev/null +++ b/k2o/src/block_summit.rs @@ -0,0 +1,211 @@ +use std::time::Instant; + +use ndarray::{ArrayBase, ArrayView, Dim, ViewRepr}; + +use crate::{ + block::K2Block, + decode::{decode_u16, decode_u16_vec, decode_u32}, +}; + +#[derive(Debug)] +pub struct K2SummitBlock { + sync: u32, // should be constant 0xFFFF0055 + // padding1: [u8; 4], + version: u8, + flags: u8, + // padding2: [u8; 6], + block_count: u32, + + /// sector width + width: u16, + + /// sector height + height: u16, + + frame_id: u32, + + /// start index in x direction + pixel_x_start: u16, + + /// start index in y direction + pixel_y_start: u16, + + /// end index in x direction, inclusive + pixel_x_end: u16, + + /// end index in y direction, inclusive + pixel_y_end: u16, + + block_size: u32, // for IS mode: fixed 0x5758; can be different in summit mode (0xc028) + payload: Vec, // the already decoded payload + sector_id: u8, // not part of the actual data received, added as "metadata" + decode_timestamp: Instant, + // TODO: receive timestamp as an Instant + acquisition_id: usize, +} + +impl K2SummitBlock { + pub fn empty(frame_id: u32, acquisition_id: usize) -> Self { + let payload: Vec = vec![0; Self::DECODED_SIZE]; + Self { + sync: 0xFFFF0055, + version: 1, + flags: 0x01, + block_count: 0, + width: 512, + height: 3840, + frame_id, + pixel_x_start: 0, + pixel_y_start: 0, + pixel_x_end: 31, + pixel_y_end: 767, + block_size: 0xc028, + payload, + sector_id: 0, + decode_timestamp: Instant::now(), + acquisition_id, + } + } +} + +impl K2Block for K2SummitBlock { + fn from_bytes(bytes: &[u8], sector_id: u8, acquisition_id: usize) -> Self { + // FIXME: we don't really need to initialize the vector, as it will be overwritten by `decode` just below... + // FIXME: use MaybeUninit stuff from nightly? + let mut payload = vec![0; Self::DECODED_SIZE]; + + decode_u16_vec::<{ Self::PACKET_SIZE }>(bytes, &mut payload); + + Self { + sync: decode_u32(&bytes[0..4]), + version: bytes[8], + flags: bytes[9], + block_count: decode_u32(&bytes[16..20]), + width: decode_u16(&bytes[20..22]), + height: decode_u16(&bytes[22..24]), + frame_id: decode_u32(&bytes[24..28]), + pixel_x_start: decode_u16(&bytes[28..30]), + pixel_y_start: decode_u16(&bytes[30..32]), + pixel_x_end: decode_u16(&bytes[32..34]), + pixel_y_end: decode_u16(&bytes[34..36]), + block_size: decode_u32(&bytes[36..40]), + payload, + sector_id, + decode_timestamp: Instant::now(), + acquisition_id, + } + } + + fn replace_with(&mut self, bytes: &[u8], sector_id: u8, acquisition_id: usize) { + decode_u16_vec::<{ Self::PACKET_SIZE }>(bytes, &mut self.payload); + + self.sync = decode_u32(&bytes[0..4]); + self.version = bytes[8]; + self.flags = bytes[9]; + self.block_count = decode_u32(&bytes[16..20]); + self.width = decode_u16(&bytes[20..22]); + self.height = decode_u16(&bytes[22..24]); + self.frame_id = decode_u32(&bytes[24..28]); + self.pixel_x_start = decode_u16(&bytes[28..30]); + self.pixel_y_start = decode_u16(&bytes[30..32]); + self.pixel_x_end = decode_u16(&bytes[32..34]); + self.pixel_y_end = decode_u16(&bytes[34..36]); + self.block_size = decode_u32(&bytes[36..40]); + self.sector_id = sector_id; + self.decode_timestamp = Instant::now(); + self.acquisition_id = acquisition_id; + } + + fn as_array(&self) -> ArrayBase, Dim<[usize; 2]>> { + let height = self.pixel_y_end - self.pixel_y_start + 1; + let width = self.pixel_x_end - self.pixel_x_start + 1; + let view = + ArrayView::from_shape((height as usize, width as usize), &self.payload[..]).unwrap(); + view + } + + fn as_vec(&self) -> &Vec { + &self.payload + } + + /// return a dummy block + /// NOTE: only meant for testing! + fn empty(first_frame_id: u32, acquisition_id: usize) -> Self { + let payload: Vec = vec![0; Self::DECODED_SIZE]; + K2SummitBlock { + sync: 0xFFFF0055, + version: 1, + flags: 0x01, + block_count: 0, + width: 512, + height: 3840, + frame_id: first_frame_id, + pixel_x_start: 0, + pixel_y_start: 0, + pixel_x_end: 31, + pixel_y_end: 767, + block_size: 0xc028, + payload, + sector_id: 0, + decode_timestamp: Instant::now(), + acquisition_id, + } + } + + fn get_flags(&self) -> u8 { + self.flags + } + + fn get_sector_width(&self) -> u16 { + self.width + } + + fn get_sector_height(&self) -> u16 { + self.height + } + + fn get_x_start(&self) -> u16 { + self.pixel_x_start + } + + fn get_y_start(&self) -> u16 { + self.pixel_y_start + } + + fn get_x_end(&self) -> u16 { + self.pixel_x_end + } + + fn get_y_end(&self) -> u16 { + self.pixel_y_end + } + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn get_sector_id(&self) -> u8 { + self.sector_id + } + + fn get_decoded_timestamp(&self) -> Instant { + self.decode_timestamp + } + + const PACKET_SIZE: usize = 0xc028; + const DECODED_SIZE: usize = 0xc000; + const BLOCK_WIDTH: usize = 32; + const BLOCK_HEIGHT: usize = 768; + const SECTOR_WIDTH: usize = 512; + const SECTOR_HEIGHT: usize = 3840; + const BLOCKS_PER_SECTOR: u8 = 80; // 3840/768 = 5; 512/32 = 16 + + fn validate(&self) { + assert_eq!(self.sync, 0xFFFF0055); + assert_eq!(self.block_size as usize, Self::PACKET_SIZE); + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} diff --git a/k2o/src/cli_args.rs b/k2o/src/cli_args.rs new file mode 100644 index 00000000..80b339f5 --- /dev/null +++ b/k2o/src/cli_args.rs @@ -0,0 +1,24 @@ +use clap::Parser; + +#[derive(clap::ValueEnum, Clone, Copy, Debug)] +pub enum Mode { + IS, + Summit, +} + +/// Test program - arm and perform a single acquisition +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +pub struct Args { + /// Camera mode, determined automatically from first frame if not given + #[clap(short, long, value_enum)] + pub mode: Option, + + /// Disable allocation re-use + #[clap(short = 'r', long)] + pub disable_reuse: bool, + + /// Shared memory socket path + #[clap(short = 's', long, default_value = "/run/user/1000/k2is-shm-socket")] + pub shm_path: String, +} diff --git a/k2o/src/control.rs b/k2o/src/control.rs new file mode 100644 index 00000000..5b3819a7 --- /dev/null +++ b/k2o/src/control.rs @@ -0,0 +1,355 @@ +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use common::tracing::get_tracer; +use crossbeam::channel::TryRecvError; +use log::debug; +use opentelemetry::trace::{TraceContextExt, Tracer}; + +use crate::events::{AcquisitionParams, EventBus, EventMsg, Events, MessagePump}; + +/// +/// Global acquisition state +/// +#[derive(PartialEq, Eq, Debug, Clone, Default)] +pub enum AcquisitionState { + #[default] + Startup, + Idle, + Armed { + params: AcquisitionParams, + /// The current acquisition id + acquisition_id: usize, + }, + /// Current receiving data + AcquisitionStarted { + params: AcquisitionParams, + /// The reference frame id for this acquisition + frame_id: u32, + /// The current acquisition id + acquisition_id: usize, + }, + /// No longer receiving new data, but still processing + /// (=> there is still data in the queues) + AcquisitionFinishing { + params: AcquisitionParams, + /// The reference frame id for this acquisition + frame_id: u32, + /// The current acquisition id + acquisition_id: usize, + }, + Shutdown, +} + +/// +/// Message pump thread connecting the "outer" world to the event bus. +/// +/// It will run until it receives `EventMsg::Shutdown` or one of the channels is +/// disconnected. +/// +pub fn control_loop(events: &Events, pump: &Option) { + let tracer = get_tracer(); + + let events_rx = events.subscribe(); + + tracer.in_span("control_loop", |cx| { + let _span = cx.span(); + + loop { + if let Some(pump) = pump.as_ref() { + pump.do_pump_timeout(events, Duration::from_millis(100)) + .expect("message pump disconnected"); + } + match events_rx.try_recv() { + Ok(EventMsg::Shutdown) => break, + Err(TryRecvError::Empty) => continue, + Err(TryRecvError::Disconnected) => break, + Ok(_) => continue, + } + } + }); +} + +#[derive(Debug)] +pub enum StateError { + InvalidTransition { + from: AcquisitionState, + msg: EventMsg, + }, +} + +pub struct StateTracker { + pub state: AcquisitionState, +} + +/// Keep track of the acquisition state, changed by incoming events +impl StateTracker { + pub fn new() -> Self { + StateTracker { + state: AcquisitionState::Startup, + } + } + + pub fn next_state(&self, event: &EventMsg) -> Result { + match &self.state { + AcquisitionState::Startup => { + // only Init is a valid transition here: + match event { + EventMsg::Init => Ok(AcquisitionState::Idle), + _ => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + } + } + AcquisitionState::Shutdown => { + // can't handle any messages when shut down (should also not happen...) + Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }) + } + AcquisitionState::Idle => { + match event { + // invalid transitions: + EventMsg::Init => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionStartedSector { + sector_id: _, + frame_id: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionStarted { + frame_id: _, + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::ArmSectors { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionEnded { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::CancelAcquisition { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::ProcessingDone { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in AcquisitionFinishing state + + // valid transitions: + EventMsg::Arm { + params, + acquisition_id, + } => Ok(AcquisitionState::Armed { + params: params.clone(), + acquisition_id: *acquisition_id, + }), + EventMsg::Shutdown => Ok(AcquisitionState::Shutdown), + EventMsg::AcquisitionError { msg: _ } => Ok(AcquisitionState::Shutdown), + } + } + AcquisitionState::Armed { + params, + acquisition_id: _, + } => { + match event { + // invalid transitions: + EventMsg::Init => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::Arm { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::ProcessingDone { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in AcquisitionFinishing state + + // valid transitions to self: + EventMsg::ArmSectors { + params, + acquisition_id, + } => Ok(AcquisitionState::Armed { + params: params.clone(), + acquisition_id: *acquisition_id, + }), + EventMsg::AcquisitionStartedSector { + sector_id: _, + frame_id: _, + acquisition_id, + } => Ok(AcquisitionState::Armed { + params: params.clone(), + acquisition_id: *acquisition_id, + }), + + // valid transitions: + EventMsg::AcquisitionStarted { + frame_id, + params, + acquisition_id, + } => Ok(AcquisitionState::AcquisitionStarted { + params: params.clone(), + frame_id: *frame_id, + acquisition_id: *acquisition_id, + }), + EventMsg::AcquisitionEnded { acquisition_id: _ } => Ok(AcquisitionState::Idle), + EventMsg::CancelAcquisition { acquisition_id: _ } => Ok(AcquisitionState::Idle), + EventMsg::Shutdown => Ok(AcquisitionState::Shutdown), + EventMsg::AcquisitionError { msg: _ } => Ok(AcquisitionState::Shutdown), + } + } + AcquisitionState::AcquisitionStarted { + params, + frame_id, + acquisition_id, + } => { + match event { + // invalid transitions: + EventMsg::Init => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in Idle state + EventMsg::AcquisitionStarted { + frame_id: _, + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in Armed state + EventMsg::Arm { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in Idle state + EventMsg::ArmSectors { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in Armed state + EventMsg::ProcessingDone { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), // should only come in AcquisitionFinishing state + + // valid transitions: + EventMsg::AcquisitionStartedSector { + sector_id: _, + frame_id: _, + acquisition_id: _, + } => Ok(AcquisitionState::AcquisitionStarted { + params: params.clone(), + frame_id: *frame_id, + acquisition_id: *acquisition_id, + }), + EventMsg::AcquisitionEnded { acquisition_id } => { + Ok(AcquisitionState::AcquisitionFinishing { + params: params.clone(), + frame_id: *frame_id, + acquisition_id: *acquisition_id, + }) + } + EventMsg::CancelAcquisition { acquisition_id: _ } => Ok(AcquisitionState::Idle), + EventMsg::Shutdown => Ok(AcquisitionState::Shutdown), + EventMsg::AcquisitionError { msg: _ } => Ok(AcquisitionState::Shutdown), + } + } + AcquisitionState::AcquisitionFinishing { + params: _, + frame_id: _, + acquisition_id: _acquisition_id_outer, + } => { + match event { + // invalid transitions: + EventMsg::Init => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionStartedSector { + sector_id: _, + frame_id: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionStarted { + frame_id: _, + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::Arm { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::ArmSectors { + params: _, + acquisition_id: _, + } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + EventMsg::AcquisitionEnded { .. } => Err(StateError::InvalidTransition { + from: self.state.clone(), + msg: event.clone(), + }), + + // valid transitions: + EventMsg::CancelAcquisition { acquisition_id: _ } => Ok(AcquisitionState::Idle), + EventMsg::Shutdown => Ok(AcquisitionState::Shutdown), + EventMsg::ProcessingDone { acquisition_id: _ } => Ok(AcquisitionState::Idle), + EventMsg::AcquisitionError { msg: _ } => Ok(AcquisitionState::Shutdown), + } + } + } + } + + pub fn set_state_from_msg(&mut self, msg: &EventMsg) -> Result { + let next_state = self.next_state(msg)?; + let ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + if next_state != self.state { + debug!( + "StateTracker:\n old={:?}\n event={:?}\n -> {:?}\n ts={:?}", + self.state, msg, next_state, ts, + ); + } + self.state = next_state; + Ok(self.state.clone()) + } +} + +impl Default for StateTracker { + fn default() -> Self { + Self::new() + } +} diff --git a/k2o/src/decode.rs b/k2o/src/decode.rs new file mode 100644 index 00000000..d9c3f96e --- /dev/null +++ b/k2o/src/decode.rs @@ -0,0 +1,402 @@ +//! +//! # K2IS encoding/decoding functionality +//! +//! This module contains functionality for encoding and decoding K2IS +//! files and network packets. +//! +//! # Binary file and +//! +//! # 12bit "little endian" encoding +//! +//! The encoding can be described by just looking at a single input pair (a, b) +//! of u16 values. Let's say our inputs are `0xABC` and `0xDEF`. +//! The encoder now outputs three bytes. +//! - the first output byte is made up of the two least significant nibbles of `a`, so `0xBC` +//! - the second output byte is a combination from the two input values: +//! - the least significant nibble is the most significant nibble from `a`, so `0xA` +//! - the most significant nibble is the least significant niddle from `b`, so `0xF` +//! - the third output byte is the two most significant nibbles from `b`, so `0xDE` +//! +//! So, to summarize: +//! +//! input: ABC DEF +//! output: BC FA DE +use std::convert::TryInto; + +use multiversion::multiversion; +use num::cast::AsPrimitive; + +pub const HEADER_SIZE: usize = 40; + +// These are no longer constant; they are now const generics (or derived from such): +// pub const PACKET_SIZE: usize = 0x5758; // or 0xc028 +// pub const PAYLOAD_SIZE: usize = PACKET_SIZE - HEADER_SIZE; +// pub const DECODED_SIZE: usize = 930 * 16; // number of u16 values -> can also be 32 * 768 for summit mode + +/// +/// Decodes 12bit "little endian" values into integers +/// +/// # Arguments +/// * `bytes` - the bytes that should be decoded. Should be `PACKET_SIZE` long (`0x5758` or `0xc028`) +/// * `out` - the slice where the decoded integers should be written to. Should be `DECODED_SIZE` long (`14880`). +/// +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn decode(bytes: &[u8], out: &mut [u16]) { + // make sure input/output are bounded to PACKET_SIZE and DECODED_SIZE + //const DECODED_SIZE: usize = (PACKET_SIZE - HEADER_SIZE) * 2 / 3; + let input = &bytes[..PACKET_SIZE]; + let decoded = &mut out[..(PACKET_SIZE - HEADER_SIZE) * 2 / 3]; + + assert_eq!(input.len(), PACKET_SIZE); + assert_eq!(decoded.len(), (PACKET_SIZE - HEADER_SIZE) * 2 / 3); + + for i in 0..(PACKET_SIZE - HEADER_SIZE) / 3 { + let fst = input[HEADER_SIZE + i * 3] as u16; + let mid = input[HEADER_SIZE + i * 3 + 1] as u16; + let lst = input[HEADER_SIZE + i * 3 + 2] as u16; + + let a = fst | (mid & 0x0F) << 8; + let b = (mid & 0xF0) >> 4 | lst << 4; + + decoded[i * 2] = a; + decoded[i * 2 + 1] = b; + } +} + +/// +/// Decodes 12bit "little endian" values into generic type D, converted by function f: Fn(u16) -> D +/// +/// # Arguments +/// * `bytes` - the bytes that should be decoded. Should be `PACKET_SIZE` long (`0x5758`) +/// * `out` - the slice where the decoded integers should be written to. Should be `DECODED_SIZE` long (`14880`). +/// +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn decode_map( + bytes: &[u8], + out: &mut [D], + f: F, +) where + F: Fn(u16) -> D, +{ + // make sure input/output are bounded to PACKET_SIZE and DECODED_SIZE + let input = &bytes[..PACKET_SIZE]; + let decoded = &mut out[..DECODED_SIZE]; + + assert_eq!(input.len(), PACKET_SIZE); + assert_eq!(decoded.len(), DECODED_SIZE); + + for i in 0..(PACKET_SIZE - HEADER_SIZE) / 3 { + let fst = input[HEADER_SIZE + i * 3] as u16; + let mid = input[HEADER_SIZE + i * 3 + 1] as u16; + let lst = input[HEADER_SIZE + i * 3 + 2] as u16; + + let a = fst | (mid & 0x0F) << 8; + let b = (mid & 0xF0) >> 4 | lst << 4; + + decoded[i * 2] = f(a); + decoded[i * 2 + 1] = f(b); + } +} + +/// +/// Decodes 12bit "little endian" values into generic type D, converted by function f: Fn(u16) -> D +/// +/// # Arguments +/// * `bytes` - the bytes that should be decoded. Should be `PACKET_SIZE` long (`0x5758`) +/// * `out` - the slice where the decoded integers should be written to. Should be `DECODED_SIZE` long (`14880`). +/// +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn decode_converted( + bytes: &[u8], + out: &mut [D], +) where + u16: AsPrimitive, + D: Copy + 'static, +{ + // make sure input/output are bounded to PACKET_SIZE and DECODED_SIZE + let input = &bytes[..PACKET_SIZE]; + let decoded = &mut out[..DECODED_SIZE]; + + assert_eq!(input.len(), PACKET_SIZE); + assert_eq!(decoded.len(), DECODED_SIZE); + + for i in 0..(PACKET_SIZE - HEADER_SIZE) / 3 { + let fst = input[HEADER_SIZE + i * 3] as u16; + let mid = input[HEADER_SIZE + i * 3 + 1] as u16; + let lst = input[HEADER_SIZE + i * 3 + 2] as u16; + + let a = fst | (mid & 0x0F) << 8; + let b = (mid & 0xF0) >> 4 | lst << 4; + + decoded[i * 2] = a.as_(); + decoded[i * 2 + 1] = b.as_(); + } +} + +/// +/// Decodes 12bit "little endian" values into integers. Alternative +/// implementation that in unrolled (does not seem to be good for performance in all cases!) +/// +/// # Arguments +/// * `bytes` - the bytes that should be decoded. Should be `PACKET_SIZE` long (`0x5758`) +/// * `out` - the slice where the decoded integers should be written to. Should be `DECODED_SIZE` long (`14880`). +/// +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn decode_unrolled( + bytes: &[u8], + out: &mut [u16], +) { + let in_chunk_size = 3 * 3 * 16; + let out_chunk_size = 3 * 2 * 16; + + assert_eq!((PACKET_SIZE - HEADER_SIZE) % in_chunk_size, 0); + assert_eq!(DECODED_SIZE % out_chunk_size, 0); + + let input = &bytes[..PACKET_SIZE]; + let decoded = &mut out[..DECODED_SIZE]; + + assert_eq!(decoded.len(), DECODED_SIZE); + assert_eq!(input.len(), PACKET_SIZE); + + if true { + assert_eq!(bytes.len() % PACKET_SIZE, 0); + assert_eq!(decoded.len() % DECODED_SIZE, 0); + + assert_eq!((bytes.len() - HEADER_SIZE) % in_chunk_size, 0); + assert_eq!(decoded.len() % out_chunk_size, 0); + } + + let in_chunks_outer = input[HEADER_SIZE..].chunks_exact(in_chunk_size); + let out_chunks_outer = decoded[..DECODED_SIZE].chunks_exact_mut(out_chunk_size); + + for (in_chunk_outer, out_chunk_outer) in in_chunks_outer.zip(out_chunks_outer) { + let in_chunks = in_chunk_outer.chunks_exact(3); + let out_chunks = out_chunk_outer.chunks_exact_mut(2); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + let fst = in_chunk[0] as u16; + let mid = in_chunk[1] as u16; + let lst = in_chunk[2] as u16; + + out_chunk[0] = fst | (mid & 0x0F) << 8; + out_chunk[1] = mid >> 4 | lst << 4; + } + } +} + +pub fn decode_u32(bytes: &[u8]) -> u32 { + u32::from_be_bytes(bytes.try_into().unwrap()) +} + +pub fn decode_u16(bytes: &[u8]) -> u16 { + u16::from_be_bytes(bytes.try_into().unwrap()) +} + +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn decode_u16_vec(bytes: &[u8], out: &mut [u16]) { + for i in 0..(PACKET_SIZE - HEADER_SIZE) / 2 { + let in_bytes = &bytes[HEADER_SIZE + i * 2..HEADER_SIZE + i * 2 + 2]; + out[i] = decode_u16(in_bytes); + } +} + +pub fn decode_packet_size(bytes: &[u8]) -> u32 { + decode_u32(&bytes[36..40]) +} + +/// Encode the u16 values from `inp` into 12 bit "little endian" encoding. +/// +/// # Arguments +/// +/// * `inp` - The input integers +/// * `out` - A mutable byte slice where the encoded values will be written +/// +#[multiversion(targets( + "x86_64+adx+aes+avx+avx2+bmi1+bmi2+cmpxchg16b+f16c+fma+fxsr+lzcnt+movbe+pclmulqdq+popcnt+rdrand+rdseed+sha+sse+sse2+sse3+sse4.1+sse4.2+ssse3+xsave+xsavec+xsaveopt+xsaves", + "x86_64+avx+avx2+bmi1+bmi2+fma+sse+sse2+sse3+sse4.1+sse4.2+ssse3+popcnt", + "x86_64+avx+avx2", + "x86_64+avx", +))] +pub fn encode(inp: &Vec, out: &mut [u8]) { + // pre-condition: out_chunks should have no remainder + assert_eq!(out.len() % 3, 0); + // pre-condition: output size should be 3/2 of input size + assert_eq!(out.len(), inp.len() * 3 / 2); + + let in_chunks = inp.chunks_exact(2); + // pre-condition: in_chunks should have no remainder + assert_eq!(in_chunks.remainder().len(), 0); + let out_chunks = out.chunks_exact_mut(3); + + for (in_chunk, out_chunk) in in_chunks.zip(out_chunks) { + let a = in_chunk[0]; + let b = in_chunk[1]; + + out_chunk[0] = (a & 0xFF) as u8; + out_chunk[1] = ((a & 0xF00) >> 8) as u8 | ((b & 0xF) << 4) as u8; + out_chunk[2] = ((b & 0xFF0) >> 4) as u8; + } +} + +#[cfg(test)] +mod tests { + use crate::decode::decode; + use crate::decode::decode_converted; + use crate::decode::decode_map; + use crate::decode::decode_unrolled; + use crate::decode::encode; + //use crate::decode::DECODED_SIZE; + //use crate::decode::PACKET_SIZE; + use crate::decode::HEADER_SIZE; + + const PACKET_SIZE: usize = 0x5758; + const DECODED_SIZE: usize = (PACKET_SIZE - HEADER_SIZE) * 2 / 3; + + fn make_test_data() -> Vec { + let mut original_values: Vec = Vec::new(); + original_values.extend((0u16..=0xFFF).cycle().take(DECODED_SIZE)); + original_values + } + + #[test] + fn encode_works() { + let mut original_values: Vec = Vec::new(); + original_values.extend([0xABC, 0xDEF].iter().copied()); + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..43]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values); + println!("{:02X?}", &encoded_used); + + let mut decoded: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + decode::(&encoded, &mut decoded); + + println!("{:03X?}", &decoded[..2]); + + assert_eq!(&decoded[..2], &original_values[..2]); + } + + #[test] + fn roundtrip_decode() { + let original_values = make_test_data(); + + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values[..16]); // arbitrary cut-off + println!("{:02X?}", &encoded_used[..24]); // not-so-arbitrary cut-off + + let mut decoded: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + decode::(&encoded, &mut decoded); + + println!("{:03X?}", &decoded[..16]); // arbitrary cut-off + + assert_eq!(&decoded.to_vec(), &original_values); + } + + #[test] + fn roundtrip_decode_unrolled() { + let original_values = make_test_data(); + + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values); + println!("{:02X?}", &encoded_used); + + let mut decoded: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + decode_unrolled::(&encoded, &mut decoded); + + println!("{:03X?}", &decoded[..16]); // arbitrary cut-off + + assert_eq!(&decoded.to_vec(), &original_values); + } + + #[test] + fn roundtrip_decode_map() { + let original_values = make_test_data(); + + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values); + println!("{:02X?}", &encoded_used); + + let mut decoded: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + decode_map::<_, _, PACKET_SIZE, DECODED_SIZE>(&encoded, &mut decoded, |x| x); + + println!("{:03X?}", &decoded[..16]); // arbitrary cut-off + + assert_eq!(&decoded.to_vec(), &original_values); + } + + #[test] + fn roundtrip_decode_converted() { + let original_values = make_test_data(); + + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values); + println!("{:02X?}", &encoded_used); + + let mut decoded: [u16; DECODED_SIZE] = [0; DECODED_SIZE]; + decode_converted::<_, PACKET_SIZE, DECODED_SIZE>(&encoded, &mut decoded); + + println!("{:03X?}", &decoded[..16]); // arbitrary cut-off + + assert_eq!(&decoded.to_vec(), &original_values); + } + + #[test] + fn roundtrip_decode_converted_f32() { + //! encode from test data to u12, from u12 to f32 and back to original u16 + let original_values = make_test_data(); + + let mut encoded: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let encoded_used = &mut encoded[40..]; + encode(&original_values, encoded_used); + + println!("{:03X?}", &original_values); + println!("{:02X?}", &encoded_used); + + let mut decoded: [f32; DECODED_SIZE] = [0.0; DECODED_SIZE]; + decode_converted::<_, PACKET_SIZE, DECODED_SIZE>(&encoded, &mut decoded); + + println!("{:03X?}", &decoded[..16]); // arbitrary cut-off + + let decoded_back_to_u16: Vec = decoded.iter().map(|x| *x as u16).collect(); + + assert_eq!(&decoded_back_to_u16, &original_values); + } +} diff --git a/k2o/src/dio.rs b/k2o/src/dio.rs new file mode 100644 index 00000000..ab7eb104 --- /dev/null +++ b/k2o/src/dio.rs @@ -0,0 +1,12 @@ +use nix::libc::O_DIRECT; +use std::fs::OpenOptions; +use std::os::unix::prelude::OpenOptionsExt; + +pub fn open_direct(path: &str) -> Result { + return OpenOptions::new() + .read(true) + .write(true) + .create(true) + .custom_flags(O_DIRECT) + .open(path); +} diff --git a/k2o/src/events.rs b/k2o/src/events.rs new file mode 100644 index 00000000..c47a7681 --- /dev/null +++ b/k2o/src/events.rs @@ -0,0 +1,242 @@ +use std::{ + fmt::Debug, + sync::{Arc, Mutex}, + time::Duration, +}; + +use common::background_thread::AcquisitionSize; +use crossbeam::channel::{select, unbounded, Receiver, RecvError, SendError, Sender}; +use log::debug; + +pub trait EventBus { + /// Send `msg` to all subscribers + fn send(&self, msg: &T); + + /// Subscribe gives you a channel where you can receive events + /// currently you cannot unsubscribe, so this must not be used for short-lived threads! + fn subscribe(&self) -> Receiver; +} + +type ChannelList = Vec<(Sender, Receiver)>; + +/// Event bus based on crossbeam channel pairs +pub struct ChannelEventBus { + channels: Arc>>, +} + +impl ChannelEventBus { + pub fn new() -> Self { + Self { + channels: Arc::new(Mutex::new(Vec::new())), + } + } +} + +impl Default for ChannelEventBus { + fn default() -> Self { + Self::new() + } +} + +impl EventBus for ChannelEventBus { + fn subscribe(&self) -> Receiver { + let (tx, rx) = unbounded::(); + let mut channels = self.channels.lock().unwrap(); + channels.push((tx, rx.clone())); + rx + } + + fn send(&self, msg: &T) { + debug!("Event: {:?}", msg); + // FIXME: don't panic + for (tx, _) in self.channels.lock().unwrap().iter() { + tx.send(msg.clone()).unwrap(); + } + } +} + +#[derive(Debug)] +pub enum MessagePumpError { + Disconnected, +} + +impl From> for MessagePumpError { + fn from(_: SendError) -> Self { + MessagePumpError::Disconnected + } +} + +impl From for MessagePumpError { + fn from(_: RecvError) -> Self { + MessagePumpError::Disconnected + } +} + +pub struct MessagePump { + // our ends: + rx_from_ext_to_bus: Receiver, + tx_from_bus_to_ext: Sender, + + // the external ends: + tx_from_ext_to_bus: Sender, + rx_from_bus_to_ext: Receiver, + + // the receiver from the bus; the other end we can't own or reference here: + rx_from_bus: Receiver, +} + +impl MessagePump { + pub fn new(events: &Events) -> Self { + let rx_from_bus = events.subscribe(); + + let (tx_from_bus_to_ext, rx_from_bus_to_ext) = unbounded::(); + let (tx_from_ext_to_bus, rx_from_ext_to_bus) = unbounded::(); + + MessagePump { + rx_from_ext_to_bus, + tx_from_bus_to_ext, + tx_from_ext_to_bus, + rx_from_bus_to_ext, + rx_from_bus, + } + } + + /// Pump messages between external channels and the event bus. + /// This is non-blocking and does nothing if there are no events. + /// Will return a `MessagePumpError` in case an event is received and + /// channel we try to forward to is disconnected. + pub fn do_pump(&self, events: &Events) -> Result<(), MessagePumpError> { + // from the bus to the external channel: + if let Ok(msg) = self.rx_from_bus.try_recv() { + self.tx_from_bus_to_ext.send(msg)?; + } + // from the external channel to the bus: + if let Ok(msg) = self.rx_from_ext_to_bus.try_recv() { + events.send(&msg); + } + Ok(()) + } + + pub fn do_pump_timeout( + &self, + events: &Events, + timeout: Duration, + ) -> Result<(), MessagePumpError> { + select! { + // from the bus to the external channel: + recv(self.rx_from_bus) -> msg => { + self.tx_from_bus_to_ext.send(msg?)?; + } + // from the external channel to the bus: + recv(self.rx_from_ext_to_bus) -> msg => { + events.send(&msg?); + } + default(timeout) => return Ok(()), + } + Ok(()) + } + + pub fn get_ext_channels(&self) -> (Sender, Receiver) { + ( + self.tx_from_ext_to_bus.clone(), + self.rx_from_bus_to_ext.clone(), + ) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AcquisitionSync { + /// Wait for hardware synchronization. This means we first wait for + /// the frame id to wrap around to 1, and then for the sync flag to be + /// set in the received data. + WaitForSync, + + /// Ignore synchronization completely and just start acquiring data, + /// handling wrap-arounds gracefully + Immediately, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Binning { + /// 400 fps + Bin1x, + + /// 800 fps + Bin2x, + + /// 1200 fps + Bin4x, + + /// 1600 fps + Bin8x, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct AcquisitionParams { + pub size: AcquisitionSize, + pub sync: AcquisitionSync, + pub binning: Binning, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum EventMsg { + /// Ready for commands + Init, + + /// Sent when the sector `sector_id` has started the acquisition, for + /// example when it has received the first block with the sync flag set; + /// synchronizing to the given `frame_id` + AcquisitionStartedSector { + sector_id: u8, + frame_id: u32, + acquisition_id: usize, + }, + + /// Send when any sector has started the acquisition + AcquisitionStarted { + frame_id: u32, + params: AcquisitionParams, + acquisition_id: usize, + }, + + /// Send when a acquisition should be started + Arm { + params: AcquisitionParams, + acquisition_id: usize, + }, + + /// Send when the sector receiver threads should start acquiring data + ArmSectors { + params: AcquisitionParams, + acquisition_id: usize, + }, + + /// Send when the acquisition has ended (successfully or with an error) + // FIXME: need to distinguish cases! + AcquisitionEnded { + acquisition_id: usize, + }, + + /// Send when the final consumer is done processing all data + ProcessingDone { + acquisition_id: usize, + }, + + /// Send when the currently running acquisition should be stopped. + /// Depending on the `AcquisitionSize`, this can either be before finishing + /// acquisition of the fixed number of frames, or for continuous, + /// this successfully finishes the acquisition. + CancelAcquisition { + acquisition_id: usize, + }, + + /// Generic fatal acquisition error + AcquisitionError { + msg: String, + }, + + Shutdown, +} + +pub type Events = ChannelEventBus; +pub type EventReceiver = Receiver; diff --git a/k2o/src/frame.rs b/k2o/src/frame.rs new file mode 100644 index 00000000..037df398 --- /dev/null +++ b/k2o/src/frame.rs @@ -0,0 +1,323 @@ +use std::{ops::Range, time::Instant}; + +use common::frame_stack::FrameStackHandle; +use ipc_test::{SharedSlabAllocator, Slot, SlotInfo}; +use multiversion::multiversion; +use ndarray::{s, ArrayView2, ArrayViewMut2}; + +use crate::{block::K2Block, events::Binning, helpers::Shape2}; + +pub trait FrameForWriting: Sized { + const FRAME_WIDTH: usize; + const FRAME_HEIGHT: usize; + + /// The associated block type + type Block: K2Block; + + /// The matching read-only frame type + type ReadOnlyFrame: K2Frame; + + fn get_frame_id(&self) -> u32; + fn get_created_timestamp(&self) -> Instant; + fn get_modified_timestamp(&self) -> Instant; + fn set_modified_timestamp(&mut self, ts: &Instant); + fn get_payload(&self) -> &[u16]; + fn get_payload_mut(&mut self) -> &mut [u16]; + fn get_size_bytes() -> usize { + Self::FRAME_WIDTH * Self::FRAME_HEIGHT * std::mem::size_of::() + } + + fn empty(frame_id: u32, shm: &mut SharedSlabAllocator, acquisition_id: usize) -> Self { + Self::empty_with_timestamp::(frame_id, &Instant::now(), shm, acquisition_id) + } + + fn empty_from_block( + block: &B, + shm: &mut SharedSlabAllocator, + acquisition_id: usize, + ) -> Self { + Self::empty_with_timestamp::( + block.get_frame_id(), + &block.get_decoded_timestamp(), + shm, + acquisition_id, + ) + } + fn empty_with_timestamp( + frame_id: u32, + ts: &Instant, + shm: &mut SharedSlabAllocator, + acquisition_id: usize, + ) -> Self; + + fn writing_done(self, shm: &mut SharedSlabAllocator) -> Self::ReadOnlyFrame; + + fn reset(&mut self) { + self.get_tracker_mut().fill(false); + } + + fn reset_from_block(&mut self, block: &B) { + self.reset_with_timestamp::(block.get_frame_id(), &block.get_decoded_timestamp()) + } + + fn reset_with_timestamp(&mut self, frame_id: u32, ts: &Instant); + + fn as_array(&self) -> ArrayView2 { + let view = + ArrayView2::from_shape((Self::FRAME_HEIGHT, Self::FRAME_WIDTH), self.get_payload()) + .unwrap(); + view + } + + fn as_array_mut(&mut self) -> ArrayViewMut2 { + let view = ArrayViewMut2::from_shape( + (Self::FRAME_HEIGHT, Self::FRAME_WIDTH), + &mut self.get_payload_mut()[..], + ) + .unwrap(); + view + } + + /// + /// Copy the data from `block` over to this `K2Frame` + /// + /// This assumes that the block belongs to this frame and will panic if this is not the case. + /// + /// Needs to handle the following artifacts: + /// 1) Duplicate packets: with the assumption that this is a very rare event, we can let the assignment + /// continue as normal, as long as the tracking whether a block-position is already filled is + /// idempotent. If a duplicate comes in after a frame has finished, a new frame is kept around, + /// which is dropped after the timeout (because it is very unlikely that _all_ blocks of a frame + /// will be duplicated) + /// 2) Dropped packets: we can't keep frames with missing data around indefinitely, so we track the + /// last-modified timestamp and time out once we are certain the packet is not only late but really + /// dropped + /// 3) Out-of-order delivery + /// + fn assign_block(&mut self, block: &impl K2Block) { + let block_arr = block.as_array(); + assert_eq!(block.get_frame_id(), self.get_frame_id()); + let mut frame_arr = ArrayViewMut2::from_shape( + (Self::FRAME_HEIGHT, Self::FRAME_WIDTH), + &mut self.get_payload_mut()[..], + ) + .unwrap(); + let sector_x_offset = block.get_x_offset(); + let start_y = block.get_y_start() as usize; + let start_x = (block.get_x_start() + sector_x_offset) as usize; + let end_y = (block.get_y_end() + 1) as usize; + let end_x = (block.get_x_end() + 1 + sector_x_offset) as usize; + let mut dest_slice = frame_arr.slice_mut(s![start_y..end_y, start_x..end_x,]); + + dest_slice.assign(&block_arr); + self.track_block(block); + } + + fn is_finished(&self) -> bool { + return self.get_tracker().iter().all(|&x| x); + } + + fn get_tracker(&self) -> &Vec; + + fn get_tracker_mut(&mut self) -> &mut Vec; + + fn track_block(&mut self, block: &B) { + // blocks are identified according to their (y, x) start coordinates + let sector_x_offset = block.get_x_offset(); + let start_x = (block.get_x_start() + sector_x_offset) as usize; + let start_y = block.get_y_start() as usize; + + let block_width = (block.get_x_end() - block.get_x_start() + 1) as usize; + let block_height = (block.get_y_end() - block.get_y_start() + 1) as usize; + let num_blocks_x_direction = Self::FRAME_WIDTH / block_width; + + assert_eq!(block_width, B::BLOCK_WIDTH); + assert_eq!(block_height, B::BLOCK_HEIGHT); + + let block_id_x = start_x / block_width; + let block_id_y = start_y / block_height; + let block_id = num_blocks_x_direction * block_id_y + block_id_x; + + // println!("for start_x={} start_y={} have block_id={} block_id_x={} block_id_y={}", start_x, start_y, block_id, block_id_x, block_id_y); + let tracker = self.get_tracker_mut(); + tracker.get(block_id).or_else(|| { + println!("index out of bounds: {block_id} ..."); + println!( + "start_x = {start_x}, start_y = {start_y}, num_blocks_x_direction = {num_blocks_x_direction}", + ); + panic!("can't continue, sorry"); + }); + + tracker[block_id] = true; + + // update "mtime" + self.set_modified_timestamp(&Instant::now()); + } + + fn get_acquisition_id(&self) -> usize; +} + +pub trait K2Frame: Send { + const FRAME_WIDTH: usize; + const FRAME_HEIGHT: usize; + + type Block: K2Block; + type FrameForWriting: FrameForWriting; + + fn into_slot(self, shm: &SharedSlabAllocator) -> Slot; + fn free_payload(self, shm: &mut SharedSlabAllocator); + fn get_frame_id(&self) -> u32; + fn get_created_timestamp(&self) -> Instant; + fn get_modified_timestamp(&self) -> Instant; + fn get_pixel_size_bytes() -> usize { + std::mem::size_of::() + } + fn get_size_bytes() -> usize { + Self::FRAME_WIDTH * Self::FRAME_HEIGHT * Self::get_pixel_size_bytes() + } + + fn into_generic(self) -> GenericFrame; + + fn get_shape_for_binning(binning: &Binning) -> Shape2; + fn get_num_subframes(binning: &Binning) -> u32; + fn subframe_indexes(&self, binning: &Binning) -> Range; + fn get_subframe(&self, index: u32, binning: &Binning, shm: &SharedSlabAllocator) -> SubFrame; + fn get_acquisition_id(&self) -> usize; + + /// to grab an independent copy of only some metadata of the frame + fn get_meta(&self) -> FrameMeta { + FrameMeta { + acquisition_id: self.get_acquisition_id(), + frame_id: self.get_frame_id(), + created_timestamp: self.get_created_timestamp(), + } + } +} + +pub struct FrameMeta { + acquisition_id: usize, + frame_id: u32, + created_timestamp: Instant, +} + +impl FrameMeta { + pub fn new(acquisition_id: usize, frame_id: u32, created_timestamp: Instant) -> Self { + Self { + acquisition_id, + frame_id, + created_timestamp, + } + } + pub fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } + + pub fn get_created_timestamp(&self) -> Instant { + self.created_timestamp + } + + pub fn get_frame_id(&self) -> u32 { + self.frame_id + } +} + +pub struct SubFrame { + binning: Binning, + shape: Shape2, + slot: Slot, + + /// start index in u16 ("pixel") + pub start: usize, + + /// end index in u16 ("pixel") + pub end: usize, +} + +impl SubFrame { + pub fn new(binning: Binning, shape: Shape2, slot: Slot, start: usize, end: usize) -> SubFrame { + SubFrame { + binning, + shape, + slot, + start, + end, + } + } + + pub fn apply_to_payload(&self, f: impl Fn(&[u16])) { + let payload_raw: &[u16] = &bytemuck::cast_slice(self.slot.as_slice())[self.start..self.end]; + f(payload_raw) + } + + pub fn apply_to_payload_raw(&self, f: impl Fn(&[u8])) { + let payload_sliced: &[u16] = + &bytemuck::cast_slice(self.slot.as_slice())[self.start..self.end]; + let payload_raw = bytemuck::cast_slice(payload_sliced); + f(payload_raw) + } + + pub fn apply_to_payload_array(&self, mut f: impl FnMut(ArrayView2)) { + let payload_sliced: &[u16] = + &bytemuck::cast_slice(self.slot.as_slice())[self.start..self.end]; + let view = ArrayView2::from_shape(self.shape, payload_sliced).unwrap(); + f(view) + } + + pub fn get_binning(&self) -> Binning { + self.binning + } +} + +/// Once decoding, assembly etc. is finished we convert to this generic +/// frame type for downstream processing +pub struct GenericFrame { + /// a reference to the decoded payload of the whole frame + pub payload: SlotInfo, + + /// the frame id as received + pub frame_id: u32, + + /// when the first block was received, to handle dropped packets + pub created_timestamp: Instant, + + /// when the last block was received, to handle dropped packets + pub modified_timestamp: Instant, + + /// Acquisition id/generation + pub acquisition_id: usize, +} + +impl GenericFrame { + pub fn new( + payload: SlotInfo, + frame_id: u32, + created_timestamp: Instant, + modified_timestamp: Instant, + acquisition_id: usize, + ) -> GenericFrame { + GenericFrame { + payload, + frame_id, + created_timestamp, + modified_timestamp, + acquisition_id, + } + } + + pub fn get_frame_id(&self) -> u32 { + self.frame_id + } + + pub fn into_slot(self, shm: &SharedSlabAllocator) -> Slot { + shm.get(self.payload.slot_idx) + } + + pub fn into_payload(self) -> SlotInfo { + self.payload + } + + pub fn free_payload(self, shm: &mut SharedSlabAllocator) { + let slot_r = self.into_slot(shm); + shm.free_idx(slot_r.slot_idx); + } +} diff --git a/k2o/src/frame_is.rs b/k2o/src/frame_is.rs new file mode 100644 index 00000000..b59c73d4 --- /dev/null +++ b/k2o/src/frame_is.rs @@ -0,0 +1,247 @@ +use std::{ops::Range, time::Instant}; + +use ipc_test::{SharedSlabAllocator, Slot, SlotForWriting, SlotInfo}; +use itertools::Itertools; + +use crate::{ + block::K2Block, + block_is::K2ISBlock, + events::Binning, + frame::{FrameForWriting, GenericFrame, K2Frame, SubFrame}, + helpers::Shape2, +}; + +pub struct K2ISFrameForWriting { + /// the decoded payload of the whole frame + pub payload: SlotForWriting, + /// used to keep track of which block positions we have seen + tracker: Vec, + + subframe_idx: u8, + + /// the frame id as received + pub frame_id: u32, + + /// when the first block was received, to handle dropped packets + pub created_timestamp: Instant, + + /// when the last block was received, to handle dropped packets + pub modified_timestamp: Instant, + + /// Acquisition id/generation + pub acquisition_id: usize, +} + +impl FrameForWriting for K2ISFrameForWriting { + fn empty_with_timestamp( + frame_id: u32, + ts: &Instant, + shm: &mut SharedSlabAllocator, + acquisition_id: usize, + ) -> Self { + let mut payload = shm.get_mut().expect("get free SHM slot"); + assert!(payload.size >= Self::FRAME_WIDTH * Self::FRAME_HEIGHT); + + for item in payload.as_slice_mut() { + *item = 0; + } + + // how many blocks are there? in IS-mode, we have + // FRAME_WIDTH=2048, FRAME_HEIGHT=1860 + // block_width == 16, block_height == 930 + // -> we have 1860/930=2 blocks in y direction, and 2048/16=128 blocks in x direction + // -> 256 blocks per frame + // or, alternatively: 2048*1860/930/16 == 256 + let tracker: Vec = + vec![false; Self::FRAME_WIDTH * Self::FRAME_HEIGHT / B::DECODED_SIZE]; + + Self { + payload, + tracker, + frame_id, + created_timestamp: *ts, + modified_timestamp: Instant::now(), + subframe_idx: 0, + acquisition_id, + } + } + + fn reset_with_timestamp(&mut self, frame_id: u32, ts: &Instant) { + self.reset(); + self.created_timestamp = *ts; + self.modified_timestamp = *ts; + self.frame_id = frame_id; + self.subframe_idx = 0; + } + + fn set_modified_timestamp(&mut self, ts: &Instant) { + self.modified_timestamp = *ts; + } + + fn get_tracker_mut(&mut self) -> &mut Vec { + &mut self.tracker + } + + fn get_payload_mut(&mut self) -> &mut [u16] { + let slot_as_u16: &mut [u16] = bytemuck::cast_slice_mut(self.payload.as_slice_mut()); + slot_as_u16 + } + + fn get_tracker(&self) -> &Vec { + &self.tracker + } + + fn writing_done(self, shm: &mut SharedSlabAllocator) -> Self::ReadOnlyFrame { + let slot_info = shm.writing_done(self.payload); + K2ISFrame { + payload: slot_info, + frame_id: self.frame_id, + created_timestamp: self.created_timestamp, + modified_timestamp: self.modified_timestamp, + acquisition_id: self.acquisition_id, + } + } + + const FRAME_WIDTH: usize = 2048; + const FRAME_HEIGHT: usize = 1860; + + type Block = K2ISBlock; + type ReadOnlyFrame = K2ISFrame; + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn get_created_timestamp(&self) -> Instant { + self.created_timestamp + } + + fn get_modified_timestamp(&self) -> Instant { + self.modified_timestamp + } + + fn get_payload(&self) -> &[u16] { + let slot_as_u16: &[u16] = bytemuck::cast_slice(self.payload.as_slice()); + slot_as_u16 + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} + +impl K2ISFrameForWriting { + pub fn dump_finished_state(&self) { + let counts = self.tracker.iter().counts(); + println!( + "have {} hits and {} still missing", + counts.get(&true).unwrap_or(&0), + counts.get(&false).unwrap_or(&0) + ); + } +} + +pub struct K2ISFrame { + /// a reference to the decoded payload of the whole frame + pub payload: SlotInfo, + + /// the frame id as received + pub frame_id: u32, + + /// when the first block was received, to handle dropped packets + pub created_timestamp: Instant, + + /// when the last block was received, to handle dropped packets + pub modified_timestamp: Instant, + + /// Acquisition id/generation + pub acquisition_id: usize, +} + +impl K2Frame for K2ISFrame { + const FRAME_WIDTH: usize = 2048; + const FRAME_HEIGHT: usize = 1860; + + type Block = K2ISBlock; + type FrameForWriting = K2ISFrameForWriting; + + fn get_created_timestamp(&self) -> Instant { + self.created_timestamp + } + + fn get_modified_timestamp(&self) -> Instant { + self.modified_timestamp + } + + fn get_shape_for_binning(binning: &Binning) -> Shape2 { + match binning { + Binning::Bin1x => (Self::FRAME_HEIGHT, Self::FRAME_WIDTH), + Binning::Bin2x => (895, Self::FRAME_WIDTH), + Binning::Bin4x => (574, Self::FRAME_WIDTH), + Binning::Bin8x => (414, Self::FRAME_WIDTH), + } + } + + fn subframe_indexes(&self, binning: &Binning) -> Range { + match binning { + Binning::Bin1x => 0..1, + Binning::Bin2x => 0..2, + Binning::Bin4x => 0..3, + Binning::Bin8x => 0..4, + } + } + + fn get_subframe(&self, index: u32, binning: &Binning, shm: &SharedSlabAllocator) -> SubFrame { + let skip_rows: usize = match binning { + Binning::Bin1x => 0, + Binning::Bin2x => 4, + Binning::Bin4x => 4, + Binning::Bin8x => 4, + } + (index as usize * 66); + let shape = Self::get_shape_for_binning(binning); + let slot = shm.get(self.payload.slot_idx); + // let payload_raw = bytemuck::cast_slice(slot.as_slice()); + + let start = shape.1 * skip_rows; + let end = start + shape.0 * shape.1; + // let payload = &payload_raw[start..end]; + + SubFrame::new(*binning, shape, slot, start, end) + } + + fn get_num_subframes(binning: &Binning) -> u32 { + match binning { + Binning::Bin1x => 1, + Binning::Bin2x => 2, + Binning::Bin4x => 3, + Binning::Bin8x => 4, + } + } + + fn into_generic(self) -> GenericFrame { + GenericFrame::new( + self.payload, + self.frame_id, + self.created_timestamp, + self.modified_timestamp, + self.acquisition_id, + ) + } + + fn into_slot(self, shm: &SharedSlabAllocator) -> Slot { + shm.get(self.payload.slot_idx) + } + + fn free_payload(self, shm: &mut SharedSlabAllocator) { + let slot_r = self.into_slot(shm); + shm.free_idx(slot_r.slot_idx); + } + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} diff --git a/k2o/src/frame_summit.rs b/k2o/src/frame_summit.rs new file mode 100644 index 00000000..4c58b3f5 --- /dev/null +++ b/k2o/src/frame_summit.rs @@ -0,0 +1,221 @@ +use std::{ops::Range, time::Instant}; + +use ipc_test::{SharedSlabAllocator, SlotForWriting, SlotInfo}; + +use crate::{ + block::K2Block, + block_summit::K2SummitBlock, + events::Binning, + frame::{FrameForWriting, GenericFrame, K2Frame, SubFrame}, + helpers::Shape2, +}; + +pub struct K2SummitFrame { + /// the decoded payload of the whole frame + pub payload: SlotInfo, + + /// the frame id as received + pub frame_id: u32, + + /// when the first block was received, to handle dropped packets + pub created_timestamp: Instant, + + /// when the last block was received, to handle dropped packets + pub modified_timestamp: Instant, + + /// Acquisition id/generation + pub acquisition_id: usize, +} + +pub struct K2SummitFrameForWriting { + /// the decoded payload of the whole frame + pub payload: SlotForWriting, + // pub payload_slices: Vec, Dim<[usize; 2]>>>, + /// used to keep track of which block positions we have seen + tracker: Vec, + + /// the frame id as received + pub frame_id: u32, + + subframe_idx: u8, + + /// when the first block was received, to handle dropped packets + pub created_timestamp: Instant, + + /// when the last block was received, to handle dropped packets + pub modified_timestamp: Instant, + + /// Acquisition id/generation + pub acquisition_id: usize, +} + +impl K2SummitFrameForWriting {} + +impl FrameForWriting for K2SummitFrameForWriting { + const FRAME_WIDTH: usize = 4096; + const FRAME_HEIGHT: usize = 3840; + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn get_created_timestamp(&self) -> Instant { + self.created_timestamp + } + + fn get_modified_timestamp(&self) -> Instant { + self.modified_timestamp + } + + fn get_payload(&self) -> &[u16] { + let slot_as_u16: &[u16] = bytemuck::cast_slice(self.payload.as_slice()); + slot_as_u16 + } + + fn empty_with_timestamp( + frame_id: u32, + ts: &Instant, + shm: &mut SharedSlabAllocator, + acquisition_id: usize, + ) -> Self { + let mut payload = shm.get_mut().expect("get free SHM slot"); + assert!(payload.size >= Self::FRAME_WIDTH * Self::FRAME_HEIGHT); + + for item in payload.as_slice_mut() { + *item = 0; + } + + // how many blocks are there? in IS-mode, we have + // FRAME_WIDTH=2048, FRAME_HEIGHT=1860 + // block_width == 16, block_height == 930 + // -> we have 1860/930=2 blocks in y direction, and 2048/16=128 blocks in x direction + // -> 256 blocks per frame + // or, alternatively: 2048*1860/930/16 == 256 + let tracker: Vec = vec![false; 8 * B::BLOCKS_PER_SECTOR as usize]; + + Self { + payload, + tracker, + frame_id, + created_timestamp: *ts, + modified_timestamp: Instant::now(), + subframe_idx: 0, + acquisition_id, + } + } + + fn reset_with_timestamp(&mut self, frame_id: u32, ts: &Instant) { + self.reset(); + self.created_timestamp = *ts; + self.modified_timestamp = *ts; + self.frame_id = frame_id; + self.subframe_idx = 0; + } + + fn set_modified_timestamp(&mut self, ts: &Instant) { + self.modified_timestamp = *ts; + } + + fn get_tracker_mut(&mut self) -> &mut Vec { + &mut self.tracker + } + + fn get_payload_mut(&mut self) -> &mut [u16] { + let slot_as_u16: &mut [u16] = bytemuck::cast_slice_mut(self.payload.as_slice_mut()); + slot_as_u16 + } + + fn get_tracker(&self) -> &Vec { + &self.tracker + } + + type Block = K2SummitBlock; + + type ReadOnlyFrame = K2SummitFrame; + + fn writing_done(self, shm: &mut SharedSlabAllocator) -> Self::ReadOnlyFrame { + let slot_info = shm.writing_done(self.payload); + K2SummitFrame { + payload: slot_info, + frame_id: self.frame_id, + created_timestamp: self.created_timestamp, + modified_timestamp: self.modified_timestamp, + acquisition_id: self.acquisition_id, + } + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} + +impl K2Frame for K2SummitFrame { + type Block = K2SummitBlock; + + fn get_shape_for_binning(_binning: &Binning) -> Shape2 { + (Self::FRAME_HEIGHT, Self::FRAME_WIDTH) + } + + fn subframe_indexes(&self, _binning: &Binning) -> Range { + 0..1 + } + + fn get_subframe(&self, index: u32, binning: &Binning, shm: &SharedSlabAllocator) -> SubFrame { + let slot = shm.get(self.payload.slot_idx); + let start = 0; + assert!(index == 0, "can't handle sub frames yet"); + let end = start + Self::FRAME_HEIGHT * Self::FRAME_WIDTH; + + SubFrame::new( + *binning, + Self::get_shape_for_binning(binning), + slot, + start, + end, + ) + } + + fn get_num_subframes(_binning: &Binning) -> u32 { + 1 + } + + const FRAME_WIDTH: usize = 4096; + const FRAME_HEIGHT: usize = 3840; + + type FrameForWriting = K2SummitFrameForWriting; + + fn get_created_timestamp(&self) -> Instant { + self.created_timestamp + } + + fn get_modified_timestamp(&self) -> Instant { + self.modified_timestamp + } + + fn into_slot(self, shm: &SharedSlabAllocator) -> ipc_test::Slot { + shm.get(self.payload.slot_idx) + } + + fn free_payload(self, shm: &mut SharedSlabAllocator) { + let slot_r = self.into_slot(shm); + shm.free_idx(slot_r.slot_idx); + } + + fn get_frame_id(&self) -> u32 { + self.frame_id + } + + fn into_generic(self) -> GenericFrame { + GenericFrame::new( + self.payload, + self.frame_id, + self.created_timestamp, + self.modified_timestamp, + self.acquisition_id, + ) + } + + fn get_acquisition_id(&self) -> usize { + self.acquisition_id + } +} diff --git a/k2o/src/helpers.rs b/k2o/src/helpers.rs new file mode 100644 index 00000000..2dd7f6e0 --- /dev/null +++ b/k2o/src/helpers.rs @@ -0,0 +1,136 @@ +use std::{cmp, fs::File, os::unix::prelude::AsRawFd, time::Duration}; + +use log::info; +use ndarray::Ix; +use nix::{ + fcntl::{fallocate, FallocateFlags}, + sched::CpuSet, + unistd::Pid, +}; + +use crate::{ + block::K2Block, + decode::{decode_packet_size, HEADER_SIZE}, + net::{create_mcast_socket, K2oConnectionError}, +}; + +/// pin the current thread to a specific CPU +pub fn set_cpu_affinity(cpu_id: usize) { + let mut cpu_set = CpuSet::new(); + cpu_set.set(cpu_id).expect("could not set CPU affinity!"); + nix::sched::sched_setaffinity(Pid::from_raw(0), &cpu_set).expect("could not set CPU affinity!"); +} + +pub const CPU_AFF_DECODE_START: usize = 10; +pub const CPU_AFF_WRITER: usize = 18; +pub const CPU_AFF_ASSEMBLY: usize = 19; + +/// Operation modes for `preallocate` +#[derive(PartialEq)] +pub enum AllocateMode { + AllocateOnly, + ZeroFill, +} + +/// +/// Create a new file and allocate space for `num_frames` frames of size `bytes_per_frame`. +/// +pub fn preallocate(filename: &str, bytes_per_frame: usize, num_frames: usize, mode: AllocateMode) { + let file = File::options() + .create(true) + .write(true) + .open(filename) + .unwrap(); + let length = bytes_per_frame * num_frames; + let mut flags = FallocateFlags::empty(); + if mode == AllocateMode::AllocateOnly { + flags.insert(FallocateFlags::FALLOC_FL_KEEP_SIZE); + } + if length == 0 { + return; + } + fallocate(file.as_raw_fd(), flags, 0, length.try_into().unwrap()).unwrap_or_else(|e| { + panic!( + "fallocate {} for num_frames={} failed: {}", + filename, num_frames, e + ) + }); +} + +pub type Shape3 = (Ix, Ix, Ix); +pub type Shape2 = (Ix, Ix); + +pub fn recv_single( + sector_id: u8, +) -> Result { + let port: u32 = 2001 + (sector_id as u32); + let socket = create_mcast_socket(port, "225.1.1.1", "192.168.10.99")?; + let mut buf: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + let (number_of_bytes, _src_addr) = socket.recv_from(&mut buf).expect("recv_from failed"); + assert_eq!(number_of_bytes, PACKET_SIZE); + Ok(B::from_bytes(&buf, sector_id, 0)) +} + +/// +/// Receive a single packet and read the PACKET_SIZE from it +/// +pub fn recv_and_get_init() -> Result { + // finding the PACKET_SIZE: we just have a look at the first packet from the first sector + // we can't use the normal decoding in K2ISBlock.from_bytes here, because *drumroll* we don't know + // the size yet :) + const PORT: u32 = 2005; + let group = "225.1.1.1"; + let local = "192.168.10.99"; + let socket = create_mcast_socket(PORT, group, local)?; + info!("created multicast socket for group {group} local {local} port {PORT}"); + let mut buf: [u8; HEADER_SIZE] = [0; HEADER_SIZE]; + let (number_of_bytes, _src_addr) = socket.recv_from(&mut buf).expect("recv_from failed"); + info!("got initial packet"); + info!("initial packet: {buf:?}"); + assert_eq!(number_of_bytes, HEADER_SIZE); + Ok(decode_packet_size(&buf)) +} + +pub fn make_realtime(prio: u32) -> Result> { + let c = dbus::blocking::Connection::new_system()?; + + let proxy = c.with_proxy( + "org.freedesktop.RealtimeKit1", + "/org/freedesktop/RealtimeKit1", + Duration::from_millis(10000), + ); + use dbus::blocking::stdintf::org_freedesktop_dbus::Properties; + + // Make sure we don't fail by wanting too much + let max_prio: i32 = proxy.get("org.freedesktop.RealtimeKit1", "MaxRealtimePriority")?; + let prio = cmp::min(prio, max_prio as u32); + + // Enforce RLIMIT_RTPRIO, also a must before asking rtkit for rtprio + let max_rttime: i64 = proxy.get("org.freedesktop.RealtimeKit1", "RTTimeUSecMax")?; + let new_limit = libc::rlimit64 { + rlim_cur: max_rttime as u64, + rlim_max: max_rttime as u64, + }; + let mut old_limit = new_limit; + if unsafe { libc::getrlimit64(libc::RLIMIT_RTTIME, &mut old_limit) } < 0 { + return Err(Box::from("getrlimit failed")); + } + if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &new_limit) } < 0 { + return Err(Box::from("setrlimit failed")); + } + + // Finally, let's ask rtkit to make us realtime + let thread_id = unsafe { libc::syscall(libc::SYS_gettid) }; + let r = proxy.method_call( + "org.freedesktop.RealtimeKit1", + "MakeThreadRealtime", + (thread_id as u64, prio), + ); + + if r.is_err() { + unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &old_limit) }; + } + + r?; + Ok(prio) +} diff --git a/k2o/src/lib.rs b/k2o/src/lib.rs new file mode 100644 index 00000000..844b7a20 --- /dev/null +++ b/k2o/src/lib.rs @@ -0,0 +1,20 @@ +pub mod acquisition; +pub mod assemble; +pub mod block; +pub mod block_is; +pub mod block_summit; +pub mod cli_args; +pub mod control; +pub mod decode; +pub mod dio; +pub mod events; +pub mod frame; +pub mod frame_is; +pub mod frame_summit; +pub mod helpers; +pub mod net; +pub mod ordering; +pub mod params; +pub mod recv; +pub mod runtime; +pub mod tracing; diff --git a/k2o/src/net.rs b/k2o/src/net.rs new file mode 100644 index 00000000..bb031537 --- /dev/null +++ b/k2o/src/net.rs @@ -0,0 +1,71 @@ +use std::net::AddrParseError; +use std::net::Ipv4Addr; +use std::net::UdpSocket; + +#[derive(thiserror::Error, Debug)] +pub enum K2oConnectionError { + #[error("failed to parse address {address}: {err}")] + ParseError { + address: String, + err: AddrParseError, + }, + + #[error("could not join multicast group {group_addr} on {local_addr}: {err}")] + JoinError { + group_addr: String, + local_addr: String, + err: std::io::Error, + }, + + #[error("couldn't bind to {group_w_port}: {err}")] + BindError { + group_w_port: String, + err: std::io::Error, + }, + + #[error("I/O error: {err}")] + IoError { err: std::io::Error }, +} + +pub fn create_mcast_socket( + port: u32, + group: &str, + local: &str, +) -> Result { + // Compared to Python version, we create a bound socket here (we don't + // really need one, but shouldn't hurt) + let group_w_port = format!("{group}:{port}", group = group, port = port); + let socket = UdpSocket::bind(&group_w_port) + .map_err(|err| K2oConnectionError::BindError { group_w_port, err })?; + + // I'm leaving out the step of setting SO_REUSEADDR and SO_REUSEPORT, as I + // think we don't need them - we have to "route" all packets from/to a single port + // to the same process anyways, we can't distribute packets to different procesess. + + let group_addr: Ipv4Addr = group + .parse() + .map_err(|err| K2oConnectionError::ParseError { + address: group.to_owned(), + err, + })?; + let local_addr: Ipv4Addr = local + .parse() + .map_err(|err| K2oConnectionError::ParseError { + address: local.to_owned(), + err, + })?; + + // socket.connect(group_w_port).unwrap(); + + // Compared to the Python version, we are using the address of the local interface here, + // instead of using the interface index. Let's see if this works out! + socket + .join_multicast_v4(&group_addr, &local_addr) + .map_err(|err| K2oConnectionError::JoinError { + group_addr: group_addr.to_string(), + local_addr: local_addr.to_string(), + err, + })?; + + Ok(socket) +} diff --git a/k2o/src/ordering.rs b/k2o/src/ordering.rs new file mode 100644 index 00000000..361c4894 --- /dev/null +++ b/k2o/src/ordering.rs @@ -0,0 +1,460 @@ +use std::{ + cmp::Reverse, + collections::{BinaryHeap, HashSet}, +}; + +use itertools::Itertools; + +use crate::{acquisition::AcquisitionResult, frame::GenericFrame}; + +pub enum FrameOrderingResult { + Buffered, + Dropped, + NextFrame(FrameWithIdx), +} + +pub enum FrameWithIdx { + Frame(GenericFrame, u32), + DroppedFrame(GenericFrame, u32), +} + +impl From for AcquisitionResult { + fn from(val: FrameWithIdx) -> Self { + match val { + FrameWithIdx::Frame(frame, frame_idx) => AcquisitionResult::Frame(frame, frame_idx), + FrameWithIdx::DroppedFrame(frame, frame_idx) => { + AcquisitionResult::DroppedFrame(frame, frame_idx) + } + } + } +} + +impl FrameWithIdx { + fn get_frame(&self) -> &GenericFrame { + match self { + FrameWithIdx::Frame(frame, _idx) => frame, + FrameWithIdx::DroppedFrame(frame, _idx) => frame, + } + } + + fn get_idx(&self) -> u32 { + match self { + FrameWithIdx::Frame(_, idx) | FrameWithIdx::DroppedFrame(_, idx) => *idx, + } + } +} + +impl PartialEq for FrameWithIdx { + fn eq(&self, other: &Self) -> bool { + self.get_frame().get_frame_id() == other.get_frame().get_frame_id() + } +} + +impl PartialOrd for FrameWithIdx { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Eq for FrameWithIdx {} + +impl Ord for FrameWithIdx { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.get_frame() + .get_frame_id() + .cmp(&other.get_frame().get_frame_id()) + } +} + +impl FrameOrderingResult { + pub fn is_frame(&self) -> bool { + matches!(self, Self::NextFrame(..)) + } + + pub fn is_buffered(&self) -> bool { + matches!(self, Self::Buffered) + } + + pub fn is_dropped(&self) -> bool { + matches!(self, Self::Dropped) + } +} + +pub struct FrameOrdering { + frame_buffer: BinaryHeap>, + next_expected_frame_idx: u32, + dropped_idxs: HashSet, +} + +impl FrameOrdering { + // 100 => ~200ms of frames, so should be enough such that if we are unlucky + // and miss two frames in a 100ms window, we still don't have to re-allocate + const DEFAULT_CAPACITY: usize = 100; + + pub fn new(first_expected_frame_idx: u32) -> Self { + Self { + frame_buffer: BinaryHeap::with_capacity(Self::DEFAULT_CAPACITY), + next_expected_frame_idx: first_expected_frame_idx, + dropped_idxs: HashSet::new(), + } + } + + pub fn handle_frame(&mut self, frame_w_idx: FrameWithIdx) -> FrameOrderingResult { + let expected_frame_idx = self.next_expected_frame_idx; + + // Frame indices can be repeated, in case we drop a frame and later a + // block of said frame arrives, which starts a new frame with the old index. + // filter these out here: + if self.dropped_idxs.contains(&frame_w_idx.get_idx()) { + return FrameOrderingResult::Dropped; + } + if let FrameWithIdx::DroppedFrame(_, idx) = frame_w_idx { + self.dropped_idxs.insert(idx); + } + + if frame_w_idx.get_idx() == expected_frame_idx { + self.next_expected_frame_idx = expected_frame_idx + 1; + FrameOrderingResult::NextFrame(frame_w_idx) + } else { + self.insert_sorted(frame_w_idx); + FrameOrderingResult::Buffered + } + } + + pub fn maybe_get_next_frame(&mut self) -> Option { + // cases: + // 1) `self.frame_buffer` is empty -> no next frame + // 2) `self.frame_buffer` is non-empty and starts the expected frame -> emit first frame + + match self.frame_buffer.peek() { + Some(Reverse(frame)) => { + let expected_frame_idx = self.next_expected_frame_idx; + if frame.get_idx() == expected_frame_idx { + if let Some(Reverse(f)) = self.frame_buffer.pop() { + self.next_expected_frame_idx = f.get_idx() + 1; + Some(f) + } else { + unreachable!("should have Some(frame) here, we just peeked!") + } + } else { + None + } + } + None => None, + } + } + + /// Insert `frame` into the buffer at the correct position. Will panic if + /// this `FrameOrdering` instance is not compacted. + fn insert_sorted(&mut self, frame_w_idx: FrameWithIdx) { + self.frame_buffer.push(Reverse(frame_w_idx)); + } + + pub fn is_empty(&self) -> bool { + self.frame_buffer.len() == 0 + } + + pub(crate) fn dump_if_nonempty(&self) { + if !self.is_empty() { + println!("\n\nDUMP START"); + println!("next expected frame idx: {}", self.next_expected_frame_idx); + for rf in self.frame_buffer.iter().sorted() { + let Reverse(f) = rf; + print!("{:?} - ", f.get_idx()); + } + println!("\n\nDUMP END"); + } + } +} + +#[cfg(test)] +mod tests { + use ipc_test::SharedSlabAllocator; + use tempfile::tempdir; + + use crate::{ + frame::{FrameForWriting, K2Frame}, + frame_is::{K2ISFrame, K2ISFrameForWriting}, + ordering::FrameWithIdx, + }; + + use super::FrameOrdering; + + #[test] + fn test_direct_return() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("test.socket"); + + let mut ordering: FrameOrdering = FrameOrdering::new(0); + + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + let f1w: K2ISFrameForWriting = K2ISFrameForWriting::empty(1, &mut ssa, 0); + let f1 = f1w.writing_done(&mut ssa); + let f2w: K2ISFrameForWriting = K2ISFrameForWriting::empty(2, &mut ssa, 0); + let f2 = f2w.writing_done(&mut ssa); + let f3w: K2ISFrameForWriting = K2ISFrameForWriting::empty(3, &mut ssa, 0); + let f3 = f3w.writing_done(&mut ssa); + + assert_eq!(ordering.frame_buffer.len(), 0); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f1.into_generic(), 0)) + .is_frame()); + assert_eq!(ordering.frame_buffer.len(), 0); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f2.into_generic(), 1)) + .is_frame()); + assert_eq!(ordering.frame_buffer.len(), 0); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f3.into_generic(), 2)) + .is_frame()); + + assert_eq!(ordering.next_expected_frame_idx, 3); + + assert_eq!(ordering.frame_buffer.len(), 0); + assert!(ordering.maybe_get_next_frame().is_none()); + } + + #[test] + fn test_one_missing() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("test.socket"); + let mut ordering: FrameOrdering = FrameOrdering::new(0); + + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + let f1w: K2ISFrameForWriting = K2ISFrameForWriting::empty(1, &mut ssa, 0); + let f1 = f1w.writing_done(&mut ssa); + let f2w: K2ISFrameForWriting = K2ISFrameForWriting::empty(2, &mut ssa, 0); + let f2 = f2w.writing_done(&mut ssa); + let f3w: K2ISFrameForWriting = K2ISFrameForWriting::empty(3, &mut ssa, 0); + let f3 = f3w.writing_done(&mut ssa); + + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f1.into_generic(), 0)) + .is_frame()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f3.into_generic(), 2)) + .is_buffered()); + + // f1 was the last emitted frame, f3 is buffered, f2 is expected: + assert_eq!(ordering.next_expected_frame_idx, 1); + assert_eq!(ordering.frame_buffer.len(), 1); + assert!(ordering.maybe_get_next_frame().is_none()); + + // now, we push in f2, which is directly emitted, because its frame id + // matches the currently expected id (f1 + 1): + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f2.into_generic(), 1)) + .is_frame()); + assert_eq!(ordering.next_expected_frame_idx, 2); + assert_eq!(ordering.frame_buffer.len(), 1); + + assert!( + // we get a frame, and it has to be f3 with idx 2: + match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 2 + } + None => false, + } + ); + } + + #[test] + fn test_multiple_buffered() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("test.socket"); + let mut ordering: FrameOrdering = FrameOrdering::new(0); + + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + let f1w: K2ISFrameForWriting = K2ISFrameForWriting::empty(1, &mut ssa, 0); + let f1 = f1w.writing_done(&mut ssa); + let f2w: K2ISFrameForWriting = K2ISFrameForWriting::empty(2, &mut ssa, 0); + let f2 = f2w.writing_done(&mut ssa); + let f3w: K2ISFrameForWriting = K2ISFrameForWriting::empty(3, &mut ssa, 0); + let f3 = f3w.writing_done(&mut ssa); + let f4w: K2ISFrameForWriting = K2ISFrameForWriting::empty(4, &mut ssa, 0); + let f4 = f4w.writing_done(&mut ssa); + + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f1.into_generic(), 0)) + .is_frame()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f3.into_generic(), 2)) + .is_buffered()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f4.into_generic(), 3)) + .is_buffered()); + + // f1 was the last emitted frame, f3 and f4 are buffered: + assert_eq!(ordering.next_expected_frame_idx, 1); + assert_eq!(ordering.frame_buffer.len(), 2); + assert!(ordering.maybe_get_next_frame().is_none()); + + // now, we push in f2, which is directly emitted, because its frame id + // matches the currently expected id (f1 + 1): + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f2.into_generic(), 1)) + .is_frame()); + assert_eq!(ordering.next_expected_frame_idx, 2); + assert_eq!(ordering.frame_buffer.len(), 2); + + assert!( + // we get a frame, and it has to be frame id 3: + match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 2 + } + None => false, + } + ); + + assert!( + // we get a frame, and it has to be frame id 4: + match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 3 + } + None => false, + } + ); + } + + #[test] + fn test_multiple_holes() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("test.socket"); + // something like this: f1 _ f3 _ f5 + let mut ordering: FrameOrdering = FrameOrdering::new(0); + + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + let f1w: K2ISFrameForWriting = K2ISFrameForWriting::empty(1, &mut ssa, 0); + let f1 = f1w.writing_done(&mut ssa); + let f2w: K2ISFrameForWriting = K2ISFrameForWriting::empty(2, &mut ssa, 0); + let f2 = f2w.writing_done(&mut ssa); + let f3w: K2ISFrameForWriting = K2ISFrameForWriting::empty(3, &mut ssa, 0); + let f3 = f3w.writing_done(&mut ssa); + let f4w: K2ISFrameForWriting = K2ISFrameForWriting::empty(4, &mut ssa, 0); + let f4 = f4w.writing_done(&mut ssa); + let f5w: K2ISFrameForWriting = K2ISFrameForWriting::empty(5, &mut ssa, 0); + let f5 = f5w.writing_done(&mut ssa); + + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f1.into_generic(), 0)) + .is_frame()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f3.into_generic(), 2)) + .is_buffered()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f5.into_generic(), 4)) + .is_buffered()); + + // f1 was the last emitted frame, f3 and f5 are buffered: + assert_eq!(ordering.next_expected_frame_idx, 1); + assert_eq!(ordering.frame_buffer.len(), 2); + assert!(ordering.maybe_get_next_frame().is_none()); + + // now, we push in f2, which is directly emitted, because its frame id + // matches the currently expected id (f1 + 1): + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f2.into_generic(), 1)) + .is_frame()); + assert_eq!(ordering.next_expected_frame_idx, 2); + assert_eq!(ordering.frame_buffer.len(), 2); + + // now, we push in f4, which is buffered: + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f4.into_generic(), 3)) + .is_buffered()); + assert_eq!(ordering.next_expected_frame_idx, 2); + assert_eq!(ordering.frame_buffer.len(), 3); + + // and we can now consume the buffered frames: + assert!(match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 2 + } + None => false, + }); + assert_eq!(ordering.frame_buffer.len(), 2); + assert!(match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 3 + } + None => false, + }); + assert_eq!(ordering.frame_buffer.len(), 1); + assert!(match ordering.maybe_get_next_frame() { + Some(frame) => { + frame.get_idx() == 4 + } + None => false, + }); + assert_eq!(ordering.frame_buffer.len(), 0); + assert!(ordering.maybe_get_next_frame().is_none()); + } + + #[test] + fn test_drop_duplicates() { + let socket_dir = tempdir().unwrap(); + let socket_as_path = socket_dir.into_path().join("test.socket"); + let mut ordering: FrameOrdering = FrameOrdering::new(0); + + let mut ssa = SharedSlabAllocator::new( + 10, + K2ISFrame::FRAME_HEIGHT * K2ISFrame::FRAME_WIDTH * std::mem::size_of::(), + false, + &socket_as_path, + ) + .expect("create SHM area for testing"); + + let f1w: K2ISFrameForWriting = K2ISFrameForWriting::empty(1, &mut ssa, 0); + let f1 = f1w.writing_done(&mut ssa); + let f2w: K2ISFrameForWriting = K2ISFrameForWriting::empty(2, &mut ssa, 0); + let f2 = f2w.writing_done(&mut ssa); + let f3w: K2ISFrameForWriting = K2ISFrameForWriting::empty(3, &mut ssa, 0); + let f3 = f3w.writing_done(&mut ssa); + let f4w: K2ISFrameForWriting = K2ISFrameForWriting::empty(4, &mut ssa, 0); + let f4 = f4w.writing_done(&mut ssa); + + assert!(ordering + .handle_frame(FrameWithIdx::DroppedFrame(f1.into_generic(), 0)) + .is_frame()); + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f2.into_generic(), 1)) + .is_frame()); + assert!(ordering + .handle_frame(FrameWithIdx::DroppedFrame(f3.into_generic(), 0)) + .is_dropped()); // note duplicate index! + assert!(ordering + .handle_frame(FrameWithIdx::Frame(f4.into_generic(), 2)) + .is_frame()); + } +} diff --git a/k2o/src/params.rs b/k2o/src/params.rs new file mode 100644 index 00000000..095e1e6b --- /dev/null +++ b/k2o/src/params.rs @@ -0,0 +1,5 @@ +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CameraMode { + IS, + Summit, +} diff --git a/k2o/src/recv.rs b/k2o/src/recv.rs new file mode 100644 index 00000000..db9c334c --- /dev/null +++ b/k2o/src/recv.rs @@ -0,0 +1,278 @@ +use std::{ + io::ErrorKind, + sync::{Arc, Condvar, Mutex}, + time::Duration, +}; + +use crossbeam::channel::{Receiver, Sender, TryRecvError}; +use log::{debug, error, info, warn}; + +use crate::{ + block::{BlockRouteInfo, K2Block}, + events::{AcquisitionSync, EventBus, EventMsg, EventReceiver, Events}, + helpers::{make_realtime, set_cpu_affinity, CPU_AFF_DECODE_START}, + net::{create_mcast_socket, K2oConnectionError}, +}; + +#[derive(Debug, Clone)] +pub struct RecvConfig { + pub realtime: bool, +} + +impl RecvConfig { + pub fn new(realtime: bool) -> Self { + Self { realtime } + } +} + +#[derive(PartialEq)] +enum RecvState { + Initializing, + + /// Receiving UDP packets, but not doing anything with them + Idle, + + /// Receiving and decoding blocks, but not passing them on downstream to assembly, + /// goes to `Receiving` state once a block with sync flag has been received + WaitForSync { + acquisition_id: usize, + }, + + /// When receiving the next block, go to the `WaitForFrame` state + WaitForNext { + acquisition_id: usize, + }, + + /// Start receiving and decoding at the start of the specified frame id, + /// regardless of sync status + WaitForFrame { + acquisition_id: usize, + frame_id: u32, + }, + + /// Recveicing and decoding packets, and sending the decoded packets down + /// the pipeline + Receiving { + acquisition_id: usize, + }, +} + +fn block_for_bytes( + buf: &[u8], + chan: &Receiver, + acquisition_id: usize, + sector_id: u8, +) -> B { + let block: B = { + let maybe_block = chan.try_recv(); + match maybe_block { + Err(_) => B::from_bytes(buf, sector_id, acquisition_id), + Ok(mut b) => { + b.replace_with(buf, sector_id, acquisition_id); + b + } + } + }; + block.validate(); + block +} + +fn recv_decode_impl( + sector_id: u8, + port: u32, + assembly_channel: &Sender<(B, BlockRouteInfo)>, + recycle_blocks_rx: &Receiver, + recycle_blocks_tx: &Sender, + events_rx: &EventReceiver, + events: &Events, + local_addr: String, + first_block_counter: Option, Condvar)>>, + config: &RecvConfig, +) -> Result<(), K2oConnectionError> { + let socket = create_mcast_socket(port, "225.1.1.1", &local_addr)?; + let mut buf: [u8; PACKET_SIZE] = [0; PACKET_SIZE]; + + if config.realtime { + match make_realtime(50) { + Ok(prio) => info!("successfully enabled realtime priority {prio}"), + Err(e) => error!("failed to set realtime priority: {e:?}"), + } + } + + socket + .set_read_timeout(Some(Duration::from_millis(10))) + .map_err(|err| K2oConnectionError::IoError { err: err })?; + + let mut state = RecvState::Initializing; + + info!("Listening on {local_addr}:{port} for sector {sector_id}"); + + let aff = CPU_AFF_DECODE_START + sector_id as usize; + info!("Pinning to CPU {aff} for sector {sector_id}"); + set_cpu_affinity(aff); + + // FIXME: at startup, first wait for all sectors to have received at least + // one block + + loop { + match events_rx.try_recv() { + Ok(EventMsg::ArmSectors { + params, + acquisition_id, + }) => { + debug!("sector {sector_id} waiting for acquisition {acquisition_id}"); + state = match params.sync { + AcquisitionSync::Immediately => RecvState::WaitForNext { acquisition_id }, + AcquisitionSync::WaitForSync => RecvState::WaitForSync { acquisition_id }, + }; + } + Ok(EventMsg::Shutdown {}) => break, + Err(TryRecvError::Disconnected) => break, + Err(TryRecvError::Empty) => {} // this is fine. + Ok(_) => {} // unknown event in the channel, just continue. + } + + // no matter the current state, we receive the UDP packets and read them + // into a buffer: + match socket.recv_from(&mut buf) { + Ok((number_of_bytes, _src_addr)) => { + assert_eq!(number_of_bytes, B::PACKET_SIZE); + } + Err(error) if error.kind() == ErrorKind::WouldBlock => continue, + Err(error) if error.kind() == ErrorKind::Interrupted => continue, + Err(error) => return Err(K2oConnectionError::IoError { err: error }), + } + + if state == RecvState::Initializing { + if let Some(counter) = &first_block_counter { + let (lock, cvar) = &**counter; + let mut counter = lock.lock().unwrap(); + *counter += 1; + cvar.notify_all(); + } + state = RecvState::Idle; + }; + + // if we are not armed for acquisition, we don't decode the buffer into + // a block: + if state == RecvState::Idle { + // we use a "fake" acquisition id here, because there is no acquisition running: + let block = block_for_bytes(&buf, recycle_blocks_rx, 0, sector_id); + recycle_blocks_tx.send(block).unwrap(); + continue; + } + + match state { + RecvState::WaitForFrame { + acquisition_id, + frame_id, + } => { + let block = block_for_bytes(&buf, recycle_blocks_rx, acquisition_id, sector_id); + if block.get_frame_id() == frame_id { + events.send(&EventMsg::AcquisitionStartedSector { + sector_id, + frame_id: block.get_frame_id(), + acquisition_id, + }); + state = RecvState::Receiving { acquisition_id }; + // send out the first block: + let route_info = BlockRouteInfo::new(&block); + if assembly_channel.send((block, route_info)).is_err() { + events.send(&EventMsg::AcquisitionError { + msg: "failed to send to assembly threads".to_string(), + }); + break; + } + } + } + RecvState::WaitForNext { acquisition_id } => { + let block = block_for_bytes(&buf, recycle_blocks_rx, acquisition_id, sector_id); + state = RecvState::WaitForFrame { + acquisition_id, + frame_id: block.get_frame_id() + 1, + } + } + RecvState::WaitForSync { acquisition_id } => { + let block = block_for_bytes(&buf, recycle_blocks_rx, acquisition_id, sector_id); + if block.sync_is_set() { + events.send(&EventMsg::AcquisitionStartedSector { + sector_id, + frame_id: block.get_frame_id(), + acquisition_id, + }); + state = RecvState::Receiving { acquisition_id }; + } else { + let block = block_for_bytes(&buf, recycle_blocks_rx, acquisition_id, sector_id); + // recycle blocks directly if we don't forward them to the frame + // assembly thread: + recycle_blocks_tx.send(block).unwrap(); + + // FIXME: this is an opportunity to de-allocate + // memory, if we had buffered "too much" beforehand. + // Add a "high watermark" queue fill level and only recycle + // blocks if we are below. + } + } + RecvState::Receiving { acquisition_id } => { + let block = block_for_bytes(&buf, recycle_blocks_rx, acquisition_id, sector_id); + let route_info = BlockRouteInfo::new(&block); + let l = assembly_channel.len(); + if l > 400 && l % 100 == 0 { + warn!("assembly_channel is backed up, len={l} sector={sector_id}"); + } + if l > 10000 { + // make sure we don't consume all available memory: + error!("too many blocks in assembly_channel, bailing out"); + events.send(&EventMsg::AcquisitionError { + msg: format!("too many blocks in assembly_channel for sector {sector_id}"), + }); + break; + } + if assembly_channel.send((block, route_info)).is_err() { + events.send(&EventMsg::AcquisitionError { + msg: "failed to send to assembly threads".to_string(), + }); + break; + } + } + RecvState::Idle | RecvState::Initializing => { + // handled before the match + } + } + } + + Ok(()) +} + +/// receive and decode a block from the specified sector, and send it to the +/// central assembly thread +#[allow(clippy::too_many_arguments)] +pub fn recv_decode_loop( + sector_id: u8, + port: u32, + assembly_channel: &Sender<(B, BlockRouteInfo)>, + recycle_blocks_rx: &Receiver, + recycle_blocks_tx: &Sender, + events_rx: &EventReceiver, + events: &Events, + local_addr: String, + first_block_counter: Option, Condvar)>>, + config: &RecvConfig, +) { + if let Err(error) = recv_decode_impl::( + sector_id, + port, + assembly_channel, + recycle_blocks_rx, + recycle_blocks_tx, + events_rx, + events, + local_addr, + first_block_counter, + config, + ) { + let msg = format!("receiving thread for sector {sector_id} shutting down: {error}"); + error!("{msg}"); + events.send(&EventMsg::AcquisitionError { msg }); + } +} diff --git a/k2o/src/runtime.rs b/k2o/src/runtime.rs new file mode 100644 index 00000000..b17ca694 --- /dev/null +++ b/k2o/src/runtime.rs @@ -0,0 +1,649 @@ +use crate::acquisition::{acquisition_loop, frame_in_acquisition, AcquisitionResult}; +use crate::assemble::{assembler_main, AssemblyResult}; +use crate::block::{BlockRouteInfo, K2Block}; +use crate::block_is::K2ISBlock; +use crate::block_summit::K2SummitBlock; +use crate::control::{control_loop, AcquisitionState, StateError, StateTracker}; +use crate::events::{AcquisitionParams, ChannelEventBus, EventBus, EventMsg, Events, MessagePump}; +use crate::frame::{GenericFrame, K2Frame}; +use crate::frame_is::K2ISFrame; +use crate::frame_summit::K2SummitFrame; +use crate::helpers::{set_cpu_affinity, CPU_AFF_WRITER}; +use crate::params::CameraMode; +use crate::recv::{recv_decode_loop, RecvConfig}; +use common::tracing::get_tracer; +use crossbeam::channel::{unbounded, Receiver, RecvTimeoutError, SendError, Sender, TryRecvError}; +use ipc_test::{SHMHandle, SharedSlabAllocator}; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread::JoinHandle; +use std::time::{Duration, Instant}; + +use log::{debug, info}; +use opentelemetry::trace::Tracer; +use opentelemetry::Context; + +#[derive(Debug, Clone)] +pub struct AddrConfig { + top: String, + bottom: String, +} + +#[derive(Debug, Clone)] +pub struct AssemblyConfig { + pub timeout: Duration, + pub realtime: bool, +} + +impl AssemblyConfig { + pub fn new(timeout: Duration, realtime: bool) -> Self { + Self { timeout, realtime } + } +} + +impl Default for AssemblyConfig { + fn default() -> Self { + Self { + timeout: Duration::from_millis(100), + realtime: true, + } + } +} + +impl AddrConfig { + pub fn new(top: &str, bottom: &str) -> Self { + Self { + top: top.to_string(), + bottom: bottom.to_string(), + } + } + + pub fn addr_for_sector(&self, sector: u8) -> String { + if sector < 4 { + self.bottom.clone() + } else { + self.top.clone() + } + } + + pub fn port_for_sector(&self, sector_id: u8) -> u32 { + 2001 + sector_id as u32 + } +} + +fn k2_bg_thread< + const PACKET_SIZE: usize, // FIXME: use associated B::PACKET_SIZE instead of this generic? + F: K2Frame, + B: K2Block, +>( + events: &Events, + addr_config: &AddrConfig, + pump: MessagePump, + writer_dest_channel: Sender>, // either going to the consumer, or back to the assembly + shm: SharedSlabAllocator, + asm_config: AssemblyConfig, + recv_config: RecvConfig, +) { + let tracer = get_tracer(); + tracer.in_span("start_threads", |_cx| { + let ids = 0..=7u8; + + let (recycle_blocks_tx, recycle_blocks_rx) = unbounded::(); + + let ctx = Context::current(); + + let first_block_counter = Arc::new((Mutex::new(0u8), Condvar::new())); + + crossbeam::scope(|s| { + info!("spawning recv threads..."); + let (assembly_tx, assembly_rx) = unbounded::<(B, BlockRouteInfo)>(); + for sector_id in ids.clone() { + let tx = assembly_tx.clone(); + let recycle_clone_rx = recycle_blocks_rx.clone(); + let recycle_clone_tx = recycle_blocks_tx.clone(); + let events_rx = events.subscribe(); + let addr = addr_config.addr_for_sector(sector_id); + let port = addr_config.port_for_sector(sector_id); + let decode_ctx = ctx.clone(); + let sector_counter = Arc::clone(&first_block_counter); + let recv_config = recv_config.clone(); + s.builder() + .name(format!("recv-decode-{}", sector_id)) + .spawn(move |_| { + let _guard = decode_ctx.attach(); + recv_decode_loop::( + sector_id, + port, + &tx, + &recycle_clone_rx, + &recycle_clone_tx, + &events_rx, + events, + addr, + Some(sector_counter), + &recv_config, + ); + }) + .expect("spawn recv+decode thread"); + } + + let (full_frames_tx, full_frames_rx) = unbounded::>(); + // let (recycle_frames_tx, recycle_frames_rx) = unbounded::(); + + let asm_events_rx = events.subscribe(); + let asm_ctx = ctx.clone(); + let asm_shm_handle = shm.get_handle().os_handle; + + info!("spawning assembly threads..."); + + // assembly main thread: + s.builder() + .name("assembly".to_string()) + .spawn(move |_| { + let asm_shm = + SharedSlabAllocator::connect(&asm_shm_handle).expect("connect to shm"); + + //set_cpu_affinity(CPU_AFF_ASSEMBLY); + //frame_assembler(&assembly_rx, &full_frames_tx); + let _guard = asm_ctx.attach(); + assembler_main::( + &assembly_rx, + &full_frames_tx, + &recycle_blocks_tx, + asm_events_rx, + asm_shm, + &asm_config.timeout, + asm_config.realtime, + ); + }) + .expect("could not spawn assembly thread"); + + let writer_ctx = ctx.clone(); + + let acq_shm_handle = shm.get_handle(); + + info!("spawning acquisition threads..."); + + // acquisition/writer thread: + let w1rx = full_frames_rx; + let writer_events_rx = events.subscribe(); + s.builder() + .name("acquisition".to_string()) + .spawn(move |_| { + set_cpu_affinity(CPU_AFF_WRITER); + let _guard = writer_ctx.attach(); + let acq_shm = SharedSlabAllocator::connect(&acq_shm_handle.os_handle) + .expect("connect to shm"); + + acquisition_loop( + &w1rx, + &writer_dest_channel, + &writer_events_rx, + events, + acq_shm, + ); + }) + .expect("could not spawn acquisition thread"); + + let (lock, cvar) = &*first_block_counter; + + info!("waiting for first blocks..."); + + // if an error happens while waiting for the first block, we need to + // propagate it, which is why we alternate between pumping events + // and waiting for the condition: + loop { + pump.do_pump_timeout(events, Duration::from_millis(10)) + .unwrap(); + if let Ok(result) = cvar.wait_timeout_while( + lock.lock().unwrap(), + Duration::from_millis(1), + |counter| (*counter as usize) < ids.len(), + ) { + if result.1.timed_out() { + continue; + } else { + drop(result); + break; + } + } + } + + info!("sending Init event"); + + events.send(&EventMsg::Init {}); + + info!("starting control loop..."); + + control_loop(events, &Some(pump)); + }) + .unwrap(); + }); +} + +/// +/// The background thread is started when arming the acquisition object, +/// and stops when `Acquisition::stop` is called. +/// +/// In turn, this thread starts and manages receiver/decoder/assembly/writer threads. +/// +/// Communication with the background thread(s) is handled via the event bus, +/// that is, `k2o::events::Events` and `k2o::events::EventReceiver`. +/// +pub fn start_bg_thread( + events: Events, + addr_config: AddrConfig, + pump: MessagePump, + + // Channel from the writer to the next frame consumer + tx_from_writer: Sender>, + + shm_handle: SHMHandle, + asm_config: &AssemblyConfig, + recv_config: &RecvConfig, +) -> JoinHandle<()> { + let thread_builder = std::thread::Builder::new(); + let ctx = Context::current(); + let asm_config = asm_config.clone(); + let recv_config = recv_config.clone(); + thread_builder + .name("k2_bg_thread".to_string()) + .spawn(move || { + let _guard = ctx.attach(); + let shm = SharedSlabAllocator::connect(&shm_handle.os_handle).expect("connect to shm"); + k2_bg_thread::( + &events, + &addr_config, + pump, + tx_from_writer, + shm, + asm_config, + recv_config, + ); + }) + .expect("failed to start k2 background thread") +} + +#[derive(Debug)] +pub enum RuntimeError { + Timeout, + Disconnected, + ConfigurationError, +} + +impl From> for RuntimeError { + fn from(_: SendError) -> Self { + RuntimeError::Disconnected + } +} + +impl From for RuntimeError { + fn from(e: RecvTimeoutError) -> Self { + match e { + RecvTimeoutError::Timeout => RuntimeError::Timeout, + RecvTimeoutError::Disconnected => RuntimeError::Disconnected, + } + } +} + +pub enum UpdateStateResult { + DidUpdate, + NoNewMessage, +} + +pub enum WaitResult { + Timeout, + PredSuccess, +} + +impl WaitResult { + pub fn is_success(&self) -> bool { + matches!(self, WaitResult::PredSuccess) + } +} + +#[derive(Debug, Clone)] +pub struct AcquisitionRuntimeConfig { + pub enable_frame_iterator: bool, + pub recv_realtime: bool, + pub assembly_realtime: bool, + pub mode: CameraMode, + pub addr_config: AddrConfig, +} + +impl AcquisitionRuntimeConfig { + pub fn new( + enable_frame_iterator: bool, + recv_realtime: bool, + assembly_realtime: bool, + mode: CameraMode, + addr_config: AddrConfig, + ) -> Self { + Self { + enable_frame_iterator, + recv_realtime, + assembly_realtime, + mode, + addr_config, + } + } +} + +/// The `AcquisitionRuntime` starts and communicates with a background thread, +/// keeps track of the state via the `StateTracker`, and owns the shared memory +/// area. +/// +/// This runtime is kept alive over multiple acquisitions, and as such the +/// parameters (like IS/Summit mode, network settings, shm socket path, frame +/// iterator settings) cannot be changed without restarting the runtime. +/// +/// It is possible to change per-acquisition settings, though, like filename and +/// file writer settings, number of frames for the acquisition, and the camera +/// sync mode. +pub struct AcquisitionRuntime { + // bg_thread is an Option so we are able to join by moving out of it + bg_thread: Option>, + main_events_tx: Sender, + main_events_rx: Receiver, + + /// This is where an "external" frame consumer gets their frames: + rx_writer_to_consumer: Receiver>, + + state_tracker: StateTracker, + + shm: SharedSlabAllocator, + + current_acquisition_id: usize, + + config: AcquisitionRuntimeConfig, +} + +impl AcquisitionRuntime { + pub fn new(config: &AcquisitionRuntimeConfig, shm: SHMHandle) -> Self { + let events: Events = ChannelEventBus::new(); + let pump = MessagePump::new(&events); + let (main_events_tx, main_events_rx) = pump.get_ext_channels(); + + let (tx_writer_to_consumer, rx_writer_to_consumer) = + unbounded::>(); + + // Two main configuration options: + // 1) Writer enabled or not (currently can't disable writer) + // 2) "Frame Consumer" enabled or not + // + // They are configured by wiring up channels in the correct way. + let os_handle = shm.os_handle.clone(); + let bg_thread = if config.enable_frame_iterator { + // Frame consumer enabled -> after writing, the writer thread should send the frames + // to the `tx_frame_consumer` channel + let asm_config = + AssemblyConfig::new(Duration::from_millis(25), config.assembly_realtime); + let recv_config = RecvConfig::new(config.recv_realtime); + match config.mode { + CameraMode::IS => Some(start_bg_thread::( + events, + config.addr_config.clone(), + pump, + tx_writer_to_consumer, + shm, + &asm_config, + &recv_config, + )), + CameraMode::Summit => Some(start_bg_thread::< + K2SummitFrame, + { K2SummitBlock::PACKET_SIZE }, + >( + events, + config.addr_config.clone(), + pump, + tx_writer_to_consumer, + shm, + &asm_config, + &recv_config, + )), + } + } else { + // Directly recycle after writing: + todo!("implement a tx_writer_to_consumer that just frees the shm"); + }; + + let mut state_tracker = StateTracker::new(); + + // Wait for the init event, so we know the background thread is started. + // We currently don't wait for all threads, but that's fine, as it's + // most important that the receiver for control messages is already + // listening, as events are buffered in a channel: + let tracer = get_tracer(); + tracer.in_span("AcquisitionRuntime wait_for_init", |_cx| loop { + match main_events_rx.recv_timeout(Duration::from_millis(5000)) { + Ok(msg) => match state_tracker.set_state_from_msg(&msg) { + Ok(AcquisitionState::Idle) => { + break; + } + Ok(_) => continue, + Err(StateError::InvalidTransition { from, msg }) => { + panic!("invalid state transition: from={from:?} msg={msg:?}") + } + }, + Err(RecvTimeoutError::Timeout) => { + panic!("timeout while waiting for init event"); + } + Err(RecvTimeoutError::Disconnected) => panic!("error while waiting for init event"), + } + }); + + let shm = SharedSlabAllocator::connect(&os_handle).expect("connect to shm"); + + AcquisitionRuntime { + bg_thread, + main_events_tx, + main_events_rx, + rx_writer_to_consumer, + state_tracker, + shm, + current_acquisition_id: 0, + config: config.clone(), + } + } + + /// Receive at most one event from the event bus and update the state. + pub fn update_state(&mut self) -> UpdateStateResult { + match self.main_events_rx.try_recv() { + Ok(msg) => match self.state_tracker.set_state_from_msg(&msg) { + Ok(_) => UpdateStateResult::DidUpdate, + Err(StateError::InvalidTransition { from, msg }) => { + panic!("invalid state transition: from={from:?} msg={msg:?}") + } + }, + Err(TryRecvError::Disconnected) => panic!("lost connection to background thread"), + Err(TryRecvError::Empty) => UpdateStateResult::NoNewMessage, + } + } + + pub fn is_done(&self) -> bool { + // FIXME: out of band message means we can still have data in the queue + // from this acquisition! Maybe add checks if we have received a + // sentinel value like AcquisitionResult::DoneSuccess + matches!( + self.state_tracker.state, + AcquisitionState::Idle | AcquisitionState::Shutdown + ) + } + + pub fn get_next_frame(&self) -> Result, RuntimeError> { + // FIXME: can we make this a non-issue somehow? + if !self.config.enable_frame_iterator { + return Err(RuntimeError::ConfigurationError); + } + let acquisition_result = self + .rx_writer_to_consumer + .recv_timeout(Duration::from_millis(100))?; + match acquisition_result { + AcquisitionResult::DoneSuccess { + acquisition_id, + dropped: _, + } + | AcquisitionResult::DoneShuttingDown { acquisition_id } + | AcquisitionResult::DoneAborted { + acquisition_id, + dropped: _, + } => { + self.main_events_tx + .send(EventMsg::ProcessingDone { acquisition_id })?; + debug!("AcquisitionRuntime::get_next_frame: {acquisition_result:?}"); + } + _ => {} + }; + Ok(acquisition_result) + } + + pub fn frame_done( + &mut self, + frame: AcquisitionResult, + ) -> Result<(), RuntimeError> { + // TODO: keep track of which frames we have seen here, and once we have + // seen all of them, send `EventMsg::ProcesingDone` + if !self.config.enable_frame_iterator { + return Err(RuntimeError::ConfigurationError); + } + let inner = frame.unpack(); + if let Some(f) = inner { + f.free_payload(&mut self.shm); + } + Ok(()) + } + + pub fn get_frame_slot(&mut self, frame: AcquisitionResult) -> Option { + let frame_inner = frame.unpack()?; + Some(frame_inner.into_slot(&self.shm).slot_idx) + } + + pub fn arm(&mut self, params: AcquisitionParams) -> Result<(), RuntimeError> { + self.current_acquisition_id += 1; + self.main_events_tx.send(EventMsg::Arm { + params, + acquisition_id: self.current_acquisition_id, + })?; + Ok(()) + } + + pub fn get_current_acquisition_id(&self) -> usize { + self.current_acquisition_id + } + + pub fn stop(&mut self) -> Result<(), RuntimeError> { + // FIXME: do we need to do anything special if an acquisition is + // currently running? + // self.events + // .send(&k2o::events::EventMsg::CancelAcquisition {}); + self.main_events_tx.send(EventMsg::Shutdown {})?; + Ok(()) + } + + pub fn try_join(&mut self) -> Option<()> { + if let Some(join_handle) = self.bg_thread.take() { + if !join_handle.is_finished() { + self.bg_thread = Some(join_handle); + return None; + } else { + return Some(()); + } + } + Some(()) + } + + pub fn wait_predicate

(&mut self, timeout: Duration, pred: P) -> WaitResult + where + P: Fn(&Self) -> bool, + { + let deadline = Instant::now() + timeout; + // bail out of predicate is true already: + if pred(self) { + log::trace!("predicate success"); + return WaitResult::PredSuccess; + } + loop { + log::trace!("updating state"); + let update_result = self.update_state(); + // only sleep if there was no new message, so we can handle + // storms of events efficiently here: + match update_result { + UpdateStateResult::DidUpdate => { + log::trace!("checking predicate"); + if pred(self) { + log::trace!("predicate success"); + return WaitResult::PredSuccess; + } + } + UpdateStateResult::NoNewMessage => { + log::trace!("no state change, sleeping"); + std::thread::sleep(Duration::from_millis(1)); + } + } + if Instant::now() > deadline { + log::trace!("wait_predicate: timeout"); + return WaitResult::Timeout; + } + } + } + + /// Wait until the acquisition has ended or the timeout expired + pub fn wait_until_complete(&mut self, timeout: Duration) -> WaitResult { + self.wait_predicate(timeout, |slf| slf.is_done()) + } + + /// Wait until the arm command succeeded + pub fn wait_for_arm(&mut self, timeout: Duration) -> WaitResult { + debug!("wait_for_arm"); + self.wait_predicate(timeout, |slf| { + matches!( + slf.state_tracker.state, + AcquisitionState::Armed { + params: _, + acquisition_id: _ + } + ) + }) + } + + pub fn wait_for_start(&mut self, timeout: Duration) -> WaitResult { + self.wait_predicate(timeout, |slf| { + matches!( + slf.state_tracker.state, + AcquisitionState::AcquisitionStarted { + params: _, + frame_id: _, + acquisition_id: _, + } + ) + }) + } + + /// + /// Is the `frame_id` in the current acquisition? + /// If so, returns the frame's index in the acquisition. + /// + pub fn frame_in_acquisition(&self, frame_id: u32) -> Option { + let (params, ref_frame_id) = match &self.state_tracker.state { + AcquisitionState::Startup + | AcquisitionState::Idle + | AcquisitionState::Armed { + params: _, + acquisition_id: _, + } + | AcquisitionState::Shutdown => { + return None; + } + AcquisitionState::AcquisitionStarted { + params, + frame_id, + acquisition_id: _, + } + | AcquisitionState::AcquisitionFinishing { + params, + frame_id, + acquisition_id: _, + } => (params, frame_id), + }; + frame_in_acquisition(frame_id, *ref_frame_id, params) + } +} diff --git a/k2o/src/tracing.rs b/k2o/src/tracing.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/k2o/src/tracing.rs @@ -0,0 +1 @@ + diff --git a/libertem_asi_mpx3/Cargo.toml b/libertem_asi_mpx3/Cargo.toml index 6b5976df..791647ca 100644 --- a/libertem_asi_mpx3/Cargo.toml +++ b/libertem_asi_mpx3/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" version = "0.2.14" edition = "2021" readme = "README.md" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -16,7 +16,7 @@ crate-type = ["cdylib"] bincode = "1.3.3" env_logger = "0.11.5" log = "0.4.22" -pyo3 = { version = "0.21.0", features = ["abi3-py37"] } +pyo3 = { version = "0.21.0", features = ["abi3-py39"] } serde = { version = "1.0.210", features = ["derive"] } ipc-test = { path = "../ipc_test" } serval-client = { path = "../serval-client" } diff --git a/libertem_asi_mpx3/pyproject.toml b/libertem_asi_mpx3/pyproject.toml index d18d9512..e611a934 100644 --- a/libertem_asi_mpx3/pyproject.toml +++ b/libertem_asi_mpx3/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "libertem-asi-mpx3" -requires-python = ">=3.7" +requires-python = ">=3.9" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/libertem_asi_mpx3/src/background_thread.rs b/libertem_asi_mpx3/src/background_thread.rs index 0fcea2d6..bc92350f 100644 --- a/libertem_asi_mpx3/src/background_thread.rs +++ b/libertem_asi_mpx3/src/background_thread.rs @@ -7,7 +7,9 @@ use std::{ }; use common::{ - background_thread::{BackgroundThread, BackgroundThreadSpawnError, ControlMsg, ReceiverMsg}, + background_thread::{ + AcquisitionSize, BackgroundThread, BackgroundThreadSpawnError, ControlMsg, ReceiverMsg, + }, frame_stack::{FrameStackForWriting, FrameStackWriteError}, tcp::{self, ReadExactError}, utils::{num_from_byte_slice, three_way_shift, NumParseError}, @@ -317,9 +319,8 @@ impl From for AcquisitionError { /// especially convert `ControlMsg::StopThread` to `AcquisitionError::Cancelled`. fn check_for_control(control_channel: &Receiver) -> Result<(), AcquisitionError> { match control_channel.try_recv() { - Ok(ControlMsg::StartAcquisitionPassive) => Err(AcquisitionError::StateError { - msg: "received StartAcquisitionPassive while an acquisition was already running" - .to_string(), + Ok(m @ ControlMsg::StartAcquisitionPassive { .. }) => Err(AcquisitionError::StateError { + msg: format!("received {m:?} while an acquisition was already running"), }), Ok(ControlMsg::StopThread) => Err(AcquisitionError::StopThread), Ok(ControlMsg::SpecializedControlMsg { msg: _ }) => { @@ -334,6 +335,7 @@ fn check_for_control(control_channel: &Receiver) -> Result<(), /// Passively listen for the start of an acquisition /// and automatically latch on to it. fn passive_acquisition( + acquisition_size: AcquisitionSize, control_channel: &Receiver, from_thread_s: &Sender>, frame_stack_size: usize, @@ -343,6 +345,14 @@ fn passive_acquisition( ) -> Result<(), AcquisitionError> { let client = ServalClient::new(api_uri); + if acquisition_size != AcquisitionSize::Auto { + return Err(AcquisitionError::ConfigurationError { + msg: format!( + "unsupported parameter: acquisition_size must be Auto, is {acquisition_size:?}" + ), + }); + } + loop { trace!("connecting to {data_uri}..."); check_for_control(control_channel)?; @@ -492,13 +502,13 @@ fn acquisition( let handle = frame_stack.writing_done(shm)?; from_thread_s.send(ReceiverMsg::Finished { - frame_stack: handle, + frame_stack: Some(handle), })?; if !extra_frame_stack.is_empty() { let handle = extra_frame_stack.writing_done(shm)?; from_thread_s.send(ReceiverMsg::Finished { - frame_stack: handle, + frame_stack: Some(handle), })?; } else { // let's not leak the `extra_frame_stack`: @@ -507,6 +517,7 @@ fn acquisition( // in case of error handling. // ah, but it can't, because it doesn't have a reference to `shm`! hmm extra_frame_stack.free_empty_frame_stack(shm)?; + from_thread_s.send(ReceiverMsg::Finished { frame_stack: None })?; } return Ok(()); @@ -558,8 +569,9 @@ fn background_thread( Ok(ControlMsg::CancelAcquisition) => { warn!("background_thread: ControlMsg::CancelAcquisition without running acquisition"); } - Ok(ControlMsg::StartAcquisitionPassive) => { + Ok(ControlMsg::StartAcquisitionPassive { acquisition_size }) => { match passive_acquisition( + acquisition_size, to_thread_r, from_thread_s, frame_stack_size, diff --git a/libertem_asi_mpx3/src/base_types.rs b/libertem_asi_mpx3/src/base_types.rs index f047e396..d3823664 100644 --- a/libertem_asi_mpx3/src/base_types.rs +++ b/libertem_asi_mpx3/src/base_types.rs @@ -1,4 +1,5 @@ use common::{ + background_thread::ConcreteAcquisitionSize, frame_stack::FrameMeta, generic_connection::{AcquisitionConfig, DetectorConnectionConfig}, }; @@ -135,8 +136,8 @@ impl PendingAcquisition { } impl AcquisitionConfig for PendingAcquisition { - fn num_frames(&self) -> usize { - self.config.n_triggers as usize + fn acquisition_size(&self) -> common::background_thread::ConcreteAcquisitionSize { + ConcreteAcquisitionSize::NumFrames(self.config.n_triggers as usize) } } diff --git a/libertem_asi_mpx3/src/main_py.rs b/libertem_asi_mpx3/src/main_py.rs index 1daecd8e..b3d3155b 100644 --- a/libertem_asi_mpx3/src/main_py.rs +++ b/libertem_asi_mpx3/src/main_py.rs @@ -197,7 +197,7 @@ impl ServalConnection { } fn start_passive(&mut self, timeout: Option, py: Python<'_>) -> PyResult<()> { - self.conn.start_passive(timeout, py) + self.conn.start_passive(timeout, None, py) } fn close(&mut self, py: Python) -> PyResult<()> { diff --git a/libertem_asi_tpx3/Cargo.toml b/libertem_asi_tpx3/Cargo.toml index d9578e0b..6124708a 100644 --- a/libertem_asi_tpx3/Cargo.toml +++ b/libertem_asi_tpx3/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" version = "0.2.14" edition = "2021" readme = "README.md" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -19,7 +19,7 @@ crossbeam-channel = "0.5.6" env_logger = "0.11.5" log = "0.4.22" numpy = "0.21" -pyo3 = { version = "0.21", features = ["abi3-py37"] } +pyo3 = { version = "0.21", features = ["abi3-py39"] } serde = { version = "1.0.210", features = ["derive"] } uuid = { version = "1.1.2", features = ["v4", "fast-rng"] } ipc-test = { path = "../ipc_test" } diff --git a/libertem_asi_tpx3/pyproject.toml b/libertem_asi_tpx3/pyproject.toml index e843374f..56b13add 100644 --- a/libertem_asi_tpx3/pyproject.toml +++ b/libertem_asi_tpx3/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "libertem-asi-tpx3" -requires-python = ">=3.7" +requires-python = ">=3.9" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/libertem_dectris/Cargo.toml b/libertem_dectris/Cargo.toml index ca48184a..3caa0f7a 100644 --- a/libertem_dectris/Cargo.toml +++ b/libertem_dectris/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" version = "0.2.14" edition = "2021" readme = "README.md" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -20,12 +20,12 @@ path = "src/main.rs" thiserror = "1.0.64" bincode = "1.3.3" bs_sys = { path = "../bs-sys" } -clap = { version = "3.2.16", features = ["derive"] } +clap = { version = "4.5.18", features = ["derive"] } env_logger = "0.11.5" log = "0.4.22" memmap2 = "0.5.6" numpy = "0.21" -pyo3 = { version = "0.21", features = ["abi3-py37"] } +pyo3 = { version = "0.21", features = ["abi3-py39"] } serde = { version = "1.0.210", features = ["derive"] } serde_json = "1.0.128" spin_sleep = "1.1.1" diff --git a/libertem_dectris/pyproject.toml b/libertem_dectris/pyproject.toml index 0bb2fb97..52b1d6d6 100644 --- a/libertem_dectris/pyproject.toml +++ b/libertem_dectris/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "libertem-dectris" -requires-python = ">=3.7" +requires-python = ">=3.9" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/libertem_dectris/src/background_thread.rs b/libertem_dectris/src/background_thread.rs index 34837602..2a67fc15 100644 --- a/libertem_dectris/src/background_thread.rs +++ b/libertem_dectris/src/background_thread.rs @@ -8,7 +8,7 @@ use std::{ }; use common::{ - background_thread::{self, BackgroundThread, ControlMsg, ReceiverMsg}, + background_thread::{self, AcquisitionSize, BackgroundThread, ControlMsg, ReceiverMsg}, frame_stack::{FrameStackForWriting, FrameStackWriteError}, generic_connection::DetectorConnectionConfig, }; @@ -139,9 +139,8 @@ fn check_for_control( }) => Err(AcquisitionError::StateError { msg: "received StartAcquisition while an acquisition was already running".to_string(), }), - Ok(ControlMsg::StartAcquisitionPassive) => Err(AcquisitionError::StateError { - msg: "received StartAcquisitionPassive while an acquisition was already running" - .to_string(), + Ok(m @ ControlMsg::StartAcquisitionPassive { .. }) => Err(AcquisitionError::StateError { + msg: format!("received {m:?} while an acquisition was already running"), }), Ok(ControlMsg::StopThread) => { debug!("check_for_control: StopThread received"); @@ -402,7 +401,9 @@ fn acquisition( let handle = frame_stack.writing_done(shm); match handle { - Ok(frame_stack) => from_thread_s.send(ReceiverMsg::Finished { frame_stack })?, + Ok(frame_stack) => from_thread_s.send(ReceiverMsg::Finished { + frame_stack: Some(frame_stack), + })?, Err(FrameStackWriteError::Empty) => { warn!("acquisition: unexpected empty frame stack") } @@ -503,7 +504,13 @@ fn background_thread( // control: main threads tells us to quit let control = to_thread_r.recv_timeout(Duration::from_millis(100)); match control { - Ok(ControlMsg::StartAcquisitionPassive) => { + Ok(ControlMsg::StartAcquisitionPassive { acquisition_size }) => { + if acquisition_size != AcquisitionSize::Auto { + return Err(AcquisitionError::ConfigurationError { + msg: format!("unsupported parameter: acquisition_size must be Auto, is {acquisition_size:?}"), + }); + } + from_thread_s.send(ReceiverMsg::ReceiverArmed).unwrap(); match passive_acquisition( to_thread_r, diff --git a/libertem_dectris/src/base_types.rs b/libertem_dectris/src/base_types.rs index db9e1844..c0f60efd 100644 --- a/libertem_dectris/src/base_types.rs +++ b/libertem_dectris/src/base_types.rs @@ -2,7 +2,10 @@ use std::ops::Deref; -use common::{frame_stack::FrameMeta, generic_connection::AcquisitionConfig}; +use common::{ + background_thread::ConcreteAcquisitionSize, frame_stack::FrameMeta, + generic_connection::AcquisitionConfig, +}; use log::info; use serde::{Deserialize, Serialize}; @@ -152,8 +155,8 @@ impl DectrisPendingAcquisition { } impl AcquisitionConfig for DectrisPendingAcquisition { - fn num_frames(&self) -> usize { - self.detector_config.get_num_images() as usize + fn acquisition_size(&self) -> common::background_thread::ConcreteAcquisitionSize { + ConcreteAcquisitionSize::NumFrames(self.detector_config.get_num_images() as usize) } } diff --git a/libertem_dectris/src/dectris_py.rs b/libertem_dectris/src/dectris_py.rs index 269f778c..e11fe1c6 100644 --- a/libertem_dectris/src/dectris_py.rs +++ b/libertem_dectris/src/dectris_py.rs @@ -158,7 +158,7 @@ impl DectrisConnection { /// Start listening for global acquisition headers on the zeromq socket. fn start_passive(&mut self, timeout: Option, py: Python<'_>) -> PyResult<()> { - self.conn.start_passive(timeout, py) + self.conn.start_passive(timeout, None, py) } fn close(&mut self, py: Python) -> PyResult<()> { diff --git a/libertem_k2is/.cargo/config.toml b/libertem_k2is/.cargo/config.toml new file mode 100644 index 00000000..41f92d14 --- /dev/null +++ b/libertem_k2is/.cargo/config.toml @@ -0,0 +1,2 @@ +# [build] +# rustflags = ["-Ctarget-cpu=native"] diff --git a/libertem_k2is/Cargo.toml b/libertem_k2is/Cargo.toml new file mode 100644 index 00000000..8fd8e04e --- /dev/null +++ b/libertem_k2is/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "libertem_k2is" +authors = ["Alexander Clausen "] +license = "MIT" +version = "0.2.14" +edition = "2021" +readme = "README.md" +rust-version = "1.74" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +# [lib] +# name = "libertem_k2is" +# crate-type = ["cdylib"] + +[dependencies] +pyo3 = { version = "0.21.0", features = ["abi3-py39"] } +numpy = "0.21.0" +k2o = { path = "../k2o" } +common = { path = "../common" } +stats = { path = "../stats" } +opentelemetry = { version = "0.25" } +tokio = "1.21.0" +ipc-test = { path = "../ipc_test" } +bincode = "1.3.3" +sendfd = "0.4.3" +env_logger = "0.10.0" +log = "0.4.18" +num = "0.4.3" +zerocopy = "0.7.35" +serde = "1.0.210" +thiserror = "1.0.63" +crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] } + +[features] +extension-module = ["pyo3/extension-module"] +hdf5 = [] diff --git a/libertem_k2is/README.md b/libertem_k2is/README.md new file mode 100644 index 00000000..356e1f55 --- /dev/null +++ b/libertem_k2is/README.md @@ -0,0 +1,13 @@ +# LiberTEM-k2is + +[![LiberTEM-qd-mpx on GitHub](https://img.shields.io/badge/GitHub-MIT-informational)](https://github.com/LiberTEM/LiberTEM-rs) + +This is a Python package for efficiently receiving data from +Gatan K2 detectors, both in + +It is built for [LiberTEM-live](https://github.com/libertem/libertem-live), but can +also be used stand-alone. + +## Changelog + +- Initial release diff --git a/libertem_k2is/examples/examples.py b/libertem_k2is/examples/examples.py new file mode 100644 index 00000000..476508e4 --- /dev/null +++ b/libertem_k2is/examples/examples.py @@ -0,0 +1,25 @@ +from k2opy import K2ISCam, Sync, Flags + +cam = K2ISCam() + +aq = cam.make_acquisition() +aq.set_sync(Sync.WaitForSync) # or Sync.Immediately +# aq.set_binning(...) - not implemented fully +aq.set_num_frames(256*256) +# aq.set_num_frames(Flags.Continuous) - alternatively +aq.enable_file_writing(method="direct", dest_path="") +aq.enable_frame_iterator() + +it = aq.get_frame_iterator(ordered=True) + +def get_frames(): + try: + shape = aq.get_shape() # different frame sizes when binning/cropping + aq.arm() + for i in range(256*256): + frame = aq.get_next_frame() + arr = frame.get_array() + yield arr + aq.frame_done(frame) + finally: + aq.stop() \ No newline at end of file diff --git a/libertem_k2is/examples/fast_acq_integrate.py b/libertem_k2is/examples/fast_acq_integrate.py new file mode 100644 index 00000000..573024e5 --- /dev/null +++ b/libertem_k2is/examples/fast_acq_integrate.py @@ -0,0 +1,119 @@ +""" +This example demonstrates fast turnaround of multiple acquisitions, where: + +1) Each acquisition is integrating potentially many frames, and +2) There is little down time between acquisitions, and +3) Each acquisition start point is properly synchronized, meaning it doesn't + include data from any point in time before explicitly starting the + acquisition. + +To run with full instrumentation and debug logging: + +$ OTEL_ENABLE=1 OTLP_ENDPOINT=localhost:4317 LIBERTEM_K2IS_LOG_LEVEL=debug\ + python examples/fast_acq_integrate.py\ + --mode summit --num-parts=2 --frames-per-part=4 +""" + +import time +import datetime + +import click +import numpy as np +import numba +from libertem.common.tracing import maybe_setup_tracing + +from opentelemetry import trace + +from k2opy import ( + Cam, Sync, AcquisitionParams, Writer, CamClient, Mode, +) + +tracer = trace.get_tracer("write_and_iterate") + + +@numba.njit(parallel=True) +def cast_and_add(dst, src): + dst_flat = dst.reshape((-1,)) + src_flat = src.reshape((-1,)) + # assert dst_flat.shape == src_flat.shape + for i in numba.prange(dst_flat.shape[0]): + dst_flat[i] += src_flat[i] + + +def iterate(outer_i, aq, cam, cam_client, frame_arr, do_work): + t0 = time.time() + i = 0 + try: + while frame := cam.get_next_frame(): + if frame.is_dropped(): + slot = cam.get_frame_slot(frame) + cam_client.done(slot) + print(f"dropped frame {frame.get_idx()}") + continue + i += 1 + slot = cam.get_frame_slot(frame) + frame_ref = cam_client.get_frame_ref(slot) + mv = frame_ref.get_memoryview() + payload = np.frombuffer(mv, dtype=np.uint16).reshape( + cam.get_frame_shape() + ) + if do_work: + cast_and_add(frame_arr, payload) + # frame_arr += payload + cam_client.done(slot) + finally: + t1 = time.time() + print(f"acquisition {aq} done, got {i} frames in {t1-t0:.2f}s...") + np.save(f"/cachedata/alex/bar-sum-{outer_i}.npy", frame_arr) + + +@click.command +@click.option('--mode', default="summit", type=str) +@click.option('--num-parts', default=4, type=int) +@click.option('--frames-per-part', default=10, type=int) +@click.option('--do-work', default=True, type=bool) +def main(mode, num_parts, frames_per_part, do_work): + maybe_setup_tracing("write_and_iterate") + with tracer.start_as_current_span("main"): + mode = Mode.from_string(mode) + shm_socket = "/tmp/k2shm.socket" + cam = Cam( + local_addr_top="192.168.10.99", + local_addr_bottom="192.168.10.99", + mode=mode, + enable_frame_iterator=True, + shm_path=shm_socket, + ) + cam_client = CamClient(shm_socket) + + frame_arr = np.zeros(cam.get_frame_shape(), dtype=np.float32) + + numba.set_num_threads(8) + print("ready for acquisition") + try: + for i in range(num_parts): + frame_arr[:] = 0 + ts = datetime.datetime.now().strftime("%H:%M:%S") + writer = Writer( + method="direct", + # method="mmap", + filename=f"/cachedata/alex/bar-{i}-{ts}.raw", + ) + aqp = AcquisitionParams( + # sync=Sync.WaitForSync, + sync=Sync.Immediately, + size=frames_per_part, + writer=writer, + # writer=None, + ) + aq = cam.make_acquisition(aqp) + print(f"acquisition {aq}") + cam.wait_for_start() + iterate(i, aq, cam, cam_client, frame_arr, do_work) + finally: + # this shuts down the runtime, backgrounds threads and all... + cam.stop() + + +if __name__ == "__main__": + main() diff --git a/libertem_k2is/examples/iterate_new.py b/libertem_k2is/examples/iterate_new.py new file mode 100644 index 00000000..d686e24b --- /dev/null +++ b/libertem_k2is/examples/iterate_new.py @@ -0,0 +1,60 @@ +import time + +import numpy as np +from libertem.common.buffers import zeros_aligned +from libertem.common.tracing import maybe_setup_tracing + +from opentelemetry import trace + +from libertem_k2is import ( + K2Connection, K2AcquisitionConfig, K2CamClient, K2Mode, +) + +tracer = trace.get_tracer("write_and_iterate") + + +def main(): + maybe_setup_tracing("iterate_new") + with tracer.start_as_current_span("main"): + shm_socket = "/tmp/k2shm.socket" + conn = K2Connection( + local_addr_top="192.168.10.98", + local_addr_bottom="192.168.10.99", + shm_handle_path=shm_socket, + frame_stack_size=1, + mode=K2Mode.Summit, + ) + + frame_shape = conn.get_frame_shape() + conn.start_passive() + cam_client = K2CamClient(shm_socket) + frame_arr = zeros_aligned((1,) + frame_shape, dtype=np.uint16) + + conn.wait_for_arm() + + t0 = time.time() + i = 0 + try: + while stack := conn.get_next_stack(1): + print(f"{i}: {stack}") + i += 1 + try: + cam_client.decode_range_into_buffer( + stack, + frame_arr, + 0, + 1, + ) + finally: + cam_client.frame_stack_done(stack) + except Exception as e: + print(f"got an exception: {e}") + raise + finally: + t1 = time.time() + print(f"stopping, got {i} frames in {t1-t0:.2f}s...") + conn.close() + + +if __name__ == "__main__": + main() diff --git a/libertem_k2is/examples/k2is_live.py b/libertem_k2is/examples/k2is_live.py new file mode 100644 index 00000000..dbd8f1ae --- /dev/null +++ b/libertem_k2is/examples/k2is_live.py @@ -0,0 +1,387 @@ +from contextlib import contextmanager +import os +import logging +import time +from typing import ( + Optional, Tuple, Type, Dict, Any, +) + +import numpy as np +from opentelemetry import trace + +from libertem.common import Shape, Slice +from libertem.common.math import prod +from libertem.common.executor import WorkerContext + +from libertem.io.dataset.base import ( + DataTile, DataSetMeta, BasePartition, Partition, DataSet, TilingScheme, +) +from libertem.corrections.corrset import CorrectionSet +from libertem_live.detectors.base.controller import ( + AcquisitionController, +) +from libertem_live.detectors.base.acquisition import ( + AcquisitionMixin, AcquisitionProtocol, GetFrames, GenericCommHandler, +) +from libertem_live.detectors.base.connection import ( + PendingAcquisition, DetectorConnection, +) +from libertem_live.hooks import Hooks + +from libertem_k2is import ( + K2Connection, K2AcquisitionConfig, K2CamClient, K2Mode, PyAcquisitionSize, + K2FrameStack, +) + +tracer = trace.get_tracer(__name__) +logger = logging.getLogger(__name__) + + +class K2ISPendingAcquisition(PendingAcquisition): + def __init__(self): + super().__init__() + + @property + def nimages(self) -> int: + # XXX we don't really know the number of images in the acquisition - + # unless the user tells us beforehand. + raise NotImplementedError("how should we know this?") + + +class K2GetFrames(GetFrames): + CAM_CLIENT_CLS = K2CamClient + FRAME_STACK_CLS = K2FrameStack + + +class K2ISDetectorConnection(DetectorConnection): + def __init__( + self, + local_addr_top: str, + local_addr_bottom: str, + sync_mode=None, # FIXME: immediate or sync to stem? + camera_mode=K2Mode.IS, + file_pattern: Optional[str] = None, + shm_path: Optional[str] = None, + ): + self._local_addr_top = local_addr_top + self._local_addr_bottom = local_addr_bottom + self._sync_mode = sync_mode + self._cam_mode = camera_mode + self._file_pattern = file_pattern + if shm_path is None: + shm_path = f"/run/user/{os.getuid()}/k2is-shm-path" + self._shm_path = shm_path + + self._connect() + + def _connect(self): + cam = K2Connection( + local_addr_top=self._local_addr_top, + local_addr_bottom=self._local_addr_bottom, + shm_handle_path=self._shm_path, + frame_stack_size=1, + mode=self._cam_mode, + crop_to_image_data=True, + ) + self._conn = cam + + def wait_for_acquisition( + self, + timeout: Optional[float] = None, + ) -> Optional[PendingAcquisition]: + # XXX: we don't know how many frames there will be in the acquisition + # (see `K2ISPendingAcquisition` comment above) + raise NotImplementedError() + + def get_conn_impl(self): + return self._conn + + def get_shm_path(self) -> str: + return self._shm_path + + def close(self): + self._conn.stop() + self._conn = None + + def reconnect(self): + if self._conn is not None: + self.close() + self._connect() + + def __enter__(self): + if self._conn is None: + self._connect() + return self + + def get_acquisition_cls(self) -> Type[AcquisitionProtocol]: + return K2Acquisition + + +class K2ISConnectionBuilder: + def open( + self, + local_addr_top: str, + local_addr_bottom: str, + camera_mode: K2Mode = K2Mode.IS, + shm_path: Optional[str] = None, + file_pattern: Optional[str] = None, + ): + return K2ISDetectorConnection( + local_addr_top=local_addr_top, + local_addr_bottom=local_addr_bottom, + camera_mode=camera_mode, + shm_path=shm_path, + file_pattern=file_pattern, + ) + + +class K2CommHandler(GenericCommHandler): + def __init__(self, conn: K2ISDetectorConnection): + super().__init__(conn=conn) + + def get_conn_impl(self): + return self._conn.get_conn_impl() + + def start(self): + pass + + def done(self): + # continue pumping events for a bit: + cam = self._conn.get_conn_impl() + while True: + frame = cam.get_next_stack(1) + if frame is None: + break + + +class K2Acquisition(AcquisitionMixin, DataSet): + ''' + Acquisition from a K2IS detector + + Parameters + ---------- + + local_addr_top + The local IPv4 address where we receive data on (top part) + local_addr_bottom + The local IPv4 address where we receive data on (bottom part) + nav_shape + The number of scan positions as a 2-tuple :code:`(height, width)` + frames_per_partition + A tunable for configuring the feedback rate - more frames per partition + means slower feedback, possibly less computational overhead, but also + less parallelism. Might need to be tuned to adapt to the dwell time. + ''' + def __init__( + self, + conn: K2ISDetectorConnection, + + hooks: Optional[Hooks] = None, + + # in passive mode, we get this: + pending_aq: Optional[K2ISPendingAcquisition] = None, + + controller: Optional[AcquisitionController] = None, + + nav_shape: Optional[Tuple[int, ...]] = None, + + frames_per_partition: Optional[int] = None, + ): + super().__init__( + conn=conn, + nav_shape=nav_shape, + frames_per_partition=frames_per_partition, + controller=controller, + pending_aq=pending_aq, + hooks=hooks, + ) + self._sig_shape: Tuple[int, ...] = () + self._frames_per_partition = min(frames_per_partition, prod(nav_shape)) + + def initialize(self, executor) -> "DataSet": + dtype = np.uint16 + conn = self._conn.get_conn_impl() + shape = conn.get_frame_shape() + self._sig_shape = shape + self._meta = DataSetMeta( + shape=Shape(self._nav_shape + self._sig_shape, sig_dims=2), + raw_dtype=dtype, + dtype=dtype, + ) + return self + + @property + def dtype(self): + return self._meta.dtype + + @property + def raw_dtype(self): + return self._meta.raw_dtype + + @property + def shape(self): + return self._meta.shape + + @property + def meta(self): + return self._meta + + def get_correction_data(self): + return CorrectionSet() + + def _get_filename(self, pattern: str, values: Dict[str, Any]) -> str: + assert "%" in pattern + seq = 1 + all_values = {} + all_values.update(values) + all_values['seq'] = seq + path = pattern % all_values + while os.path.exists(path): + seq += 1 + all_values['seq'] = seq + path = pattern % all_values + return path + + def start_acquisition(self): + nimages = prod(self.shape.nav) + if False: + file_pattern = self._conn._file_pattern + if file_pattern is None: + writer = None + else: + filename = self._get_filename(file_pattern, { + 'nav_shape': "x".join( + [str(part) for part in self.shape.nav] + ), + }) + writer = Writer( + method="direct", + filename=filename, + ) + conn = self._conn.get_conn_impl() + conn.start_passive(acquisition_size=PyAcquisitionSize.from_num_frames(nimages)) + conn.wait_for_arm() # here? + + def end_acquisition(self): + pass + + def check_valid(self): + pass + + def need_decode(self, read_dtype, roi, corrections): + return True # FIXME: we just do this to get a large tile size + + def adjust_tileshape(self, tileshape, roi): + depth = 1 + return (depth, *self.meta.shape.sig) + + def get_max_io_size(self): + # FIXME magic numbers? + return 12*np.prod(self.meta.shape.sig)*8 + + def get_base_shape(self, roi): + return (1, 1, self.meta.shape.sig[-1]) + + @property + def acquisition_state(self): + return self._acq_state + + def get_partitions(self): + num_frames = np.prod(self._nav_shape, dtype=np.uint64) + num_partitions = int(num_frames // self._frames_per_partition) + + slices = BasePartition.make_slices(self.shape, num_partitions) + + for part_slice, start, stop in slices: + yield K2LivePartition( + start_idx=start, + end_idx=stop, + meta=self._meta, + partition_slice=part_slice, + shm_path=self._conn.get_shm_path(), + ) + + def get_task_comm_handler(self) -> "K2CommHandler": + return K2CommHandler( + conn=self._conn, + ) + + +class K2LivePartition(Partition): + def __init__( + self, start_idx, end_idx, partition_slice, + meta, shm_path, + ): + super().__init__( + meta=meta, + partition_slice=partition_slice, + io_backend=None, + decoder=None, + ) + self._start_idx = start_idx + self._end_idx = end_idx + self._shm_path = shm_path + + def shape_for_roi(self, roi): + return self.slice.adjust_for_roi(roi).shape + + @property + def shape(self): + return self.slice.shape + + @property + def dtype(self): + return self.meta.raw_dtype + + def set_corrections(self, corrections): + self._corrections = corrections + + def set_worker_context(self, worker_context: WorkerContext): + self._worker_context = worker_context + + def _preprocess(self, tile_data, tile_slice): + if self._corrections is None: + return + self._corrections.apply(tile_data, tile_slice) + + def _get_tiles_fullframe( + self, + tiling_scheme: TilingScheme, + dest_dtype="float32", + roi=None, + array_backend=None, + ): + assert len(tiling_scheme) == 1 + logger.debug("reading up to frame idx %d for this partition", self._end_idx) + to_read = self._end_idx - self._start_idx + + with K2GetFrames( + request_queue=self._worker_context.get_worker_queue(), + dtype=dest_dtype, + sig_shape=tuple(tiling_scheme[0].shape), + ) as frames: + yield from frames.get_tiles( + to_read=to_read, + start_idx=self._start_idx, + tiling_scheme=tiling_scheme, + corrections=self._corrections, + roi=roi, + array_backend=array_backend, + ) + + def get_tiles( + self, + tiling_scheme, + dest_dtype="float32", + roi=None, + array_backend=None, + ): + yield from self._get_tiles_fullframe( + tiling_scheme, + dest_dtype, + roi, + array_backend=array_backend, + ) + + def __repr__(self): + return f"" diff --git a/libertem_k2is/examples/write_and_iterate.py b/libertem_k2is/examples/write_and_iterate.py new file mode 100644 index 00000000..9ed4c932 --- /dev/null +++ b/libertem_k2is/examples/write_and_iterate.py @@ -0,0 +1,86 @@ +import time + +import numpy as np +from libertem.common.buffers import zeros_aligned +from libertem.common.tracing import maybe_setup_tracing + +from opentelemetry import trace + +from libertem_k2is import ( + K2Connection, K2Mode, K2CamClient, K2AcquisitionConfig, PyAcquisitionSize, +) + +# Cam, Sync, AcquisitionParams, Writer, CamClient + +raise NotImplementedError("writer interface TBD") + +tracer = trace.get_tracer("write_and_iterate") + + +def main(): + maybe_setup_tracing("write_and_iterate") + num_frames = 250 + frame_shape = (2048, 1860) + with tracer.start_as_current_span("main"): + shm_socket = "/tmp/k2shm.socket" + cam = K2Connection( + local_addr_top="192.168.10.99", + local_addr_bottom="192.168.10.98", + frame_stack_size=1, + shm_handle_path=shm_socket, + ) + + writer = Writer( + method="direct", + # method="mmap", + filename="/cachedata/alex/bar.raw", + ) + aqp = AcquisitionParams( + # sync=Sync.WaitForSync, + sync=Sync.Immediately, + size=num_frames, + writer=writer, + # writer=None, + enable_frame_iterator=True, + shm_path=shm_socket, + ) + + aq = cam.make_acquisition(aqp) + aq.arm() + + cam_client = CamClient(shm_socket) + + frame_arr = zeros_aligned(frame_shape, dtype=np.uint16) + frame_indexes = set() + + aq.wait_for_start() + + t0 = time.time() + i = 0 + try: + while frame := aq.get_next_frame(): + i += 1 + frame_indexes.add(frame.get_idx()) + if frame.is_dropped(): + print(f"dropped frame {frame.get_idx()}") + continue + slot = aq.get_frame_slot(frame) + frame_ref = cam_client.get_frame_ref(slot) + mv = frame_ref.get_memoryview() + payload = np.frombuffer(mv, dtype=np.uint16).reshape(frame_shape) + + payload.sum() + # print(payload.sum()) + + cam_client.done(slot) + # print(arr.sum(), arr.shape, arr.dtype) + finally: + t1 = time.time() + print(f"stopping, got {i} frames in {t1-t0:.2f}s...") + aq.stop() + missing = set(range(num_frames)) - frame_indexes + print(missing, len(missing)) + + +if __name__ == "__main__": + main() diff --git a/libertem_k2is/examples/writer_only.py b/libertem_k2is/examples/writer_only.py new file mode 100644 index 00000000..ac2b02a3 --- /dev/null +++ b/libertem_k2is/examples/writer_only.py @@ -0,0 +1,34 @@ +from k2opy import Cam, Sync, AcquisitionParams, Writer + + +def main(): + cam = Cam( + local_addr_top="192.168.10.99", + local_addr_bottom="192.168.10.99", + ) + + writer = Writer( + method="direct", + # method="mmap", + filename="/cachedata/alex/bar.raw", + ) + aqp = AcquisitionParams( + # sync=Sync.WaitForSync, + sync=Sync.Immediately, + size=1800, + writer=writer, + enable_frame_iterator=False, + shm_path="/tmp/k2shm.socket", + ) + + aq = cam.make_acquisition(aqp) + aq.arm() + + # only needed if we only write to a file and don't consume the frame iterator: + aq.wait_until_complete() + print("stopping...") + aq.stop() + + +if __name__ == "__main__": + main() diff --git a/libertem_k2is/pyproject.toml b/libertem_k2is/pyproject.toml new file mode 100644 index 00000000..3c962f27 --- /dev/null +++ b/libertem_k2is/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["maturin>=1.5,<2"] +build-backend = "maturin" + +[project] +name = "libertem_k2is" +requires-python = ">=3.9" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dependencies = [ + "numpy>=1.16.0", + "opentelemetry-api", +] +dynamic = ["version"] + +[project.urls] +repository = "https://github.com/LiberTEM/LiberTEM-rs/" + +[tool.maturin] +features = ["pyo3/extension-module"] diff --git a/libertem_k2is/rust-toolchain.toml b/libertem_k2is/rust-toolchain.toml new file mode 100644 index 00000000..292fe499 --- /dev/null +++ b/libertem_k2is/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" diff --git a/libertem_k2is/src/background_thread.rs b/libertem_k2is/src/background_thread.rs new file mode 100644 index 00000000..5e6b7dd1 --- /dev/null +++ b/libertem_k2is/src/background_thread.rs @@ -0,0 +1,405 @@ +use std::{ + sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender, TryRecvError}, + thread::JoinHandle, + time::Duration, +}; + +use common::{ + background_thread::{ + AcquisitionSize, BackgroundThread, BackgroundThreadSpawnError, ConcreteAcquisitionSize, + ControlMsg, ReceiverMsg, + }, + frame_stack::FrameStackHandle, +}; +use crossbeam::channel::{ + unbounded, Receiver as CReceiver, RecvTimeoutError as CRecvTimeoutError, Sender as CSender, +}; +use ipc_test::SharedSlabAllocator; +use k2o::{ + acquisition::AcquisitionResult, + block::K2Block, + block_is::K2ISBlock, + block_summit::K2SummitBlock, + events::{AcquisitionParams, AcquisitionSync, ChannelEventBus, EventMsg, Events, MessagePump}, + frame::GenericFrame, + frame_is::K2ISFrame, + frame_summit::K2SummitFrame, + recv::RecvConfig, + runtime::{start_bg_thread, AddrConfig, AssemblyConfig}, +}; +use log::{debug, error, info, warn}; +use opentelemetry::Context; + +use crate::{ + config::{K2AcquisitionConfig, K2DetectorConnectionConfig, K2Mode}, + frame_meta::K2FrameMeta, +}; + +type K2ControlMsg = ControlMsg<()>; + +type K2ReceiverMsg = ReceiverMsg; + +#[derive(Debug, Clone, thiserror::Error)] +pub enum AcquisitionError { + #[error("cancelled by the user")] + Cancelled, + + #[error("disconnected")] + Disconnected, + + #[error("thread stopped")] + ThreadStopped, + + #[error("error while initializing: {msg}")] + InitError { msg: String }, + + #[error("receiver state error: {msg}")] + StateError { msg: String }, +} + +#[derive(Debug, Clone, Copy)] +enum PassiveAcquisitionControlFlow { + Shutdown, + Continue, +} + +/// With a running acquisition, check for control messages; +/// especially convert `ControlMsg::StopThread` to `AcquisitionError::Cancelled`. +fn check_for_control(control_channel: &Receiver) -> Result<(), AcquisitionError> { + match control_channel.try_recv() { + Ok(m @ ControlMsg::StartAcquisitionPassive { .. }) => Err(AcquisitionError::StateError { + msg: format!("received {m:?} while an acquisition was already running"), + }), + Ok(ControlMsg::StopThread) => Err(AcquisitionError::ThreadStopped), + Ok(ControlMsg::SpecializedControlMsg { msg: _ }) => { + panic!("unsupported SpecializedControlMsg") + } + Ok(ControlMsg::CancelAcquisition) => Err(AcquisitionError::Cancelled), + Err(TryRecvError::Disconnected) => Err(AcquisitionError::Disconnected), + Err(TryRecvError::Empty) => Ok(()), + } +} + +/// Start a passive acquisition. This always synchronizes with the sync flag, +/// meaning with the STEM scan. +fn passive_acquisition( + acquisition_size: AcquisitionSize, + config: &K2DetectorConnectionConfig, + to_thread_r: &Receiver, + from_thread_s: &Sender, + main_events_tx: &CSender, + main_events_rx: &CReceiver, + rx_writer_to_consumer: &CReceiver>, +) -> Result { + main_events_tx + .send(EventMsg::Arm { + params: AcquisitionParams { + size: acquisition_size, + sync: AcquisitionSync::Immediately, + binning: k2o::events::Binning::Bin1x, + }, + acquisition_id: 1, + }) + .unwrap(); + + // read from `main_events_rx` until we get an `EventMsg::Armed` + loop { + // FIXME: need to have a different control check here, and need to + // keep messages that are not cancellation/abortion. how? + // wrapper around the control channel might be a good idea anyways? + //check_for_control(to_thread_r)?; + match main_events_rx.recv_timeout(Duration::from_millis(100)) { + Ok(e @ EventMsg::AcquisitionStarted { .. }) => { + info!("passive_acquisition: {e:?}"); + break; + } + Ok(EventMsg::AcquisitionError { msg }) => todo!("acquisition error {msg}"), + Ok(EventMsg::Shutdown) => todo!(), + Ok(_) => continue, + Err(CRecvTimeoutError::Disconnected) => return Err(AcquisitionError::Disconnected), + Err(CRecvTimeoutError::Timeout) => continue, + } + } + + from_thread_s.send(ReceiverMsg::ReceiverArmed).unwrap(); + + let effective_frame_shape = config.effective_shape(); + + let acq_size = match acquisition_size { + AcquisitionSize::Auto => ConcreteAcquisitionSize::Continuous, + AcquisitionSize::NumFrames(n) => ConcreteAcquisitionSize::NumFrames(n), + AcquisitionSize::Continuous => ConcreteAcquisitionSize::Continuous, + }; + + from_thread_s + .send(ReceiverMsg::AcquisitionStart { + pending_acquisition: K2AcquisitionConfig::new(acq_size, effective_frame_shape), + }) + .unwrap(); + + 'acquisition: loop { + check_for_control(&to_thread_r)?; + + match rx_writer_to_consumer.recv_timeout(Duration::from_millis(120)) { + Ok(AcquisitionResult::Frame(f, idx)) => { + let meta = vec![K2FrameMeta::new( + f.acquisition_id, + f.frame_id, + idx, + config.mode.get_frame_type(), + config.mode.get_bytes_per_pixel(), + config.crop_to_image_data, + )]; + let slot_info = f.into_payload(); + let frame_stack = FrameStackHandle::new(slot_info, meta, vec![0], 0); + from_thread_s + .send(ReceiverMsg::FrameStack { frame_stack }) + .unwrap(); + } + Ok(AcquisitionResult::DoneSuccess { + dropped, + acquisition_id, + }) => { + info!("acquisition {acquisition_id} done with {dropped} frames dropped"); + from_thread_s + .send(ReceiverMsg::Finished { frame_stack: None }) + .unwrap(); + break 'acquisition; + } + Ok(AcquisitionResult::DoneAborted { + dropped, + acquisition_id, + }) => { + warn!("aborted acquisition {acquisition_id}, with {dropped} dropped frames"); + from_thread_s.send(ReceiverMsg::Cancelled).unwrap(); + break 'acquisition; + } + Ok(AcquisitionResult::DoneShuttingDown { acquisition_id }) => { + warn!("shutting down; current acquisition {acquisition_id}"); + from_thread_s.send(ReceiverMsg::Cancelled).unwrap(); + return Ok(PassiveAcquisitionControlFlow::Shutdown); + } + Ok(result) => { + info!("some result received: {result:?}"); + } + Err(_e) => { + continue 'acquisition; + } + } + } + + Ok(PassiveAcquisitionControlFlow::Continue) +} + +fn background_thread( + config: &K2DetectorConnectionConfig, + to_thread_r: &Receiver, + from_thread_s: &Sender, + shm: SharedSlabAllocator, +) -> Result<(), AcquisitionError> { + let events: Events = ChannelEventBus::new(); + let pump = MessagePump::new(&events); + let (main_events_tx, main_events_rx) = pump.get_ext_channels(); + + let (tx_writer_to_consumer, rx_writer_to_consumer) = + unbounded::>(); + + let asm_config = AssemblyConfig::new(Duration::from_millis(25), config.assembly_realtime); + let recv_config = RecvConfig::new(config.recv_realtime); + let addr_config = AddrConfig::new(&config.local_addr_top, &config.local_addr_bottom); + + // FIXME: join this on drop, and/or use a threading scope + let inner_bg_thread = match config.mode { + K2Mode::IS => Some(start_bg_thread::( + events, + addr_config, + pump, + tx_writer_to_consumer, + shm.get_handle(), + &asm_config, + &recv_config, + )), + K2Mode::Summit => Some(start_bg_thread::< + K2SummitFrame, + { K2SummitBlock::PACKET_SIZE }, + >( + events, + addr_config, + pump, + tx_writer_to_consumer, + shm.get_handle(), + &asm_config, + &recv_config, + )), + }; + + loop { + // FIXME: need to have a different control check here, and need to + // keep messages that are not cancellation/abortion. how? + // wrapper around the control channel might be a good idea anyways? + //check_for_control(to_thread_r)?; + // timeout sets the lower limit of the reaction time to + // control commands from the main thread. + match main_events_rx.recv_timeout(Duration::from_millis(500)) { + Ok(EventMsg::Init) => { + info!("init done"); + break; + } + Ok(EventMsg::AcquisitionError { msg }) => { + error!("error while initializing: {msg}"); + return Err(AcquisitionError::InitError { msg }); + } + Ok(e) => { + info!("unexpected event: {e:?}"); + continue; + } + Err(_timeout) => { + info!("still waiting for init..."); + continue; + } + } + } + + 'outer: loop { + loop { + // control: main threads tells us what to do. + let control = to_thread_r.recv_timeout(Duration::from_millis(100)); + match control { + Ok(ControlMsg::StartAcquisitionPassive { acquisition_size }) => { + match passive_acquisition( + acquisition_size, + config, + to_thread_r, + from_thread_s, + &main_events_tx, + &main_events_rx, + &rx_writer_to_consumer, + ) { + Ok(PassiveAcquisitionControlFlow::Continue) => { + info!("passive acquisition returned, waiting for next") + } + Ok(PassiveAcquisitionControlFlow::Shutdown) => { + warn!("shutting down background thread"); + break 'outer; + } + Err(AcquisitionError::Cancelled) => { + info!("acquisition cancelled by user"); + from_thread_s.send(ReceiverMsg::Cancelled).unwrap(); + continue 'outer; + } + e @ Err( + AcquisitionError::Disconnected | AcquisitionError::ThreadStopped, + ) => { + info!("background_thread: terminating: {e:?}"); + return Ok(()); + } + Err(e) => { + error!("background_thread: error: {}; re-connecting", e); + from_thread_s + .send(ReceiverMsg::FatalError { error: Box::new(e) }) + .unwrap(); + continue 'outer; + } + } + } + Ok(ControlMsg::CancelAcquisition) => { + warn!( + "background_thread: got a CancelAcquisition message in main loop; ignoring" + ); + } + Ok(ControlMsg::StopThread) => { + debug!("background_thread: got a StopThread message"); + break 'outer; + } + Err(RecvTimeoutError::Disconnected) => { + warn!("background_thread: control channel has disconnected"); + break 'outer; + } + Err(RecvTimeoutError::Timeout) => (), // no message, nothing to do + Ok(ControlMsg::SpecializedControlMsg { msg: _ }) => { + panic!("ControlMsg::SpecializesControlMsg is unused for K2"); + } + } + } + } + main_events_tx.send(EventMsg::Shutdown).unwrap(); + inner_bg_thread.unwrap().join().unwrap(); + info!("background_thread: is done"); + Ok(()) +} + +fn background_thread_wrap( + config: &K2DetectorConnectionConfig, + to_thread_r: &Receiver, + from_thread_s: &Sender, + shm: SharedSlabAllocator, +) { + if let Err(err) = background_thread(config, to_thread_r, from_thread_s, shm) { + log::error!("background_thread err'd: {}", err.to_string()); + // NOTE: `shm` is dropped in case of an error, so anyone who tries to connect afterwards + // will get an error + from_thread_s + .send(ReceiverMsg::FatalError { + error: Box::new(err), + }) + .unwrap(); + } +} + +pub struct K2BackgroundThread { + bg_thread: JoinHandle<()>, + to_thread: Sender>, + from_thread: Receiver>, +} + +impl BackgroundThread for K2BackgroundThread { + type FrameMetaImpl = K2FrameMeta; + type AcquisitionConfigImpl = K2AcquisitionConfig; + type ExtraControl = (); + + fn channel_to_thread(&mut self) -> &mut Sender> { + &mut self.to_thread + } + + fn channel_from_thread( + &mut self, + ) -> &mut Receiver> { + &mut self.from_thread + } + + fn join(self) { + if let Err(e) = self.bg_thread.join() { + // FIXME: should we have an error boundary here instead and stop the panic? + std::panic::resume_unwind(e) + } + } +} + +impl K2BackgroundThread { + pub fn spawn( + config: &K2DetectorConnectionConfig, + shm: &SharedSlabAllocator, + ) -> Result { + let (to_thread_s, to_thread_r) = channel(); + let (from_thread_s, from_thread_r) = channel(); + + let builder = std::thread::Builder::new(); + let shm = shm.clone_and_connect()?; + let config = config.clone(); + let ctx = Context::current(); + + info!("connection config: {config:?}"); + + Ok(Self { + bg_thread: builder + .name("bg_thread".to_owned()) + .spawn(move || { + let _ctx_guard = ctx.attach(); + background_thread_wrap(&config, &to_thread_r, &from_thread_s, shm) + }) + .map_err(BackgroundThreadSpawnError::SpawnFailed)?, + from_thread: from_thread_r, + to_thread: to_thread_s, + }) + } +} diff --git a/libertem_k2is/src/config.rs b/libertem_k2is/src/config.rs new file mode 100644 index 00000000..12c500cc --- /dev/null +++ b/libertem_k2is/src/config.rs @@ -0,0 +1,175 @@ +use common::{ + background_thread::{ConcreteAcquisitionSize, PyAcquisitionSize}, + generic_connection::{AcquisitionConfig, DetectorConnectionConfig}, +}; +use pyo3::{pyclass, pymethods}; +use serde::{Deserialize, Serialize}; + +use crate::frame_meta::K2FrameType; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub struct Shape { + pub width: usize, + pub height: usize, +} + +#[pyclass] +#[derive(Debug, Clone)] +pub struct K2AcquisitionConfig { + acquisition_size: ConcreteAcquisitionSize, + effective_frame_shape: Shape, +} + +impl K2AcquisitionConfig { + pub fn new(acquisition_size: ConcreteAcquisitionSize, effective_frame_shape: Shape) -> Self { + Self { + acquisition_size, + effective_frame_shape, + } + } +} + +impl AcquisitionConfig for K2AcquisitionConfig { + fn acquisition_size(&self) -> ConcreteAcquisitionSize { + self.acquisition_size + } +} + +#[pymethods] +impl K2AcquisitionConfig { + fn frame_shape(&self) -> (usize, usize) { + ( + self.effective_frame_shape.height, + self.effective_frame_shape.width, + ) + } + + fn acquisition_size(&self) -> PyAcquisitionSize { + PyAcquisitionSize::from_acquisition_size(self.acquisition_size.into()) + } +} + +#[derive(Debug, Clone, Copy)] +#[pyclass] +pub enum K2Mode { + IS, + Summit, +} + +impl K2Mode { + pub fn get_bytes_per_frame(&self) -> usize { + let shape = self.get_frame_shape(false); + shape.width * shape.height * self.get_bytes_per_pixel() + } + + pub fn get_bytes_per_pixel(&self) -> usize { + 2 + } + + /// There is some "non-image data" in the data stream we receive, which we + /// may want to crop off. See also `crate::decoder::try_cast_with_crop`. + pub fn get_frame_shape(&self, crop: bool) -> Shape { + match (self, crop) { + (K2Mode::IS, true) => Shape { + height: 1920, + width: 2048 - 128, + }, + (K2Mode::IS, false) => Shape { + height: 1920, + width: 2048, + }, + (K2Mode::Summit, true) => Shape { + height: 3840 - 120, + width: 4096 - 256, + }, + (K2Mode::Summit, false) => Shape { + height: 3840, + width: 4096, + }, + } + } + + pub fn get_frame_type(&self) -> K2FrameType { + match &self { + K2Mode::IS => K2FrameType::IS, + K2Mode::Summit => K2FrameType::Summit, + } + } +} + +#[derive(Debug, Clone)] +pub struct K2DetectorConnectionConfig { + pub mode: K2Mode, + + /// IP address of the local interface that receives data from the top detector + pub local_addr_top: String, + + /// IP address of the local interface that receives data from the bottom detector + pub local_addr_bottom: String, + + /// Run frame assembly in a prioritized thread + pub assembly_realtime: bool, + + /// Run UDP receivers in prioritized threads + pub recv_realtime: bool, + + /// Crop K2CamClient output to actually usable image data + pub crop_to_image_data: bool, + + /// Number of frames per frame stack + frame_stack_size: usize, + + num_slots: usize, + enable_huge_pages: bool, + shm_handle_path: String, +} + +impl K2DetectorConnectionConfig { + pub fn new( + mode: K2Mode, + local_addr_top: String, + local_addr_bottom: String, + num_slots: usize, + enable_huge_pages: bool, + shm_handle_path: String, + frame_stack_size: usize, + recv_realtime: bool, + assembly_realtime: bool, + crop_to_image_data: bool, + ) -> Self { + Self { + mode, + local_addr_top, + local_addr_bottom, + num_slots, + enable_huge_pages, + shm_handle_path, + frame_stack_size, + recv_realtime, + assembly_realtime, + crop_to_image_data, + } + } + + pub fn effective_shape(&self) -> Shape { + self.mode.get_frame_shape(self.crop_to_image_data) + } +} + +impl DetectorConnectionConfig for K2DetectorConnectionConfig { + fn get_shm_num_slots(&self) -> usize { + self.num_slots + } + + fn get_shm_slot_size(&self) -> usize { + self.frame_stack_size * self.mode.get_bytes_per_frame() + } + + fn get_shm_enable_huge_pages(&self) -> bool { + self.enable_huge_pages + } + + fn get_shm_handle_path(&self) -> String { + self.shm_handle_path.clone() + } +} diff --git a/libertem_k2is/src/decoder.rs b/libertem_k2is/src/decoder.rs new file mode 100644 index 00000000..81d46e81 --- /dev/null +++ b/libertem_k2is/src/decoder.rs @@ -0,0 +1,113 @@ +use std::fmt::Debug; + +use common::{ + decoder::{self, try_cast_if_safe, Decoder, DecoderError}, + frame_stack::{self}, +}; +use ipc_test::SharedSlabAllocator; +use num::{NumCast, ToPrimitive}; +use numpy::ndarray::{s, ArrayViewMut3}; +use zerocopy::FromBytes; + +use crate::frame_meta::K2FrameMeta; + +/// Same as `common::decoder::try_cast_if_safe`, but crop the frame, +/// removing a stripe at the right side. +/// (useful for getting rid of non-frame-data on K2{IS,Summit}) +pub fn try_cast_with_crop( + input: &[I], + output: &mut [O], + frame_width: usize, + frame_width_orig: usize, +) -> Result<(), DecoderError> +where + O: Copy + NumCast + Debug, + I: Copy + ToPrimitive + Debug, +{ + let in_rows = input.chunks_exact(frame_width_orig); + let out_rows = output.chunks_exact_mut(frame_width); + + // -- this only works without a height difference, for double-checking stuff.... + // assert_eq!( + // in_rows.len(), + // out_rows.len(), + // "{} != {}; frame_width_orig={}, frame_width={}", + // in_rows.len(), + // out_rows.len(), + // frame_width_orig, + // frame_width, + // ); + + for (in_row, out_row) in in_rows.zip(out_rows) { + try_cast_if_safe(&in_row[0..frame_width], out_row)?; + } + + // assert!(in_rows.remainder().len() == 0); + // assert!(out_rows.into_remainder().len() == 0); + + Ok(()) +} + +#[derive(Debug, Clone, Default)] +pub struct K2Decoder {} + +impl Decoder for K2Decoder { + type FrameMeta = K2FrameMeta; + + fn decode( + &self, + shm: &SharedSlabAllocator, + input: &frame_stack::FrameStackHandle, + output: &mut ArrayViewMut3<'_, T>, + start_idx: usize, + end_idx: usize, + ) -> Result<(), decoder::DecoderError> + where + T: decoder::DecoderTargetPixelType, + u8: num::cast::AsPrimitive, + u16: num::cast::AsPrimitive, + { + // the background thread already converts the integer data to u16, + // possibly from the 12bit raw format, so all that's left here is to + // convert/copy to target pixel type `T`: + input.with_slot(shm, |slot| { + for ((frame_meta, out_idx), in_idx) in + input.get_meta().iter().zip(0..).zip(start_idx..end_idx) + { + let mut out_view = output.slice_mut(s![out_idx, .., ..]); + let out_slice = + out_view + .as_slice_mut() + .ok_or_else(|| DecoderError::FrameDecodeFailed { + msg: "out slice not C-order contiguous".to_owned(), + })?; + let raw_input_data = input.get_slice_for_frame(in_idx, slot); + let data_as_u16: &[u16] = + FromBytes::slice_from(raw_input_data).ok_or_else(|| { + DecoderError::FrameDecodeFailed { + msg: "could not interprete input data as u16".to_owned(), + } + })?; + if frame_meta.get_crop() { + try_cast_with_crop( + data_as_u16, + out_slice, + frame_meta.get_effective_frame_shape().width, + frame_meta.get_raw_frame_shape().width, + )?; + } else { + try_cast_if_safe(data_as_u16, out_slice)?; + } + } + + Ok(()) + }) + } + + fn zero_copy_available( + &self, + _handle: &frame_stack::FrameStackHandle, + ) -> Result { + Ok(false) + } +} diff --git a/libertem_k2is/src/frame_meta.rs b/libertem_k2is/src/frame_meta.rs new file mode 100644 index 00000000..cf16b48a --- /dev/null +++ b/libertem_k2is/src/frame_meta.rs @@ -0,0 +1,96 @@ +use common::frame_stack::FrameMeta; +use serde::{Deserialize, Serialize}; + +use crate::config::{K2Mode, Shape}; + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub enum K2FrameType { + IS, + Summit, + // FIXME: add 800, 1600 fps frame types? +} + +impl K2FrameType { + pub fn as_camera_mode(&self) -> K2Mode { + match self { + K2FrameType::IS => K2Mode::IS, + K2FrameType::Summit => K2Mode::Summit, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct K2FrameMeta { + acquisition_id: usize, + + /// the frame id as received + frame_id: u32, + + /// the frame index in the acquisition + frame_idx: u32, + + // FIXME: replace with the proper type + // created_timestamp: Instant, + frame_type: K2FrameType, + bytes_per_pixel: usize, + + /// whether or not to crop to the "usable image area" + crop_to_image_data: bool, +} + +impl K2FrameMeta { + pub fn new( + acquisition_id: usize, + frame_id: u32, + frame_idx: u32, + frame_type: K2FrameType, + bytes_per_pixel: usize, + crop_to_image_data: bool, + ) -> Self { + Self { + acquisition_id, + frame_id, + frame_idx, + frame_type, + bytes_per_pixel, + crop_to_image_data, + } + } + + pub fn get_crop(&self) -> bool { + self.crop_to_image_data + } + + pub fn get_frame_type(&self) -> K2FrameType { + self.frame_type + } + + pub fn get_raw_frame_shape(&self) -> Shape { + self.frame_type.as_camera_mode().get_frame_shape(false) + } + + pub fn get_effective_frame_shape(&self) -> Shape { + self.frame_type + .as_camera_mode() + .get_frame_shape(self.crop_to_image_data) + } +} + +impl FrameMeta for K2FrameMeta { + fn get_data_length_bytes(&self) -> usize { + let shape = self.get_raw_frame_shape(); + (shape.width * shape.height) as usize * self.bytes_per_pixel + } + + fn get_dtype_string(&self) -> String { + "u16".to_owned() + } + + fn get_shape(&self) -> (u64, u64) { + let shape = self + .frame_type + .as_camera_mode() + .get_frame_shape(self.crop_to_image_data); + (shape.height as u64, shape.width as u64) + } +} diff --git a/libertem_k2is/src/lib.rs b/libertem_k2is/src/lib.rs new file mode 100644 index 00000000..0be3f5d3 --- /dev/null +++ b/libertem_k2is/src/lib.rs @@ -0,0 +1,498 @@ +pub mod background_thread; +pub mod config; +pub mod decoder; +pub mod frame_meta; +pub mod main_py; + +use common::tracing::{get_tracer, span_from_py, tracing_from_env}; +use env_logger::Builder; +use ipc_test::SharedSlabAllocator; +use log::info; +use opentelemetry::trace::Tracer; +use std::{ + path::Path, + time::{Duration, Instant}, +}; + +use k2o::runtime::{AcquisitionRuntimeConfig, AddrConfig, RuntimeError, WaitResult}; + +use k2o::{ + acquisition::AcquisitionResult, + events::{AcquisitionParams, AcquisitionSync}, + frame::GenericFrame, + params::CameraMode, + runtime::AcquisitionRuntime, +}; + +use pyo3::{exceptions, prelude::*, types::PyType}; + +/* + +#[pymodule] +fn libertem_k2is(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { + tracing_from_env("libertem-k2is".to_owned()); + + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + let env = env_logger::Env::default() + .filter_or("LIBERTEM_K2IS_LOG_LEVEL", "error") + .write_style_or("LIBERTEM_K2IS_LOG_STYLE", "always"); + Builder::new() + .parse_env(env) + .format_timestamp_micros() + .init(); + + Ok(()) +} + +#[pyclass(name = "Sync")] +#[derive(Clone, Debug, PartialEq, Eq)] +enum SyncFlags { + WaitForSync, + Immediately, +} + +impl From for AcquisitionSync { + fn from(sf: SyncFlags) -> Self { + match sf { + SyncFlags::WaitForSync => AcquisitionSync::WaitForSync, + SyncFlags::Immediately => AcquisitionSync::Immediately, + } + } +} + +#[pyclass(name = "Mode")] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +enum PyMode { + #[default] + IS, + Summit, +} + +impl From for PyMode { + fn from(value: CameraMode) -> Self { + match value { + CameraMode::IS => PyMode::IS, + CameraMode::Summit => PyMode::Summit, + } + } +} + +impl From for CameraMode { + fn from(val: PyMode) -> Self { + match val { + PyMode::IS => CameraMode::IS, + PyMode::Summit => CameraMode::Summit, + } + } +} + +#[pymethods] +impl PyMode { + #[classmethod] + fn from_string(_cls: &Bound<'_, PyType>, mode: &str) -> PyResult { + match mode.to_lowercase().as_ref() { + "is" => Ok(Self::IS), + "summit" => Ok(Self::Summit), + _ => Err(exceptions::PyValueError::new_err(format!( + "unknown mode: {}", + mode + ))), + } + } +} + +#[pyclass(name = "AcquisitionParams")] +#[derive(Debug, Clone)] +struct PyAcquisitionParams { + pub size: Option, + pub sync: SyncFlags, +} + +#[pymethods] +impl PyAcquisitionParams { + #[new] + fn new(sync: SyncFlags, size: Option) -> Self { + PyAcquisitionParams { size, sync } + } +} + +#[pyclass(name = "Frame")] +struct PyFrame { + acquisition_result: Option>, + frame_idx: u32, + frame_id: u32, +} + +impl PyFrame { + fn new(result: AcquisitionResult, frame_idx: u32, frame_id: u32) -> Self { + PyFrame { + acquisition_result: Some(result), + frame_idx, + frame_id, + } + } + + fn consume_frame_data(&mut self) -> AcquisitionResult { + self.acquisition_result.take().unwrap() + } +} + +#[pymethods] +impl PyFrame { + fn is_dropped(&self) -> bool { + matches!( + &self.acquisition_result, + Some(AcquisitionResult::DroppedFrame(..)) + | Some(AcquisitionResult::DroppedFrameOutside(..)) + ) + } + + fn get_idx(&self) -> u32 { + self.frame_idx + } + + fn get_id(&self) -> u32 { + self.frame_id + } +} + +/// +/// An `Acquisition` is an object to perform a single acquisition, that is, +/// acquire a potentially unlimited number of frames and iterate over them or +/// write them to disk. +#[pyclass] +struct Acquisition { + params: PyAcquisitionParams, + camera_mode: CameraMode, + id: usize, +} + +impl Acquisition { + pub fn new(params: PyAcquisitionParams, camera_mode: CameraMode, id: usize) -> Self { + Acquisition { + params, + camera_mode, + id, + } + } +} + +#[pymethods] +impl Acquisition { + fn get_id(&self) -> usize { + self.id + } + + fn get_mode(&self) -> PyMode { + self.camera_mode.into() + } + + fn get_params(&self) -> PyAcquisitionParams { + self.params.clone() + } + + fn __repr__(&self) -> String { + let id = self.id; + format!("") + } +} + +fn convert_runtime_error(val: RuntimeError) -> PyErr { + let msg = format!("runtime error: {val:?}"); + exceptions::PyRuntimeError::new_err(msg) +} + +#[pyclass] +struct Cam { + camera_mode: PyMode, + enable_frame_iterator: bool, + shm: Option, + runtime: Option, +} + +#[pymethods] +impl Cam { + #[new] + #[allow(clippy::too_many_arguments)] + fn new( + py: Python, + local_addr_top: &str, + local_addr_bottom: &str, + mode: PyMode, + shm_path: &str, + enable_frame_iterator: Option, + recv_realtime: Option, + assembly_realtime: Option, + ) -> PyResult { + let _guard = span_from_py(py, "Cam::new")?; + + let path = Path::new(&shm_path); + let (num_slots, slot_size) = match mode { + PyMode::IS => (2000, 2048 * 1860 * 2), + PyMode::Summit => (500, 4096 * 3840 * 2), + }; + let tracer = get_tracer(); + let shm = tracer.in_span("Cam shm_setup", |_cx| { + SharedSlabAllocator::new(num_slots, slot_size, true, path).expect("create shm") + }); + let addr_config = AddrConfig::new(local_addr_top, local_addr_bottom); + let enable_frame_iterator = enable_frame_iterator.unwrap_or(true); + let runtime_config = AcquisitionRuntimeConfig::new( + enable_frame_iterator, + recv_realtime.unwrap_or(true), + assembly_realtime.unwrap_or(true), + mode.into(), + addr_config, + ); + + let runtime = AcquisitionRuntime::new(&runtime_config, shm.get_handle()); + + Ok(Cam { + camera_mode: mode, + enable_frame_iterator, + shm: Some(shm), + runtime: Some(runtime), + }) + } + + fn wait_for_start(&mut self, py: Python) -> PyResult<()> { + // TODO: total deadline for initialization? + // TODO: currently the API can be used wrong, i.e. calling + // `get_next_frame` before this function means it will throw away + // perfectly fine frames that actually belong to the beginning of the + // acquisition. This can be prevented: instead, the user should get back + // an object from this function which is the actual frame iterator. Or + // we should make the wait implicit and integrate it into + // `get_next_frame`... hmm. + let _guard = span_from_py(py, "Cam::wait_for_start")?; + + if let Some(runtime) = &mut self.runtime { + loop { + if runtime + .wait_for_start(Duration::from_millis(100)) + .is_success() + { + break; + } + py.check_signals()?; + } + } else { + return Err(exceptions::PyRuntimeError::new_err( + "acquisition is not running", + )); + } + + Ok(()) + } + + /// + /// Wait for the current acquisition to complete. This is only needed + /// if we are only writing to a file, and not consuming the + /// frame iterator, which takes care of this synchronization + /// otherwise. + /// + /// Also succeeds if the runtime is already shut down. + /// + // FIXME: timeout? + fn wait_until_complete(&mut self, py: Python) -> PyResult<()> { + let _guard = span_from_py(py, "Acquisition::wait_until_complete")?; + + if let Some(runtime) = &mut self.runtime { + loop { + match runtime.wait_until_complete(Duration::from_millis(100)) { + WaitResult::PredSuccess => return Ok(()), + WaitResult::Timeout => { + py.check_signals()?; + } + } + } + } + Ok(()) + } + + fn stop(&mut self, timeout: Option, py: Python) -> PyResult<()> { + let _guard = span_from_py(py, "Acquisition::stop")?; + + let timeout_float: f32 = timeout.unwrap_or(30_f32); + match &mut self.runtime { + None => Err(exceptions::PyRuntimeError::new_err( + "trying to stop while not running", + )), + Some(runtime) => { + if runtime.stop().is_err() { + return Err(exceptions::PyRuntimeError::new_err( + "connection to background thread lost", + )); + } + let timeout = Duration::from_secs_f32(timeout_float); + let deadline = Instant::now() + timeout; + while Instant::now() < deadline { + if runtime.try_join().is_some() { + self.shm.take(); + return Ok(()); + } + std::thread::sleep(Duration::from_millis(100)); + py.check_signals()?; + } + // deadline exceeded + Err(exceptions::PyRuntimeError::new_err( + "timeout while waiting for background thread to stop", + )) + } + } + } + + fn get_next_frame(&mut self, py: Python) -> PyResult> { + let _guard = span_from_py(py, "Cam::get_next_frame")?; + + if !self.enable_frame_iterator { + return Err(exceptions::PyRuntimeError::new_err( + "get_next_frame called without enable_frame_iterator", + )); + } + if let Some(runtime) = &mut self.runtime { + loop { + runtime.update_state(); + match runtime.get_next_frame() { + Err(RuntimeError::Timeout) => { + py.check_signals()?; + // FIXME: break out of here after some larger timeout of no data received? + continue; + } + Err(e) => return Err(convert_runtime_error(e)), + Ok(result) => { + py.check_signals()?; + match &result { + AcquisitionResult::Frame(frame, _frame_idx) + | AcquisitionResult::DroppedFrame(frame, _frame_idx) => { + // FIXME: support for subframes! maybe on the pyframe object itself? + if let Some(frame_idx) = + runtime.frame_in_acquisition(frame.get_frame_id()) + { + let frame_id = frame.get_frame_id(); + return Ok(Some(PyFrame::new(result, frame_idx, frame_id))); + } else { + let frame_id = result.get_frame().unwrap().get_frame_id(); + println!("recycling frame {frame_id}"); + runtime.frame_done(result).map_err(convert_runtime_error)?; + } + } + AcquisitionResult::DroppedFrameOutside(_) => { + runtime.frame_done(result).map_err(convert_runtime_error)?; + } + AcquisitionResult::ShutdownIdle + | AcquisitionResult::DoneShuttingDown { acquisition_id: _ } => { + return Err(exceptions::PyRuntimeError::new_err( + "acquisition runtime is shutting down", + )); + } + AcquisitionResult::DoneAborted { + dropped, + acquisition_id: _, + } + | AcquisitionResult::DoneSuccess { + dropped, + acquisition_id: _, + } => { + info!("dropped {dropped} frames in this acquisition"); + return Ok(None); + } + } + } + } + } + } else { + Err(exceptions::PyRuntimeError::new_err( + "acquisition is not running", + )) + } + } + + fn frame_done(&mut self, frame: &mut PyFrame) -> PyResult<()> { + if let Some(runtime) = &mut self.runtime { + runtime + .frame_done(frame.consume_frame_data()) + .map_err(convert_runtime_error)?; + Ok(()) + } else { + Err(exceptions::PyRuntimeError::new_err( + "acquisition is not running", + )) + } + } + + fn get_frame_slot(&mut self, frame: &mut PyFrame) -> PyResult { + if let Some(runtime) = &mut self.runtime { + let slot = runtime.get_frame_slot(frame.consume_frame_data()); + if let Some(idx) = slot { + Ok(idx) + } else { + Err(exceptions::PyRuntimeError::new_err( + "acquisition is not running", + )) + } + } else { + Err(exceptions::PyRuntimeError::new_err( + "acquisition is not running", + )) + } + } + + fn get_frame_shape(&self) -> (usize, usize) { + match self.camera_mode { + PyMode::IS => (1860, 2048), + PyMode::Summit => (3840, 4096), + } + } + + /// Arm the runtime for the next acquisition + fn make_acquisition( + &mut self, + py: Python, + params: PyAcquisitionParams, + ) -> PyResult { + let _guard = span_from_py(py, "Cam::make_acquisition")?; + let p = params.clone(); + let acq_params = AcquisitionParams { + size: p.size.into(), + sync: p.sync.into(), + binning: k2o::events::Binning::Bin1x, + }; + if let Some(runtime) = &mut self.runtime { + if runtime.arm(acq_params).is_err() { + return Err(exceptions::PyRuntimeError::new_err( + "connection to background thread lost", + )); + } + let tracer = get_tracer(); + + tracer.in_span("AcquisitionRuntime::wait_for_arm", |_cx| -> PyResult<()> { + loop { + py.check_signals()?; + if runtime + .wait_for_arm(Duration::from_millis(100)) + .is_success() + { + return Ok(()); + } + } + })?; + Ok(Acquisition::new( + params, + self.camera_mode.into(), + runtime.get_current_acquisition_id(), + )) + } else { + Err(exceptions::PyRuntimeError::new_err( + "invalid state - acquisition runtime not available", + )) + } + } +} + +*/ diff --git a/libertem_k2is/src/main_py.rs b/libertem_k2is/src/main_py.rs new file mode 100644 index 00000000..07c03684 --- /dev/null +++ b/libertem_k2is/src/main_py.rs @@ -0,0 +1,215 @@ +use common::background_thread::PyAcquisitionSize; +use common::generic_connection::GenericConnection; +use common::tracing::{span_from_py, tracing_from_env}; +use log::trace; +use numpy::PyUntypedArray; +use pyo3::exceptions::PyRuntimeError; +use pyo3::{pyclass, pymethods, Python}; +use pyo3::{pymodule, types::PyModule, Bound, PyResult}; + +use common::{impl_py_cam_client, impl_py_connection}; + +use crate::background_thread::K2BackgroundThread; +use crate::config::{K2AcquisitionConfig, K2DetectorConnectionConfig, K2Mode}; +use crate::decoder::K2Decoder; +use crate::frame_meta::K2FrameMeta; + +#[pymodule] +fn libertem_k2is(m: &Bound<'_, PyModule>) -> PyResult<()> { + let env = env_logger::Env::default() + .filter_or("LIBERTEM_K2IS_LOG_LEVEL", "error") + .write_style_or("LIBERTEM_K2IS_LOG_STYLE", "always"); + env_logger::Builder::from_env(env) + .format_timestamp_micros() + .init(); + + tracing_from_env("libertem-k2is".to_owned()); + + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + Ok(()) +} + +impl_py_connection!( + _PyK2Connection, + K2FrameStack, + K2FrameMeta, + K2BackgroundThread, + K2AcquisitionConfig, + libertem_k2is +); + +#[pyclass] +struct K2Connection { + conn: _PyK2Connection, + config: K2DetectorConnectionConfig, +} + +#[pymethods] +impl K2Connection { + #[new] + fn new( + local_addr_top: &str, + local_addr_bottom: &str, + frame_stack_size: usize, + shm_handle_path: &str, + mode: Option, + huge: Option, + crop_to_image_data: Option, + py: Python, + ) -> PyResult { + let _trace_guard = span_from_py(py, "K2Connection::new")?; + + // to have some slack, we need some more memory in IS mode: + let mode = mode.unwrap_or(K2Mode::IS); + + let num_slots = match mode { + K2Mode::IS => 1600, // about 2 seconds of buffering + K2Mode::Summit => 100, // TODO: update with realistic value here + }; + + if frame_stack_size != 1 { + return Err(PyRuntimeError::new_err( + "frame_stack_size != 1 is not yet supported", + )); + } + + let crop_to_image_data = crop_to_image_data.unwrap_or(true); + + let config = K2DetectorConnectionConfig::new( + mode, + local_addr_top.to_owned(), + local_addr_bottom.to_owned(), + num_slots, + huge.unwrap_or(false), + shm_handle_path.to_owned(), + 1, // FIXME: pass down `frame_stack_size` once a value != 1 is supported + false, + false, + crop_to_image_data, + ); + + let shm = + GenericConnection::::shm_from_config(&config) + .map_err(|e| PyConnectionError::new_err(e.to_string()))?; + + let bg_thread = K2BackgroundThread::spawn(&config, &shm) + .map_err(|e| PyConnectionError::new_err(e.to_string()))?; + + let generic_conn = + GenericConnection::::new(bg_thread, &shm) + .map_err(|e| PyConnectionError::new_err(e.to_string()))?; + + let conn = _PyK2Connection::new(shm, generic_conn); + Ok(Self { conn, config }) + } + + fn get_frame_shape(&self) -> (usize, usize) { + let shape = self + .config + .mode + .get_frame_shape(self.config.crop_to_image_data); + (shape.height, shape.width) + } + + fn wait_for_arm( + &mut self, + timeout: Option, + py: Python<'_>, + ) -> PyResult> { + self.conn.wait_for_arm(timeout, py) + } + + fn get_socket_path(&self) -> PyResult { + self.conn.get_socket_path() + } + + fn is_running(&self) -> PyResult { + self.conn.is_running() + } + + fn start_passive( + &mut self, + timeout: Option, + acquisition_size: Option, + py: Python<'_>, + ) -> PyResult<()> { + let _trace_guard = span_from_py(py, "K2Connection::start_passive")?; + + self.conn.start_passive(timeout, acquisition_size, py) + } + + fn passive_is_running(&self) -> PyResult { + self.conn.passive_is_running() + } + + fn close(&mut self, py: Python) -> PyResult<()> { + self.conn.close(py) + } + + fn cancel(&mut self, timeout: Option, py: Python) -> PyResult<()> { + self.conn.cancel(timeout, py) + } + + fn get_next_stack( + &mut self, + max_size: usize, + py: Python<'_>, + ) -> PyResult> { + self.conn.get_next_stack(max_size, py) + } +} + +impl_py_cam_client!( + _PyK2CamClient, + K2Decoder, + K2FrameStack, + K2FrameMeta, + libertem_k2is +); + +#[pyclass] +pub struct K2CamClient { + inner: _PyK2CamClient, +} + +#[pymethods] +impl K2CamClient { + #[new] + fn new(py: Python, handle_path: &str) -> PyResult { + Ok(Self { + inner: _PyK2CamClient::new(py, handle_path)?, + }) + } + + fn decode_range_into_buffer<'py>( + &self, + input: &K2FrameStack, + out: &Bound<'py, PyUntypedArray>, + start_idx: usize, + end_idx: usize, + py: Python<'py>, + ) -> PyResult<()> { + self.inner + .decode_range_into_buffer(input, out, start_idx, end_idx, py) + } + + fn done(&mut self, handle: &mut K2FrameStack) -> PyResult<()> { + self.inner.frame_stack_done(handle) + } + + fn close(&mut self) -> PyResult<()> { + self.inner.close() + } +} + +impl Drop for K2CamClient { + fn drop(&mut self) { + trace!("CamClient::drop"); + } +} diff --git a/libertem_qd_mpx/Cargo.toml b/libertem_qd_mpx/Cargo.toml index 8ef34ed1..bedd4d25 100644 --- a/libertem_qd_mpx/Cargo.toml +++ b/libertem_qd_mpx/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" version = "0.2.14" edition = "2021" readme = "README.md" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # [lib] @@ -16,7 +16,7 @@ rust-version = "1.71" bincode = "1.3.3" env_logger = "0.11.5" log = "0.4.22" -pyo3 = { version = "0.21.0", features = ["abi3-py37"] } +pyo3 = { version = "0.21.0", features = ["abi3-py39"] } serde = { version = "1.0.210", features = ["derive"] } ipc-test = { path = "../ipc_test" } stats = { path = "../stats" } diff --git a/libertem_qd_mpx/pyproject.toml b/libertem_qd_mpx/pyproject.toml index 24f21e96..e0df66d4 100644 --- a/libertem_qd_mpx/pyproject.toml +++ b/libertem_qd_mpx/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "libertem_qd_mpx" -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/libertem_qd_mpx/src/background_thread.rs b/libertem_qd_mpx/src/background_thread.rs index acd5a7f6..a7226bf1 100644 --- a/libertem_qd_mpx/src/background_thread.rs +++ b/libertem_qd_mpx/src/background_thread.rs @@ -8,7 +8,9 @@ use std::{ }; use common::{ - background_thread::{BackgroundThread, BackgroundThreadSpawnError, ControlMsg, ReceiverMsg}, + background_thread::{ + AcquisitionSize, BackgroundThread, BackgroundThreadSpawnError, ControlMsg, ReceiverMsg, + }, frame_stack::{FrameMeta, FrameStackForWriting, FrameStackWriteError, WriteGuard}, tcp::{self, ReadExactError}, utils::{num_from_byte_slice, NumParseError}, @@ -123,9 +125,8 @@ pub struct QdBackgroundThread { /// especially convert `ControlMsg::StopThread` to `AcquisitionError::Cancelled`. fn check_for_control(control_channel: &Receiver) -> Result<(), AcquisitionError> { match control_channel.try_recv() { - Ok(ControlMsg::StartAcquisitionPassive) => Err(AcquisitionError::StateError { - msg: "received StartAcquisitionPassive while an acquisition was already running" - .to_string(), + Ok(m @ ControlMsg::StartAcquisitionPassive { .. }) => Err(AcquisitionError::StateError { + msg: format!("received {m:?} while an acquisition was already running"), }), Ok(ControlMsg::StopThread) => Err(AcquisitionError::ThreadStopped), Ok(ControlMsg::SpecializedControlMsg { msg: _ }) => { @@ -472,7 +473,7 @@ fn acquisition( info!("done in {elapsed:?}"); let handle = frame_stack.writing_done()?; from_thread_s.send(ReceiverMsg::Finished { - frame_stack: handle, + frame_stack: Some(handle), })?; return Ok(()); @@ -538,6 +539,7 @@ impl DerefMut for TcpStreamGuard { } fn passive_acquisition( + acquisition_size: AcquisitionSize, to_thread_r: &Receiver, from_thread_s: &Sender, config: &QdDetectorConnConfig, @@ -546,6 +548,15 @@ fn passive_acquisition( let host = &config.data_host; let port = config.data_port; + if acquisition_size != AcquisitionSize::Auto && acquisition_size != AcquisitionSize::Continuous + { + return Err(AcquisitionError::ConfigurationError { + msg: format!( + "unsupported parameter: acquisition_size must be Auto or Continuous, is {acquisition_size:?}" + ), + }); + } + let data_uri = format!("{host}:{port}"); info!("connecting to {}...", &data_uri); @@ -635,11 +646,17 @@ fn background_thread( ) -> Result<(), AcquisitionError> { 'outer: loop { loop { - // control: main threads tells us to quit + // control: main threads tells us what to do let control = to_thread_r.recv_timeout(Duration::from_millis(100)); match control { - Ok(ControlMsg::StartAcquisitionPassive) => { - match passive_acquisition(to_thread_r, from_thread_s, config, &mut shm) { + Ok(ControlMsg::StartAcquisitionPassive { acquisition_size }) => { + match passive_acquisition( + acquisition_size, + to_thread_r, + from_thread_s, + config, + &mut shm, + ) { Ok(_) => {} Err(AcquisitionError::Cancelled) => { info!("acquisition cancelled by user"); @@ -769,7 +786,10 @@ mod test { time::{Duration, Instant}, }; - use common::generic_connection::{ConnectionError, ConnectionStatus, GenericConnection}; + use common::{ + background_thread::AcquisitionSize, + generic_connection::{ConnectionError, ConnectionStatus, GenericConnection}, + }; use ipc_test::SharedSlabAllocator; use log::info; use tempfile::{tempdir, TempDir}; @@ -959,6 +979,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1031,6 +1052,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1118,6 +1140,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1132,6 +1155,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1233,6 +1257,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1338,6 +1363,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1448,6 +1474,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(500)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1560,6 +1587,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1664,6 +1692,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1799,6 +1828,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1831,6 +1861,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(1000)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1946,6 +1977,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); @@ -1978,6 +2010,7 @@ End conn.start_passive( || Ok::<(), ConnectionError>(()), &Some(Duration::from_millis(100)), + AcquisitionSize::Auto, ) .unwrap(); diff --git a/libertem_qd_mpx/src/base_types.rs b/libertem_qd_mpx/src/base_types.rs index 62cdf174..5b3ba647 100644 --- a/libertem_qd_mpx/src/base_types.rs +++ b/libertem_qd_mpx/src/base_types.rs @@ -8,6 +8,7 @@ use std::{ }; use common::{ + background_thread::ConcreteAcquisitionSize, frame_stack::FrameMeta, generic_connection::{AcquisitionConfig, DetectorConnectionConfig}, }; @@ -759,8 +760,8 @@ impl QdAcquisitionConfig { } impl AcquisitionConfig for QdAcquisitionConfig { - fn num_frames(&self) -> usize { - self.acq_header.frames_in_acquisition + fn acquisition_size(&self) -> common::background_thread::ConcreteAcquisitionSize { + ConcreteAcquisitionSize::NumFrames(self.acq_header.frames_in_acquisition) } } diff --git a/libertem_qd_mpx/src/main_py.rs b/libertem_qd_mpx/src/main_py.rs index caf35764..50539fd0 100644 --- a/libertem_qd_mpx/src/main_py.rs +++ b/libertem_qd_mpx/src/main_py.rs @@ -128,7 +128,7 @@ impl QdConnection { } fn start_passive(&mut self, timeout: Option, py: Python<'_>) -> PyResult<()> { - self.conn.start_passive(timeout, py) + self.conn.start_passive(timeout, None, py) } fn close(&mut self, py: Python) -> PyResult<()> { diff --git a/playegui/Cargo.lock b/playegui/Cargo.lock deleted file mode 100644 index 113d9d93..00000000 --- a/playegui/Cargo.lock +++ /dev/null @@ -1,3520 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe21446ad43aa56417a767f3e2f3d7c4ca522904de1dd640529a76e9c5c3b33c" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - -[[package]] -name = "accesskit" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4803cf8c252f374ae6bfbb341e49e5a37f7601f2ce74a105927a663eba952c67" -dependencies = [ - "enumn", - "serde", -] - -[[package]] -name = "accesskit_consumer" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee8cf1202a4f94d31837f1902ab0a75c77b65bf59719e093703abe83efd74ec" -dependencies = [ - "accesskit", - "parking_lot 0.12.1", -] - -[[package]] -name = "accesskit_macos" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10be25f2b27bc33aa1647072e86b948b41596f1af1ae43a2b4b9be5d2011cbda" -dependencies = [ - "accesskit", - "accesskit_consumer", - "objc2", - "once_cell", - "parking_lot 0.12.1", -] - -[[package]] -name = "accesskit_unix" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630e7ee8f93c6246478bf0df6760db899b28d9ad54353a5f2d3157138ba817fc" -dependencies = [ - "accesskit", - "accesskit_consumer", - "async-channel", - "atspi", - "futures-lite", - "parking_lot 0.12.1", - "serde", - "zbus", -] - -[[package]] -name = "accesskit_windows" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13c462fabdd950ef14308a9390b07fa2e2e3aabccba1f3ea36ea2231bb942ab" -dependencies = [ - "accesskit", - "accesskit_consumer", - "arrayvec", - "once_cell", - "parking_lot 0.12.1", - "paste", - "windows", -] - -[[package]] -name = "accesskit_winit" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17727888757ec027ec221db33070e226ee07df44425b583bc67684204d35eff9" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_unix", - "accesskit_windows", - "parking_lot 0.12.1", - "winit", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "serde", - "version_check 0.9.4", -] - -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-activity" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4165a1aef703232031b40a6e8908c2f9e314d495f11aa7f98db75d39a497cc6a" -dependencies = [ - "android-properties", - "bitflags", - "cc", - "jni-sys", - "libc", - "log 0.4.17", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "arboard" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854" -dependencies = [ - "clipboard-win", - "log 0.4.17", - "objc", - "objc-foundation", - "objc_id", - "once_cell", - "parking_lot 0.12.1", - "thiserror", - "winapi 0.3.9", - "x11rb", -] - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "async-broadcast" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95" -dependencies = [ - "event-listener", - "futures-core", - "parking_lot 0.12.1", -] - -[[package]] -name = "async-channel" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-io" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" -dependencies = [ - "async-lock", - "autocfg 1.1.0", - "concurrent-queue", - "futures-lite", - "libc", - "log 0.4.17", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "windows-sys 0.42.0", -] - -[[package]] -name = "async-lock" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" -dependencies = [ - "event-listener", - "futures-lite", -] - -[[package]] -name = "async-recursion" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-task" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" - -[[package]] -name = "async-trait" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic_refcell" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "857253367827bd9d0fd973f0ef15506a96e79e41b0ad7aa691203a4e3214f6c8" - -[[package]] -name = "atspi" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab84c09a770065868da0d713f1f4b35af85d96530a868f1c1a6c249178379187" -dependencies = [ - "async-recursion", - "async-trait", - "atspi-macros", - "enumflags2", - "futures-lite", - "serde", - "tracing", - "zbus", - "zbus_names", -] - -[[package]] -name = "atspi-macros" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3ebc5a6f61f6996eca56a4cece7b3fe7da3b86f0473c7b71ab44e229f3acce4" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn", - "zbus", - "zbus_names", - "zvariant", -] - -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" -dependencies = [ - "generic-array 0.14.6", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "block-sys" -version = "0.1.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" -dependencies = [ - "block-sys", - "objc2-encode", -] - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "bytemuck" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" - -[[package]] -name = "calloop" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a59225be45a478d772ce015d9743e49e92798ece9e34eda9a6aa2a6a7f40192" -dependencies = [ - "log 0.4.17", - "nix 0.25.1", - "slotmap", - "thiserror", - "vec_map", -] - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cgl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] - -[[package]] -name = "clipboard-win" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" -dependencies = [ - "error-code", - "str-buf", - "winapi 0.3.9", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes 1.4.0", - "memchr", -] - -[[package]] -name = "concurrent-queue" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" -dependencies = [ - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation", - "foreign-types", - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.14", - "memoffset 0.7.1", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array 0.14.6", - "typenum", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" -dependencies = [ - "block-buffer 0.10.3", - "crypto-common", -] - -[[package]] -name = "directories-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "ecolor" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f99fe3cac305af9d6d92971af60d0f7ea4d783201ef1673571567b6699964d9" -dependencies = [ - "bytemuck", - "serde", -] - -[[package]] -name = "eframe" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07e59d9d5ba69e1d261c76e6aa88a95601375805ee473de5eb3163bf5a57704" -dependencies = [ - "bytemuck", - "directories-next", - "egui", - "egui-winit", - "egui_glow", - "glow", - "glutin", - "glutin-winit", - "js-sys", - "percent-encoding 2.2.0", - "raw-window-handle", - "ron", - "serde", - "thiserror", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winit", -] - -[[package]] -name = "egui" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6412a21e0bde7c0918f7fb44bbbb86b5e1f88e63c026a4e747cc7af02f76dfbe" -dependencies = [ - "accesskit", - "ahash", - "epaint", - "nohash-hasher", - "ron", - "serde", - "tracing", -] - -[[package]] -name = "egui-winit" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13deffe034ab864042f00d0d1fa220b86bb9a230a7362b81844bb8d1dc6b899" -dependencies = [ - "accesskit_winit", - "android-activity", - "arboard", - "egui", - "instant", - "serde", - "smithay-clipboard", - "tracing", - "webbrowser", - "winit", -] - -[[package]] -name = "egui_glow" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8257332fb168a965b3dca81d6a344e053153773c889cabdba0b3b76f1629ae81" -dependencies = [ - "bytemuck", - "egui", - "glow", - "memoffset 0.6.5", - "tracing", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "emath" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ecd80612937e0267909d5351770fe150004e24dab93954f69ca62eecd3f77e" -dependencies = [ - "bytemuck", - "serde", -] - -[[package]] -name = "enumflags2" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "enumn" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88bcb3a067a6555d577aba299e75eff9942da276e6506fc6274327daa026132" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "epaint" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e78b5c58a1f7f621f9d546add2adce20636422c9b251e29f749e8a2f713c95" -dependencies = [ - "ab_glyph", - "ahash", - "atomic_refcell", - "bytemuck", - "ecolor", - "emath", - "nohash-hasher", - "parking_lot 0.12.1", - "serde", -] - -[[package]] -name = "error-code" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - -[[package]] -name = "flate2" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding 2.2.0", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - -[[package]] -name = "futures-core" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" - -[[package]] -name = "futures-io" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-sink" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" - -[[package]] -name = "futures-task" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" - -[[package]] -name = "futures-util" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" -dependencies = [ - "futures-core", - "futures-sink", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check 0.9.4", -] - -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "getrandom" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log 0.4.17", - "xml-rs", -] - -[[package]] -name = "glow" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8edf6019dff2d92ad27c1e3ff82ad50a0aea5b01370353cc928bfdc33e95925c" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glutin" -version = "0.30.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8bdbc089506fecf7466c194c806931300c6a1d4f578e88cc215a7726f998dfb" -dependencies = [ - "bitflags", - "cfg_aliases", - "cgl", - "core-foundation", - "dispatch", - "glutin_egl_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "libloading", - "objc2", - "once_cell", - "raw-window-handle", - "wayland-sys 0.30.1", - "windows-sys 0.45.0", - "x11-dl", -] - -[[package]] -name = "glutin-winit" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" -dependencies = [ - "cfg_aliases", - "glutin", - "raw-window-handle", - "winit", -] - -[[package]] -name = "glutin_egl_sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5aaf0abb5c4148685b33101ae326a207946b4d3764d6cdc79f8316cdaa8367d" -dependencies = [ - "gl_generator", - "windows-sys 0.45.0", -] - -[[package]] -name = "glutin_glx_sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b53cb5fe568964aa066a3ba91eac5ecbac869fb0842cd0dc9e412434f1a1494" -dependencies = [ - "gl_generator", - "x11-dl", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef89398e90033fc6bc65e9bd42fd29bbbfd483bda5b56dc5562f455550618165" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase", - "url 1.7.2", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" -dependencies = [ - "autocfg 1.1.0", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "itoa" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log 0.4.17", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.139" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg 1.1.0", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.17", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memmap2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg 1.1.0", -] - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg 1.1.0", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.17", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" -dependencies = [ - "libc", - "log 0.4.17", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log 0.4.17", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "net2" -version = "0.2.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg 1.1.0", - "bitflags", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", - "pin-utils", -] - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom8" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" -dependencies = [ - "memchr", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi 0.3.9", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc-sys" -version = "0.2.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" - -[[package]] -name = "objc2" -version = "0.3.0-beta.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe31e5425d3d0b89a15982c024392815da40689aceb34bad364d58732bcfd649" -dependencies = [ - "block2", - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "once_cell" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "openssl" -version = "0.10.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" -dependencies = [ - "autocfg 1.1.0", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "orbclient" -version = "0.3.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba683f1641c11041c59d5d93689187abcab3c1349dc6d9d70c550c9f9360802f" -dependencies = [ - "cfg-if 1.0.0", - "redox_syscall 0.2.16", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "owned_ttf_parser" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25e9fb15717794fae58ab55c26e044103aad13186fbb625893f9a3bbcc24228" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.3", - "rustc_version", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api 0.4.9", - "parking_lot_core 0.9.7", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "rustc_version", - "smallvec 0.6.14", - "winapi 0.3.9", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.2.16", - "smallvec 1.10.0", - "windows-sys 0.45.0", -] - -[[package]] -name = "paste" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" - -[[package]] -name = "playegui" -version = "0.1.0" -dependencies = [ - "crossbeam", - "eframe", - "egui", - "log 0.4.17", - "serde", - "serde_json", - "tracing-subscriber", - "websocket", -] - -[[package]] -name = "png" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" -dependencies = [ - "bitflags", - "crc32fast", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 1.0.0", - "libc", - "log 0.4.17", - "wepoll-ffi", - "windows-sys 0.42.0", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi 0.3.9", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.9", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.9", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" -dependencies = [ - "cty", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb02a9aee8e8c7ad8d86890f1e16b49e0bbbffc9961ff3788c31d57c98bcbf03" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ron" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" -dependencies = [ - "base64 0.13.1", - "bitflags", - "serde", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sctk-adwaita" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc56402866c717f54e48b122eb93c69f709bc5a6359c403598992fd92f017931" -dependencies = [ - "ab_glyph", - "log 0.4.17", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - -[[package]] -name = "security-framework" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-xml-rs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0bf1ba0696ccf0872866277143ff1fd14d22eec235d2b23702f95e6660f7dfa" -dependencies = [ - "log 0.4.17", - "serde", - "thiserror", - "xml-rs", -] - -[[package]] -name = "serde_derive" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.6", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "slab" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" -dependencies = [ - "autocfg 1.1.0", -] - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check 0.9.4", -] - -[[package]] -name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "smithay-client-toolkit" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" -dependencies = [ - "bitflags", - "calloop", - "dlib", - "lazy_static", - "log 0.4.17", - "memmap2", - "nix 0.24.3", - "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - -[[package]] -name = "strict-num" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df65f20698aeed245efdde3628a6b559ea1239bbb871af1b6e3b58c413b2bd1" - -[[package]] -name = "syn" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "libc", - "redox_syscall 0.2.16", - "remove_dir_all", - "winapi 0.3.9", -] - -[[package]] -name = "thiserror" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" -dependencies = [ - "once_cell", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - -[[package]] -name = "tiny-skia" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfef3412c6975196fdfac41ef232f910be2bb37b9dd3313a49a1a6bc815a5bdb" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if 1.0.0", - "png", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b5edac058fc98f51c935daea4d805b695b38e2f151241cad125ade2a2ac20d" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures", - "tokio-io", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures", - "log 0.4.17", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures", - "lazy_static", - "log 0.4.17", - "mio 0.6.23", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", -] - -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures", - "iovec", - "mio 0.6.23", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-tls" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -dependencies = [ - "futures", - "native-tls", - "tokio-io", -] - -[[package]] -name = "toml_datetime" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" - -[[package]] -name = "toml_edit" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" -dependencies = [ - "indexmap", - "nom8", - "toml_datetime", -] - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log 0.4.17", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" -dependencies = [ - "nu-ansi-term", - "sharded-slab", - "smallvec 1.10.0", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - -[[package]] -name = "ttf-parser" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "uds_windows" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" -dependencies = [ - "tempfile", - "winapi 0.3.9", -] - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" - -[[package]] -name = "unicode-ident" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna 0.3.0", - "percent-encoding 2.2.0", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" -dependencies = [ - "bumpalo", - "log 0.4.17", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" - -[[package]] -name = "wayland-client" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.24.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys 0.29.5", -] - -[[package]] -name = "wayland-commons" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" -dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec 1.10.0", - "wayland-sys 0.29.5", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" -dependencies = [ - "nix 0.24.3", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "wayland-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" -dependencies = [ - "dlib", - "lazy_static", - "log 0.4.17", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d1fa1e5c829b2bf9eb1e28fb950248b797cd6a04866fbdfa8bc31e5eef4c78" -dependencies = [ - "core-foundation", - "dirs", - "jni", - "log 0.4.17", - "ndk-context", - "objc", - "raw-window-handle", - "url 2.3.1", - "web-sys", -] - -[[package]] -name = "websocket" -version = "0.26.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacab060eea423e4036820ddd28f3f9003b2c4d8048cbda985e5a14e18038d" -dependencies = [ - "bytes 0.4.12", - "futures", - "hyper", - "native-tls", - "rand 0.6.5", - "tokio-codec", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-tls", - "unicase", - "url 1.7.2", - "websocket-base", -] - -[[package]] -name = "websocket-base" -version = "0.26.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49aec794b07318993d1db16156d5a9c750120597a5ee40c6b928d416186cb138" -dependencies = [ - "base64 0.10.1", - "bitflags", - "byteorder", - "bytes 0.4.12", - "futures", - "native-tls", - "rand 0.6.5", - "sha-1", - "tokio-codec", - "tokio-io", - "tokio-tcp", - "tokio-tls", -] - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0286ba339aa753e70765d521bb0242cc48e1194562bfa2a2ad7ac8a6de28f5d5" -dependencies = [ - "windows-implement", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows-implement" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9539b6bd3eadbd9de66c9666b22d802b833da7e996bc06896142e09854a61767" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" - -[[package]] -name = "winit" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4755d4ba0e3d30fc7beef2095e246b1e6a6fad0717608bcb87a2df4b003bcf" -dependencies = [ - "android-activity", - "bitflags", - "cfg_aliases", - "core-foundation", - "core-graphics", - "dispatch", - "instant", - "libc", - "log 0.4.17", - "mio 0.8.5", - "ndk", - "objc2", - "once_cell", - "orbclient", - "percent-encoding 2.2.0", - "raw-window-handle", - "redox_syscall 0.3.4", - "sctk-adwaita", - "smithay-client-toolkit", - "wasm-bindgen", - "wayland-client", - "wayland-commons", - "wayland-protocols", - "wayland-scanner", - "web-sys", - "windows-sys 0.45.0", - "x11-dl", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" -dependencies = [ - "gethostname", - "nix 0.24.3", - "winapi 0.3.9", - "winapi-wsapoll", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" -dependencies = [ - "nix 0.24.3", -] - -[[package]] -name = "xcursor" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" -dependencies = [ - "nom", -] - -[[package]] -name = "xml-rs" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" - -[[package]] -name = "zbus" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f770930448dd412a4a7131dd968a8e6df0064db4d7916fbbd2d6c3f26b566938" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-recursion", - "async-task", - "async-trait", - "byteorder", - "derivative", - "dirs", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.25.1", - "once_cell", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde-xml-rs", - "serde_repr", - "sha1", - "static_assertions", - "tracing", - "uds_windows", - "winapi 0.3.9", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4832059b438689017db7340580ebabba07f114eab91bf990c6e55052408b40d8" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "syn", -] - -[[package]] -name = "zbus_names" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" -dependencies = [ - "serde", - "static_assertions", - "zvariant", -] - -[[package]] -name = "zvariant" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51" -dependencies = [ - "byteorder", - "enumflags2", - "libc", - "serde", - "static_assertions", - "zvariant_derive", -] - -[[package]] -name = "zvariant_derive" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] diff --git a/playegui/Cargo.toml b/playegui/Cargo.toml index a9fa1e44..05b5c375 100644 --- a/playegui/Cargo.toml +++ b/playegui/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.1.0" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/serval-client/Cargo.toml b/serval-client/Cargo.toml index b8d8f628..3141833e 100644 --- a/serval-client/Cargo.toml +++ b/serval-client/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.1.0" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/stats/Cargo.toml b/stats/Cargo.toml index 5cb0e744..a2c6ba4c 100644 --- a/stats/Cargo.toml +++ b/stats/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Alexander Clausen "] license = "MIT" version = "0.1.0" edition = "2021" -rust-version = "1.71" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html