diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index b7efcee..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,4 +0,0 @@ -# https://github.com/rui314/mold?tab=readme-ov-file#how-to-use -[target.'cfg(target_os = "linux")'] -linker = "clang" -rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/.github/workflows/hotpath-comment.yml b/.github/workflows/hotpath-comment.yml index a5ff678..4e072fe 100644 --- a/.github/workflows/hotpath-comment.yml +++ b/.github/workflows/hotpath-comment.yml @@ -17,10 +17,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v4 - name: Download profiling results - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v4 with: name: hotpath-results path: /tmp/ diff --git a/.github/workflows/hotpath-profile.yml b/.github/workflows/hotpath-profile.yml index f79b668..1b4ce26 100644 --- a/.github/workflows/hotpath-profile.yml +++ b/.github/workflows/hotpath-profile.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout PR HEAD - uses: actions/checkout@v6 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -53,7 +53,7 @@ jobs: echo '${{ github.event.pull_request.number }}' > /tmp/pr_number.txt - name: Upload profiling results - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v4 with: name: hotpath-results path: | diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5f435fb..b742a24 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,7 +24,7 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v6 + uses: actions/checkout@v4 - name: "Setup Rust toolchain" uses: actions-rust-lang/setup-rust-toolchain@v1 diff --git a/.gitignore b/.gitignore index 8799178..8ea0ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target result* -/.direnv diff --git a/Cargo.lock b/Cargo.lock index 065eded..3a23f75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -118,6 +124,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + [[package]] name = "cast" version = "0.3.0" @@ -229,10 +241,48 @@ dependencies = [ ] [[package]] -name = "criterion" -version = "0.8.1" +name = "cookie" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc4bff745c9b4c7fb1e97b25d13153da2bc7796260141df62378998d070207f" +dependencies = [ + "cookie", + "document-features", + "idna", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" dependencies = [ "alloca", "anes", @@ -255,9 +305,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" +checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" dependencies = [ "cast", "itertools", @@ -303,6 +353,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -324,6 +383,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "either" version = "1.15.0" @@ -336,6 +415,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "eyre" version = "0.6.12" @@ -352,6 +437,31 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +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 = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures-core" version = "0.3.31" @@ -417,6 +527,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -441,9 +557,9 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hotpath" -version = "0.9.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bff4650da2df45a71a2f5c2c51fdcd5bea79270e0cc2a9984942d57fc77c0d7" +checksum = "08382b985a19a79d95d35e2e201b02cc4b99efe2f47d82f3fd4301bb0005bb68" dependencies = [ "arc-swap", "base64", @@ -465,31 +581,161 @@ dependencies = [ "serde_json", "tiny_http", "tokio", + "ureq", ] [[package]] name = "hotpath-macros" -version = "0.9.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8d87ff506da0e93bac1a7ba104aa79fac048edab9d8ef922e75ba54106ee3d" +checksum = "7d618063f89423ebe079a69f5435a13d4909219d4e359757118b75fd05ae65d0" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indenter" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "is-terminal" version = "0.4.17" @@ -540,9 +786,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libredox" @@ -554,6 +800,18 @@ dependencies = [ "libc", ] +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + [[package]] name = "log" version = "0.4.27" @@ -581,6 +839,22 @@ dependencies = [ "libc", ] +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.19" @@ -618,6 +892,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -658,6 +938,21 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "prettytable-rs" version = "0.10.0" @@ -773,6 +1068,55 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.20" @@ -832,18 +1176,42 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd-adler32" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.100" @@ -855,6 +1223,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "term" version = "0.7.0" @@ -886,6 +1265,37 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny_http" version = "0.12.0" @@ -898,6 +1308,16 @@ dependencies = [ "log", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -929,12 +1349,80 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" +dependencies = [ + "base64", + "cookie_store", + "flate2", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "ureq-proto", + "utf-8", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -1019,6 +1507,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1056,6 +1553,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -1137,3 +1643,92 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index f6ddf6f..c245c00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,11 @@ name = "microfetch" path = "src/main.rs" [dependencies] -hotpath = { optional = true, version = "0.9.0" } -libc = "0.2.178" +hotpath = { optional = true, version = "0.7.5" } +libc = "0.2.177" [dev-dependencies] -criterion = "0.8.1" +criterion = "0.8.0" [features] hotpath = [ "dep:hotpath", "hotpath/hotpath" ] diff --git a/README.md b/README.md index 8f59640..aa299ce 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,15 @@
-

Microfetch

-

Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed

+

+ Microfetch +

+

+ Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed +


Synopsis
- Features | Motivation
| Benchmarks
+ Features | Motivation
Installation
@@ -39,7 +43,7 @@ on your system: it is pretty _[fast](#benchmarks)_... - Fast - Really fast - Minimal dependencies -- Tiny binary (~370kb [^1]) +- Tiny binary (~370kb) - Actually really fast - Cool NixOS logo (other, inferior, distros are not supported) - Reliable detection of following info: @@ -56,47 +60,36 @@ on your system: it is pretty _[fast](#benchmarks)_... - Did I mention fast? - Respects [`NO_COLOR` spec](https://no-color.org/) -[^1]: With the Mold linker, which is enabled by default in the Flake package, - the binary size is roughly 350kb. That's nearly 20kb reduction in size :) - ## Motivation -[Rube-Goldmark Machine]: https://en.wikipedia.org/wiki/Rube_Goldberg_machine +Fastfetch, as its name probably hinted, is a very fast fetch tool written in C. +However, I am not interested in _any_ of its additional features, and I'm not +interested in its configuration options. Sure I can _configure_ it when I +dislike the defaults, but how often would I really change the configuration... -Fastfetch, as its name _probably_ already hinted, is a very fast fetch tool -written in C. I used to use Fastfetch on my systems, but I eventually came to -the realization that I am _not interested in any of its additional features_. I -don't use Sixel, I don't change my configuration more than maybe once a year and -I don't even display most of the fields that it does. Sure the configurability -is nice and I can configure the defaults that I do not like but how often do I -really do that? +Microfetch is my response to this problem. It is an _even faster_ fetch tool +that I would've written in Bash and put in my `~/.bashrc` but is _actually_ +incredibly fast because it opts out of all the customization options provided by +tools such as Fastfetch. Ultimately, it's a small, opinionated binary with a +nice size that doesn't bother me, and incredible speed. Customization? No thank +you. I cannot re-iterate it enough, Microfetch is _annoyingly fast_. -Since I already enjoy programming challenges, and don't use a fetch program that -often, I eventually came to try and answer the question _how fast can I make my -fetch script?_ It is an _even faster_ fetch tool that I would've written in Bash -and put in my `~/.bashrc` but is _actually_ incredibly fast because it opts out -of all the customization options provided by tools such as Fastfetch. Since -Fetch scripts are kind of a coming-of-age ritual for most Linux users, I've -decided to use it on my system. You also might be interested if you like the -defaults and like speed. +The project is written in Rust, which comes at the cost of "bloated" dependency +trees and the increased build times, but we make an extended effort to keep the +dependencies minimal and build times managable. The latter is also very easily +mitigated with Nix's binary cache systems. Since Microfetch is already in +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? -Ultimately, it's a small, opinionated binary with a nice size that doesn't -bother me, and incredible speed. Customization? No thank you. I cannot -re-iterate it enough, Microfetch is _annoyingly fast_. It does not, however, -solve a technical problem. The "problem" Microfetch solves is entirely -self-imposed. On the matter of _size_, the project is written in Rust, which -comes at the cost of "bloated" dependency trees and the increased build times, -but we make an extended effort to keep the dependencies minimal and build times -managable. The latter is also very easily mitigated with Nix's binary cache -systems. Since Microfetch is already in 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?~~ Microfetch now features -handwritten assembly to unsafely optimize some areas. In hindsight you all -should have seen this coming. Is it faster? Yes. - -Also see: [Rube-Goldmark Machine] +> [!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 @@ -204,31 +197,17 @@ You can't. ### Why? -Customization, of most kinds, are expensive: I could try reading environment -variables, parse command-line arguments or read a configuration file to allow -configuring various fields but those inflate execution time and the resource -consumption by a lot. Since Microfetch is closer to a code golf challenge than a -program that attempts to fill a gap, I have elected not to make this trade. +Customization, of any kind, is expensive: I could try reading environment +variables, parse command-line arguments or read a configuration file but all of +those increment execution time and resource consumption by a lot. ### Really? -[main module]: ./src/main.rs -[discussions tab]: https://github.com/NotAShelf/microfetch/discussions - -To be fair, you _can_ customize Microfetch by, well, patching it. It is -certainly not the easiest way of doing so but if you are planning to change -something in Microfetch, patching is the best way to go. It will also the only -way that does not compromise on speed, unless you patch in bad code. Various -users have adapted Microfetch to their distribution by patching the -[main module] and inserting the logo of their choice. This is also the best way -to go if you plan to make small changes. If your changes are not small, you -might want to look for a program that is designed to be customizable; Microfetch -is built for maximum performance. +To be fair, you _can_ customize Microfetch by, well, patching it. It's not the +best way per se, but it will be the only way that does not compromise on speed. The Nix package allows passing patches in a streamlined manner by passing -`.overrideAttrs` to the derivation. You can apply your patches in `patches` and -share your derivations with people. Feel free to use the [discussions tab] to -share your own variants of Microfetch! +`.overrideAttrs` to the derivation. ## Contributing @@ -240,22 +219,13 @@ Contributions that help improve performance in specific areas of Microfetch are welcome. Though, prepare to be bombarded with questions if your changes are large. -### Hacking +## Hacking -A Nix flake is provided. You may use `nix develop` to get started. Direnv users -may instead run `direnv allow` to get a complete environment with shell -integration. +A Nix flake is provided. `nix develop` to get started. Direnv users may simply +run `direnv allow` to get started. -Non-Nix user will need `cargo`, `clang` and `mold` installed on their system to -build Microfetch. As Mold seems to yield _slightly_ better results than the -default linker, it has been set as the default in `.cargo/config.toml` for -x86-64 Linux. You may override those defaults using the `RUSTFLAGS` environment -variable. For example: - -```sh -# Use ld instead of Mold -$ RUSTFLAGS="-C linker=/path/to/ld.lld" cargo build -``` +Non-nix users will need `cargo` and `gcc` installed on their system, see +`Cargo.toml` for available release profiles. ## Thanks @@ -272,7 +242,6 @@ person about current issues. To list a few, special thanks to: - [@sioodmy](https://github.com/sioodmy) - Being cute - [@mewoocat](https://github.com/mewoocat) - The awesome NixOS logo ASCII used in Microfetch -- [@uzaaft](https://github.com/uzaaft) - Helping me going faster Additionally a big thank you to everyone who used, talked about or criticized Microfetch. I might have missed your name here, but you have my thanks. diff --git a/flake.nix b/flake.nix index 90978a2..ed36872 100644 --- a/flake.nix +++ b/flake.nix @@ -10,12 +10,9 @@ forEachSystem = nixpkgs.lib.genAttrs systems; pkgsForEach = nixpkgs.legacyPackages; in { - packages = forEachSystem (system: let - pkgs = pkgsForEach.${system}; - in { + packages = forEachSystem (system: { default = self.packages.${system}.microfetch; - microfetch = pkgs.callPackage ./nix/package.nix {}; - microfetch-mold = pkgs.callPackage ./nix/package.nix {useMold = true;}; + microfetch = pkgsForEach.${system}.callPackage ./nix/package.nix {}; }); devShells = forEachSystem (system: { diff --git a/nix/package.nix b/nix/package.nix index 052f576..dca3cc2 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,22 +1,14 @@ { lib, - stdenv, - stdenvAdapters, rustPlatform, + stdenvAdapters, llvm, - useMold ? stdenv.isLinux && !stdenv.hostPlatform.isAarch, }: let toml = (lib.importTOML ../Cargo.toml).package; pname = toml.name; inherit (toml) version; - - # Select stdenv based on useMold flag - stdenv = - if useMold - then stdenvAdapters.useMoldLinker llvm.stdenv - else llvm.stdenv; in - rustPlatform.buildRustPackage.override {inherit stdenv;} { + rustPlatform.buildRustPackage.override {stdenv = stdenvAdapters.useMoldLinker llvm.stdenv;} { inherit pname version; src = let fs = lib.fileset; @@ -34,14 +26,7 @@ in cargoLock.lockFile = ../Cargo.lock; enableParallelBuilding = true; - buildNoDefaultFeatures = true; - doCheck = false; - - # Only set RUSTFLAGS for mold if useMold is enabled - env = lib.optionalAttrs useMold { - CARGO_LINKER = "clang"; - RUSTFLAGS = "-C link-arg=-fuse-ld=mold"; - }; + env.RUSTFLAGS = "-C link-arg=-fuse-ld=mold"; meta = { description = "Microscopic fetch script in Rust, for NixOS systems"; diff --git a/nix/shell.nix b/nix/shell.nix index ae65e10..111b803 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -1,31 +1,27 @@ { mkShell, - cargo, - rustc, - mold, - clang, rust-analyzer-unwrapped, rustfmt, clippy, + cargo, taplo, + rustc, rustPlatform, gnuplot, }: mkShell { - name = "microfetch"; strictDeps = true; + nativeBuildInputs = [ cargo rustc - mold - clang rust-analyzer-unwrapped (rustfmt.override {asNightly = true;}) clippy taplo - gnuplot # for Criterion.rs plots + gnuplot # For Criterion.rs plots ]; env.RUST_SRC_PATH = "${rustPlatform.rustLibSrc}"; diff --git a/src/colors.rs b/src/colors.rs index 7c65944..07ab9bd 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -1,4 +1,4 @@ -use std::sync::LazyLock; +use std::{env, sync::LazyLock}; pub struct Colors { pub reset: &'static str, @@ -37,8 +37,8 @@ impl Colors { } pub static COLORS: LazyLock = LazyLock::new(|| { - const NO_COLOR: *const libc::c_char = c"NO_COLOR".as_ptr(); - let is_no_color = unsafe { !libc::getenv(NO_COLOR).is_null() }; + // Check for NO_COLOR once at startup + let is_no_color = env::var("NO_COLOR").is_ok(); Colors::new(is_no_color) }); diff --git a/src/desktop.rs b/src/desktop.rs index 501e967..561be03 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -1,27 +1,22 @@ -use std::{ffi::CStr, fmt::Write}; +use std::fmt::Write; #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_desktop_info() -> String { // Retrieve the environment variables and handle Result types - let desktop_str = unsafe { - let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr()); - if ptr.is_null() { - "Unknown" - } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); - s.strip_prefix("none+").unwrap_or(s) - } + let desktop_env = std::env::var("XDG_CURRENT_DESKTOP"); + let display_backend = std::env::var("XDG_SESSION_TYPE"); + + let desktop_str = match desktop_env { + Err(_) => "Unknown", + Ok(ref s) if s.starts_with("none+") => &s[5..], + Ok(ref s) => s.as_str(), }; - let backend_str = unsafe { - let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr()); - if ptr.is_null() { - "Unknown" - } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); - if s.is_empty() { "Unknown" } else { s } - } + let backend_str = match display_backend { + Err(_) => "Unknown", + Ok(ref s) if s.is_empty() => "Unknown", + Ok(ref s) => s.as_str(), }; // Pre-calculate capacity: desktop_len + " (" + backend_len + ")" diff --git a/src/main.rs b/src/main.rs index e29d6d1..4e664bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ mod syscall; mod system; mod uptime; -use std::io::{self, Cursor, Write}; +use std::io::{Write, stdout}; pub use microfetch_lib::UtsName; @@ -81,32 +81,16 @@ fn print_system_info( let cyan = COLORS.cyan; let blue = COLORS.blue; let reset = COLORS.reset; - - let mut buf = [0u8; 2048]; - let mut cursor = Cursor::new(&mut buf[..]); - - write!( - cursor, - " + let system_info = format!(" {cyan} ▟█▖ {blue}▝█▙ ▗█▛ {user_info} ~{reset} {cyan} ▗▄▄▟██▄▄▄▄▄{blue}▝█▙█▛ {cyan}▖ {cyan} {blue}System{reset}  {os_name} {cyan} ▀▀▀▀▀▀▀▀▀▀▀▘{blue}▝██ {cyan}▟█▖ {cyan} {blue}Kernel{reset}  {kernel_version} {blue} ▟█▛ {blue}▝█▘{cyan}▟█▛ {cyan} {blue}Shell{reset}  {shell} {blue}▟█████▛ {cyan}▟█████▛ {cyan} {blue}Uptime{reset}  {uptime} {blue} ▟█▛{cyan}▗█▖ {cyan}▟█▛ {cyan} {blue}Desktop{reset}  {desktop} - {blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan}󰍛 {blue}Memory{reset}  {memory_usage} + {blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan} {blue}Memory{reset}  {memory_usage} {blue} ▝ {cyan}▟█▜█▖{blue}▀▀▀▀▀██▛▀▀▘ {cyan}󱥎 {blue}Storage (/){reset}  {storage} - {cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset}  {colors}\n\n" - )?; + {cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset}  {colors}\n"); - let len = cursor.position() as usize; - // Direct syscall to avoid stdout buffering allocation - let written = unsafe { libc::write(libc::STDOUT_FILENO, buf.as_ptr().cast(), len) }; - if written < 0 { - return Err(io::Error::last_os_error().into()); - } - if written as usize != len { - return Err(io::Error::new(io::ErrorKind::WriteZero, "partial write to stdout").into()); - } - Ok(()) + Ok(stdout().write_all(system_info.as_bytes())?) } diff --git a/src/system.rs b/src/system.rs index ba8fe79..24406ec 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,18 +1,11 @@ -use std::{ffi::CStr, fmt::Write as _, io, mem::MaybeUninit}; +use std::{env, fmt::Write as _, io, mem::MaybeUninit}; use crate::{UtsName, colors::COLORS, syscall::read_file_fast}; #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_username_and_hostname(utsname: &UtsName) -> String { - let username = unsafe { - let ptr = libc::getenv(c"USER".as_ptr()); - if ptr.is_null() { - "unknown_user" - } else { - CStr::from_ptr(ptr).to_str().unwrap_or("unknown_user") - } - }; + let username = env::var("USER").unwrap_or_else(|_| "unknown_user".to_owned()); let hostname = utsname.nodename().to_str().unwrap_or("unknown_host"); let capacity = COLORS.yellow.len() @@ -25,7 +18,7 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { let mut result = String::with_capacity(capacity); result.push_str(COLORS.yellow); - result.push_str(username); + result.push_str(&username); result.push_str(COLORS.red); result.push('@'); result.push_str(COLORS.green); @@ -38,17 +31,15 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_shell() -> String { - unsafe { - let ptr = libc::getenv(c"SHELL".as_ptr()); - if ptr.is_null() { - return "unknown_shell".into(); - } + let shell_path = + env::var("SHELL").unwrap_or_else(|_| "unknown_shell".to_owned()); - let bytes = CStr::from_ptr(ptr).to_bytes(); - let start = bytes.iter().rposition(|&b| b == b'/').map_or(0, |i| i + 1); - let name = std::str::from_utf8_unchecked(&bytes[start..]); - name.into() - } + // Find last '/' and get the part after it, avoiding allocation + shell_path + .rsplit('/') + .next() + .unwrap_or("unknown_shell") + .to_owned() } /// Gets the root disk usage information. @@ -115,7 +106,7 @@ pub fn get_memory_usage() -> Result { fn parse_memory_info() -> Result<(f64, f64), io::Error> { let mut total_memory_kb = 0u64; let mut available_memory_kb = 0u64; - let mut buffer = [0u8; 1024]; + let mut buffer = [0u8; 2048]; // Use fast syscall-based file reading let bytes_read = read_file_fast("/proc/meminfo", &mut buffer)?;