From 6d6ee838bfb514920a71c0e09f9eb524935eb616 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:04:34 +0300 Subject: [PATCH 1/8] chore: bump criterion Signed-off-by: NotAShelf Change-Id: I5623347364c5ed71c99676029f4261026a6a6964 --- Cargo.lock | 29 +++++++++++++++++++++++++---- Cargo.toml | 2 +- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0147746..423e558 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "anes" version = "0.1.6" @@ -271,10 +280,11 @@ dependencies = [ [[package]] name = "criterion" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" dependencies = [ + "alloca", "anes", "cast", "ciborium", @@ -283,6 +293,7 @@ dependencies = [ "itertools", "num-traits", "oorandom", + "page_size", "plotters", "rayon", "regex", @@ -294,9 +305,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" dependencies = [ "cast", "itertools", @@ -816,6 +827,16 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "percent-encoding" version = "2.3.2" diff --git a/Cargo.toml b/Cargo.toml index e95ef5c..076441c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ hotpath = { optional = true, version = "0.6.0" } libc = "0.2.177" [dev-dependencies] -criterion = "0.7" +criterion = "0.8.0" [features] hotpath = [ "dep:hotpath", "hotpath/hotpath" ] From c3a6d1c93cfa22f21a45fc085eb589576e1fdafd Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:06:33 +0300 Subject: [PATCH 2/8] treewide: fix commonmark formatting in Rustdoc Signed-off-by: NotAShelf Change-Id: Ie1a13221aded56f903156fdb35abe2ac6a6a6964 --- src/lib.rs | 3 ++- src/syscall.rs | 11 +++++++++-- src/uptime.rs | 5 +++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8c8a6ba..1e0f9f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,8 @@ impl UtsName { /// Calls `uname` syscall and returns a `UtsName` wrapper /// /// # Errors - /// Returns an error if the uname syscall fails + /// + /// Returns an error if the `uname` syscall fails pub fn uname() -> Result { let mut uts = MaybeUninit::uninit(); if unsafe { libc::uname(uts.as_mut_ptr()) } != 0 { diff --git a/src/syscall.rs b/src/syscall.rs index 2776fe7..0c8634b 100644 --- a/src/syscall.rs +++ b/src/syscall.rs @@ -11,11 +11,15 @@ use std::io; /// Direct syscall to open a file -/// Returns file descriptor or -1 on error +/// +/// # Returns +/// +/// File descriptor or -1 on error /// /// # Safety /// /// The caller must ensure: +/// /// - `path` points to a valid null-terminated C string /// - The pointer remains valid for the duration of the syscall #[inline] @@ -65,7 +69,10 @@ pub unsafe fn sys_open(path: *const u8, flags: i32) -> i32 { } /// Direct syscall to read from a file descriptor -/// Returns number of bytes read or -1 on error +/// +/// # Returns n +/// +/// Number of bytes read or -1 on error /// /// # Safety /// diff --git a/src/uptime.rs b/src/uptime.rs index 98c9207..095af7d 100644 --- a/src/uptime.rs +++ b/src/uptime.rs @@ -1,6 +1,6 @@ use std::{io, mem::MaybeUninit}; -/// Fast integer to string conversion (no formatting overhead) +/// Faster integer to string conversion without the formatting overhead. #[inline] fn itoa(mut n: u64, buf: &mut [u8]) -> &str { if n == 0 { @@ -17,9 +17,10 @@ fn itoa(mut n: u64, buf: &mut [u8]) -> &str { unsafe { std::str::from_utf8_unchecked(&buf[i..]) } } -/// Direct sysinfo syscall using inline assembly +/// Direct `sysinfo` syscall using inline assembly /// /// # Safety +/// /// This function uses inline assembly to make a direct syscall. /// The caller must ensure the sysinfo pointer is valid. #[inline] From c1a4bc24f46420336d3aabf7edd2d56d1f6fc143 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:06:48 +0300 Subject: [PATCH 3/8] docs: add note about handwritten assembly Signed-off-by: NotAShelf Change-Id: I6920a416e6169a84469514bae0f207426a6a6964 --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a40e444..1bd7124 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,14 @@ Nixpkgs, you are recommended to use it to utilize the binary cache properly. The usage of Rust _is_ nice, however, since it provides us with incredible tooling and a very powerful language that allows for Microfetch to be as fast as possible. Sure C could've been used here as well, but do you think I hate -myself? [^1] +myself? -[^1]: Okay, maybe a little bit. One of the future goals of Microfetch is to - defer to inline Assembly for the costliest functions, but that's for a - future date and until I do that I can pretend to be sane. +> [!IMPORTANT] +> **Update as of November 30th, 2025**: +> +> Microfetch now inlines handwritten assembly for even better performance. I +> know I previously said I do not hate myself but I'm beginning to suspect this +> is no longer the case. Enjoy the performance benefits! ## Benchmarks From 09da1c27d21cea01bca93224726ddb3ed95d2441 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:13:14 +0300 Subject: [PATCH 4/8] chore: bump hotpath Signed-off-by: NotAShelf Change-Id: I1ae1d9b3d25ff220bee51660efc598b76a6a6964 --- Cargo.lock | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 9 +++---- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 423e558..88deaeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,6 +462,50 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -513,9 +557,9 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hotpath" -version = "0.6.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef44238d7007bbd3c41ce7dbf3d7a4fb224bbf70d6cf3162479138dda0cd6a9e" +checksum = "08382b985a19a79d95d35e2e201b02cc4b99efe2f47d82f3fd4301bb0005bb68" dependencies = [ "arc-swap", "base64", @@ -524,10 +568,15 @@ dependencies = [ "colored", "crossbeam-channel", "eyre", + "futures-util", "hdrhistogram", "hotpath-macros", + "libc", + "mach2", + "pin-project-lite", "prettytable-rs", "quanta", + "regex", "serde", "serde_json", "tiny_http", @@ -537,9 +586,9 @@ dependencies = [ [[package]] name = "hotpath-macros" -version = "0.6.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7e3443c6f4e5cc69e6b701f7bfca8a5502f0080e94629413346e7b4518d730" +checksum = "7d618063f89423ebe079a69f5435a13d4909219d4e359757118b75fd05ae65d0" dependencies = [ "proc-macro2", "quote", @@ -769,6 +818,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" + [[package]] name = "memchr" version = "2.7.4" @@ -849,6 +904,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "plotters" version = "0.3.7" @@ -1121,6 +1182,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + [[package]] name = "smallvec" version = "1.15.1" diff --git a/Cargo.toml b/Cargo.toml index 076441c..f7a2f81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,17 +12,16 @@ name = "microfetch" path = "src/main.rs" [dependencies] -hotpath = { optional = true, version = "0.6.0" } +hotpath = { optional = true, version = "0.7.5" } libc = "0.2.177" [dev-dependencies] criterion = "0.8.0" [features] -hotpath = [ "dep:hotpath", "hotpath/hotpath" ] -hotpath-alloc-bytes-total = [ "hotpath/hotpath-alloc-bytes-total" ] -hotpath-alloc-count-total = [ "hotpath/hotpath-alloc-count-total" ] -hotpath-off = [ "hotpath/hotpath-off" ] +hotpath = [ "dep:hotpath", "hotpath/hotpath" ] +hotpath-alloc = [ "hotpath/hotpath-alloc" ] +hotpath-off = [ "hotpath/hotpath-off" ] [[bench]] harness = false From 48c3807148892b5888b342cc4a64601c8cf15800 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:14:53 +0300 Subject: [PATCH 5/8] docs: update hotpath usage instructions Signed-off-by: NotAShelf Change-Id: I8a056b6814bef36e74b4aca56d4aa2686a6a6964 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bd7124..aa299ce 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ HOTPATH_JSON=true cargo run --features=hotpath To profile allocations: ```bash -HOTPATH_JSON=true cargo run --features=hotpath,hotpath-alloc-count-total +HOTPATH_JSON=true cargo run --features=hotpath,hotpath-alloc ``` The JSON output can be analyzed with the `hotpath` CLI tool for detailed From 8d97a9e8ec543611c4fde53c688a13ebd3b9a552 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:32:40 +0300 Subject: [PATCH 6/8] ci: streamline workflows; remove tagged release workflow Signed-off-by: NotAShelf Change-Id: I1432980533dee11b64a53d2ad2f2094d6a6a6964 --- .github/workflows/hotpath-comment.yml | 51 +++++++++++++++++---------- .github/workflows/hotpath-profile.yml | 30 ++++++++-------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/.github/workflows/hotpath-comment.yml b/.github/workflows/hotpath-comment.yml index 8f83d00..4e072fe 100644 --- a/.github/workflows/hotpath-comment.yml +++ b/.github/workflows/hotpath-comment.yml @@ -1,12 +1,13 @@ -name: Hotpath Comment +name: hotpath-comment on: workflow_run: - workflows: ["Hotpath Profile"] + workflows: ["hotpath-profile"] types: - completed permissions: + contents: read pull-requests: write jobs: @@ -15,17 +16,17 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Download profiling results uses: actions/download-artifact@v4 with: name: hotpath-results + path: /tmp/ github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} - - name: Read PR number - id: pr - run: echo "number=$(cat pr_number.txt)" >> $GITHUB_OUTPUT - - name: Setup Rust uses: actions-rust-lang/setup-rust-toolchain@v1 @@ -33,17 +34,29 @@ jobs: run: cargo install hotpath - name: Post timing comparison comment - run: | - hotpath profile-pr \ - --head-metrics head-timing.json \ - --base-metrics base-timing.json \ - --github-token ${{ secrets.GITHUB_TOKEN }} \ - --pr-number ${{ steps.pr.outputs.number }} + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + HEAD_METRICS=$(cat /tmp/head_timing.json) + BASE_METRICS=$(cat /tmp/base_timing.json) + PR_NUMBER=$(cat /tmp/pr_number.txt) + hotpath profile-pr \ + --head-metrics "$HEAD_METRICS" \ + --base-metrics "$BASE_METRICS" \ + --github-token "$GH_TOKEN" \ + --pr-number "$PR_NUMBER" - - name: Post allocation comparison comment - run: | - hotpath profile-pr \ - --head-metrics head-alloc.json \ - --base-metrics base-alloc.json \ - --github-token ${{ secrets.GITHUB_TOKEN }} \ - --pr-number ${{ steps.pr.outputs.number }} + - name: Post allocation comparison comment + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + HEAD_METRICS=$(cat /tmp/head_alloc.json) + BASE_METRICS=$(cat /tmp/base_alloc.json) + PR_NUMBER=$(cat /tmp/pr_number.txt) + hotpath profile-pr \ + --head-metrics "$HEAD_METRICS" \ + --base-metrics "$BASE_METRICS" \ + --github-token "$GH_TOKEN" \ + --pr-number "$PR_NUMBER" diff --git a/.github/workflows/hotpath-profile.yml b/.github/workflows/hotpath-profile.yml index b367ca2..1b4ce26 100644 --- a/.github/workflows/hotpath-profile.yml +++ b/.github/workflows/hotpath-profile.yml @@ -1,4 +1,4 @@ -name: Hotpath Profile +name: hotpath-profile on: pull_request: @@ -14,6 +14,8 @@ jobs: steps: - name: Checkout PR HEAD uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup Rust uses: actions-rust-lang/setup-rust-toolchain@v1 @@ -22,42 +24,42 @@ jobs: env: HOTPATH_JSON: "true" run: | - cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > head-timing.json + cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/head_timing.json - name: Run allocation profiling on HEAD env: HOTPATH_JSON: "true" run: | - cargo run --features='hotpath,hotpath-alloc-count-total' 2>&1 | grep '^{"hotpath_profiling_mode"' > head-alloc.json + cargo run --features='hotpath,hotpath-alloc' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/head_alloc.json - name: Checkout base branch - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.base.sha }} + run: | + git checkout ${{ github.event.pull_request.base.sha }} - name: Run timing profiling on base env: HOTPATH_JSON: "true" run: | - cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > base-timing.json + cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/base_timing.json || echo '{}' > /tmp/base_timing.json - name: Run allocation profiling on base env: HOTPATH_JSON: "true" run: | - cargo run --features='hotpath,hotpath-alloc-count-total' 2>&1 | grep '^{"hotpath_profiling_mode"' > base-alloc.json + cargo run --features='hotpath,hotpath-alloc' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/base_alloc.json || echo '{}' > /tmp/base_alloc.json - name: Save PR number - run: echo "${{ github.event.number }}" > pr_number.txt + run: | + echo '${{ github.event.pull_request.number }}' > /tmp/pr_number.txt - name: Upload profiling results uses: actions/upload-artifact@v4 with: name: hotpath-results path: | - head-timing.json - head-alloc.json - base-timing.json - base-alloc.json - pr_number.txt + /tmp/head_timing.json + /tmp/head_alloc.json + /tmp/base_timing.json + /tmp/base_alloc.json + /tmp/pr_number.txt retention-days: 1 From 16a1d5fe3f8e2d2740f3eae326664621533edcfb Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 15:38:32 +0300 Subject: [PATCH 7/8] ci: set up dependabot for GH actions Signed-off-by: NotAShelf Change-Id: I890272e62db5824a3d866748375d1a9f6a6a6964 --- .github/dependabot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a1067c4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + # Update Cargo deps + - package-ecosystem: cargo + directory: "/" + schedule: + interval: "weekly" + + # Update used workflows + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + From fa8b6b9d689d8bd7bef306b07de03b555d573018 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 30 Nov 2025 16:54:35 +0300 Subject: [PATCH 8/8] ci: set up cross comp for Rust builds Signed-off-by: NotAShelf Change-Id: I154d2afb05088e22882985bcd4536f026a6a6964 --- .github/workflows/rust.yml | 43 +++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e87e1da..b742a24 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,12 +10,45 @@ env: CARGO_TERM_COLOR: always jobs: - build: - - runs-on: ubuntu-latest + test: + name: Test on ${{ matrix.target }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu steps: - name: "Checkout" uses: actions/checkout@v4 - - name: "Build with Cargo" - run: cargo build --verbose + + - name: "Setup Rust toolchain" + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + target: ${{ matrix.target }} + + - name: "Install cross-compilation tools" + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + + - name: "Configure linker for aarch64" + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + mkdir -p .cargo + cat >> .cargo/config.toml << EOF + [target.aarch64-unknown-linux-gnu] + linker = "aarch64-linux-gnu-gcc" + EOF + + - name: "Build" + run: cargo build --verbose --target ${{ matrix.target }} + + - name: "Run tests" + if: matrix.target == 'x86_64-unknown-linux-gnu' + run: cargo test --verbose --target ${{ matrix.target }}