From a1e0f3be0b9a530ba4e13a843e4114af287be35f Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sat, 22 Mar 2025 21:06:50 -0700 Subject: [PATCH 1/5] hyper: refactor, update Rust, Hyper, and deps - Update Rust to 1.85.0 - Update hyper to 1.6.0 - Use socket2 instead of net2 - Bump other dependencies - Remove hyper-db test. This is now provided as a route in the main test. - Add a new test using tokio multi-thread runtime to compare with the single-thread runtime. This uses the same docker image, but passes a command line argument to the server to use the multi-thread runtime. - Add a healthcheck /ping url to the dockerfile to ensure that the server is running before running the tests. - Use deadpool-postgres for connection pooling. - Use cached prepared statements for the queries. - Factor each test into its own module. - Simplify the previous approach that used closures into more a more straightforward approach that uses linear functions. - Add single query and multiple query tests. --- frameworks/Rust/hyper/.dockerignore | 1 + frameworks/Rust/hyper/Cargo.lock | 1078 ++++++++++++----- frameworks/Rust/hyper/Cargo.toml | 55 +- frameworks/Rust/hyper/benchmark_config.json | 18 +- frameworks/Rust/hyper/hyper-db.dockerfile | 11 - frameworks/Rust/hyper/hyper.dockerfile | 15 +- frameworks/Rust/hyper/rustfmt.toml | 4 + frameworks/Rust/hyper/src/db.rs | 59 +- frameworks/Rust/hyper/src/fortunes.rs | 75 ++ frameworks/Rust/hyper/src/json.rs | 34 + frameworks/Rust/hyper/src/main.rs | 282 +++-- frameworks/Rust/hyper/src/main_db.rs | 109 -- frameworks/Rust/hyper/src/multiple_queries.rs | 59 + frameworks/Rust/hyper/src/plaintext.rs | 21 + frameworks/Rust/hyper/src/server.rs | 79 -- frameworks/Rust/hyper/src/single_query.rs | 50 + 16 files changed, 1290 insertions(+), 660 deletions(-) create mode 100644 frameworks/Rust/hyper/.dockerignore delete mode 100644 frameworks/Rust/hyper/hyper-db.dockerfile create mode 100644 frameworks/Rust/hyper/rustfmt.toml create mode 100644 frameworks/Rust/hyper/src/fortunes.rs create mode 100644 frameworks/Rust/hyper/src/json.rs delete mode 100644 frameworks/Rust/hyper/src/main_db.rs create mode 100644 frameworks/Rust/hyper/src/multiple_queries.rs create mode 100644 frameworks/Rust/hyper/src/plaintext.rs delete mode 100644 frameworks/Rust/hyper/src/server.rs create mode 100644 frameworks/Rust/hyper/src/single_query.rs diff --git a/frameworks/Rust/hyper/.dockerignore b/frameworks/Rust/hyper/.dockerignore new file mode 100644 index 00000000000..2f7896d1d13 --- /dev/null +++ b/frameworks/Rust/hyper/.dockerignore @@ -0,0 +1 @@ +target/ diff --git a/frameworks/Rust/hyper/Cargo.lock b/frameworks/Rust/hyper/Cargo.lock index a8cdf6d1bb0..7c1a5d6a4c6 100644 --- a/frameworks/Rust/hyper/Cargo.lock +++ b/frameworks/Rust/hyper/Cargo.lock @@ -1,89 +1,201 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys 0.59.0", +] [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ - "proc-macro2 1.0.51", - "quote 1.0.23", - "syn 1.0.108", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] [[package]] name = "base64" -version = "0.13.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] -name = "buf-min" -version = "0.1.1" +name = "bumpalo" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6ae7069aad07c7cdefe6a22a671f00650728bd2331a4cc62e1e5d0becdf9ca4" -dependencies = [ - "bytes 0.5.6", -] +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "0.5.6" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] -name = "bytes" -version = "1.4.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg-if" -version = "0.1.10" +name = "clap" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +dependencies = [ + "clap_builder", + "clap_derive", +] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "clap_builder" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -98,23 +210,73 @@ dependencies = [ "typenum", ] +[[package]] +name = "deadpool" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" +dependencies = [ + "deadpool-runtime", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-postgres" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" +dependencies = [ + "async-trait", + "deadpool", + "getrandom 0.2.15", + "tokio", + "tokio-postgres", + "tracing", +] + +[[package]] +name = "deadpool-runtime" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +dependencies = [ + "tokio", +] + [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", "subtle", ] +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "fnv" version = "1.0.7" @@ -123,9 +285,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -133,38 +295,38 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.51", - "quote 1.0.23", - "syn 1.0.108", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", @@ -177,34 +339,57 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check 0.9.4", + "version_check", ] [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] -name = "hermit-abi" -version = "0.2.6" +name = "getrandom" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ + "cfg-if", "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[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.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hmac" version = "0.12.1" @@ -216,47 +401,58 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes 1.4.0", + "bytes", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.4.0", + "bytes", "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.24" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "bytes 1.4.0", + "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -264,45 +460,97 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "smallvec", "tokio", - "tower-service", - "tracing", - "want", ] [[package]] name = "hyper-techempower" version = "0.5.0" dependencies = [ + "clap", + "deadpool-postgres", + "fastrand", + "http", + "http-body-util", "hyper", + "hyper-util", "log", "markup", - "net2", "num_cpus", "serde", "serde_json", + "socket2", + "strum", + "thiserror", "tokio", "tokio-postgres", + "tracing", + "tracing-subscriber", "v_htmlescape", ] +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -310,102 +558,112 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "markup" -version = "0.3.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360ec4d83ae8c3150530220fd89e0c5dba54cfc8d7675695f1fdc3581880dce9" +checksum = "74a887ad620fe1022257343ac77fcdd3720e92888e1b2e66e1b7a4707f453898" dependencies = [ "markup-proc-macro", ] [[package]] name = "markup-proc-macro" -version = "0.3.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba9c3711ed5187a843aaa960eb78db98f64d76ea22a47c204ca2affb3904bb92" +checksum = "9ab6ee21fd1855134cacf2f41afdf45f1bc456c7d7f6165d763b4647062dd2be" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "md-5" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if", "digest", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "mio" -version = "0.8.6" +name = "miniz_oxide" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.45.0", + "adler2", ] [[package]] -name = "net2" -version = "0.2.38" +name = "mio" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "cfg-if 0.1.10", "libc", - "winapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] -name = "nom" -version = "4.2.3" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "memchr", - "version_check 0.1.5", + "overload", + "winapi", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.1" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -413,46 +671,46 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -462,13 +720,13 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "postgres-protocol" -version = "0.6.4" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "878c6cbf956e03af9aa8204b407b9cbf47c072164800aa918c516cd4b056c50c" +checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" dependencies = [ "base64", "byteorder", - "bytes 1.4.0", + "bytes", "fallible-iterator", "hmac", "md-5", @@ -480,73 +738,64 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.4" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d946ec7d256b04dfadc4e6a3292324e6f417124750fc5c0950f981b703a0f1" +checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" dependencies = [ - "bytes 1.4.0", + "bytes", "fallible-iterator", "postgres-protocol", ] [[package]] name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "0.4.30" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "unicode-xid", + "zerocopy", ] [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "0.6.13" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ - "proc-macro2 0.4.30", + "proc-macro2", ] [[package]] -name = "quote" -version = "1.0.23" +name = "r-efi" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" -dependencies = [ - "proc-macro2 1.0.51", -] +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "libc", "rand_chacha", "rand_core", + "zerocopy", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -554,150 +803,243 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom", + "getrandom 0.3.2", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ "bitflags", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ - "proc-macro2 1.0.51", - "quote 1.0.23", - "syn 1.0.108", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "siphasher" -version = "0.3.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "stringprep" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] -name = "subtle" -version = "2.4.1" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "syn" -version = "0.15.44" +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid", + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" -version = "1.0.108" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ - "proc-macro2 1.0.51", - "quote 1.0.23", + "proc-macro2", + "quote", "unicode-ident", ] +[[package]] +name = "terminal_size" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +dependencies = [ + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[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", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -710,29 +1052,28 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.25.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ - "autocfg", - "bytes 1.4.0", + "backtrace", + "bytes", "libc", - "memchr", "mio", "pin-project-lite", "socket2", - "windows-sys 0.42.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-postgres" -version = "0.7.7" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a12c1b3e0704ae7dfc25562629798b29c72e6b1d0a681b6f29ab4ae5e7f7bf" +checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" dependencies = [ "async-trait", "byteorder", - "bytes 1.4.0", + "bytes", "fallible-iterator", "futures-channel", "futures-util", @@ -743,149 +1084,244 @@ dependencies = [ "pin-project-lite", "postgres-protocol", "postgres-types", + "rand", "socket2", "tokio", "tokio-util", + "whoami", ] [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ - "bytes 1.4.0", + "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", ] [[package]] -name = "try-lock" -version = "0.2.4" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] [[package]] name = "typenum" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] -name = "unicode-xid" +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "v_htmlescape" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasite" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] -name = "v_escape" -version = "0.13.2" +name = "wasm-bindgen" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039a44473286eb84e4e74f90165feff67c802dbeced7ee4c5b00d719b0d0475e" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "buf-min", - "v_escape_derive", + "cfg-if", + "once_cell", + "wasm-bindgen-macro", ] [[package]] -name = "v_escape_derive" -version = "0.8.5" +name = "wasm-bindgen-backend" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29769400af8b264944b851c961a4a6930e76604f59b1fcd51246bab6a296c8c" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ - "nom", - "proc-macro2 1.0.51", - "quote 1.0.23", - "syn 1.0.108", + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "v_htmlescape" -version = "0.10.4" +name = "wasm-bindgen-macro" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7c2a33ed7cf0dc1b42bcf39e01b6512f9df08f09e1cd8a49d9dc49a6a9482" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ - "cfg-if 1.0.0", - "v_escape", + "quote", + "wasm-bindgen-macro-support", ] [[package]] -name = "version_check" -version = "0.1.5" +name = "wasm-bindgen-macro-support" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] [[package]] -name = "version_check" -version = "0.9.4" +name = "wasm-bindgen-shared" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] -name = "want" -version = "0.3.0" +name = "web-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ - "log", - "try-lock", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "whoami" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] [[package]] name = "winapi" @@ -911,37 +1347,32 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 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", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -950,42 +1381,77 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/frameworks/Rust/hyper/Cargo.toml b/frameworks/Rust/hyper/Cargo.toml index 2d3819863d7..b94bb0cbbae 100644 --- a/frameworks/Rust/hyper/Cargo.toml +++ b/frameworks/Rust/hyper/Cargo.toml @@ -5,30 +5,47 @@ edition = "2018" authors = [ "Steve Klabnik ", "Alexander Polyakov ", - "Sean McArthur " + "Sean McArthur ", ] -[[bin]] -name = "hyper-techempower" -path = "src/main.rs" - -[[bin]] -name = "hyper-db-techempower" -path = "src/main_db.rs" - [dependencies] +clap = { version = "4.5.32", features = ["derive", "wrap_help"] } +deadpool-postgres = "0.14.1" +fastrand = "2.3.0" +http = "1.3.1" +http-body-util = "0.1.3" # Disable default runtime, so that tokio single thread can be used instead. -hyper = { version = "0.14", features = ["server", "http1"], default-features = false } +hyper = { version = "1.6.0", features = [ + "server", + "http1", +], default-features = false } +hyper-util = { version = "0.1.10", features = [ + "http1", + "server", + "service", + "tokio", +] } # Since no logs are allowed anyways, just compile-time turn them all off -log = { version = "0.4", features = ["release_max_level_off"] } -markup = "0.3.1" -net2 = "0.2" -num_cpus = "1.2" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -tokio = { version = "1", features = ["rt", "net", "time"] } -tokio-postgres = { version = "0.7", default-features = false, features = ["runtime"] } -v_htmlescape = "0.10" +log = { version = "0.4.26", features = ["release_max_level_off"] } +markup = "0.15.0" +num_cpus = "1.16.0" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +socket2 = { version = "0.5.8", features = ["all"] } +strum = { version = "0.27.1", features = ["derive"] } +thiserror = "2.0.12" +tokio = { version = "1.44.1", features = [ + "rt", + "rt-multi-thread", + "net", + "time", +] } +tokio-postgres = { version = "0.7.13", default-features = false, features = [ + "runtime", +] } +tracing = "0.1.41" +tracing-subscriber = "0.3.19" +v_htmlescape = "0.15.8" [profile.release] opt-level = 3 diff --git a/frameworks/Rust/hyper/benchmark_config.json b/frameworks/Rust/hyper/benchmark_config.json index 4dab46b0554..62ea21b4347 100644 --- a/frameworks/Rust/hyper/benchmark_config.json +++ b/frameworks/Rust/hyper/benchmark_config.json @@ -2,8 +2,12 @@ "framework": "hyper", "tests": [{ "default": { - "plaintext_url": "/plaintext", + "docker_cmd": "hyper-techempower --runtime current-thread", "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?count=", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Micro", @@ -15,10 +19,16 @@ "webserver": "hyper", "os": "Linux", "database_os": "Linux", - "display_name": "hyper", + "display_name": "Hyper (current-thread runtime)", "notes": "" }, - "db": { + "multi-thread": { + "dockerfile": "hyper.dockerfile", + "docker_cmd": "hyper-techempower --runtime multi-thread", + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?count=", "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", @@ -31,7 +41,7 @@ "webserver": "hyper", "os": "Linux", "database_os": "Linux", - "display_name": "hyper", + "display_name": "Hyper (multi-thread runtime)", "notes": "" } }] diff --git a/frameworks/Rust/hyper/hyper-db.dockerfile b/frameworks/Rust/hyper/hyper-db.dockerfile deleted file mode 100644 index 8930ea7c28e..00000000000 --- a/frameworks/Rust/hyper/hyper-db.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM rust:1.67 - -ADD ./ /hyper -WORKDIR /hyper - -RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release - -EXPOSE 8080 - -CMD ["./target/release/hyper-db-techempower"] diff --git a/frameworks/Rust/hyper/hyper.dockerfile b/frameworks/Rust/hyper/hyper.dockerfile index e273f5c95c4..b2f6b8cb6b3 100644 --- a/frameworks/Rust/hyper/hyper.dockerfile +++ b/frameworks/Rust/hyper/hyper.dockerfile @@ -1,11 +1,8 @@ -FROM rust:1.67 - -ADD ./ /hyper -WORKDIR /hyper - -RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release +FROM rust:1.85 AS hyper +WORKDIR /src +COPY . . +RUN RUSTFLAGS="-C target-cpu=native" cargo install --path . --locked EXPOSE 8080 - -CMD ["./target/release/hyper-techempower"] +CMD ["hyper-techempower"] +HEALTHCHECK CMD curl --fail http://localhost:8080/ping || exit 1 \ No newline at end of file diff --git a/frameworks/Rust/hyper/rustfmt.toml b/frameworks/Rust/hyper/rustfmt.toml new file mode 100644 index 00000000000..e37b2bf4664 --- /dev/null +++ b/frameworks/Rust/hyper/rustfmt.toml @@ -0,0 +1,4 @@ +# unstable_features +comment_width = 100 +group_imports = "StdExternalCrate" +imports_granularity = "Module" diff --git a/frameworks/Rust/hyper/src/db.rs b/frameworks/Rust/hyper/src/db.rs index d72de86f798..b6cb246af04 100644 --- a/frameworks/Rust/hyper/src/db.rs +++ b/frameworks/Rust/hyper/src/db.rs @@ -1,46 +1,21 @@ -use std::net::SocketAddr; +use std::sync::LazyLock; -use tokio::net::TcpStream; -use tokio::runtime::Handle; -use tokio_postgres::{Client, Config, NoTls, Statement}; +use deadpool_postgres::{Config, CreatePoolError, Pool}; +use tokio_postgres::NoTls; +use tracing::info; -pub struct Db { - client: Client, - fortune: Statement, -} - -pub struct Fortune { - pub id: i32, - pub message: String, -} - -pub async fn connect( - addr: SocketAddr, - config: Config, - handle: Handle, -) -> Result> { - let stream = TcpStream::connect(&addr).await?; - let (client, conn) = config.connect_raw(stream, NoTls).await?; - handle.spawn(conn); - let fortune = client.prepare("SELECT id, message FROM fortune").await?; - Ok(Db { client, fortune }) -} - -impl Db { - pub async fn tell_fortune(&self) -> Result, tokio_postgres::Error> { - let mut items = vec![Fortune { - id: 0, - message: "Additional fortune added at request time.".to_string(), - }]; +pub static POOL: LazyLock = + LazyLock::new(|| connect().expect("failed to create database connection pool")); - let rows = self.client.query(&self.fortune, &[]).await?; - for row in rows { - items.push(Fortune { - id: row.get(0), - message: row.get(1), - }); - } - items.sort_by(|it, next| it.message.cmp(&next.message)); - Ok(items) - } +fn connect() -> Result { + info!("Creating database connection pool"); + let config = Config { + host: Some("tfb-database".to_string()), + port: Some(5432), + dbname: Some("hello_world".to_string()), + user: Some("benchmarkdbuser".to_string()), + password: Some("benchmarkdbpass".to_string()), + ..Default::default() + }; + config.create_pool(None, NoTls) } diff --git a/frameworks/Rust/hyper/src/fortunes.rs b/frameworks/Rust/hyper/src/fortunes.rs new file mode 100644 index 00000000000..0cdbd2f3ccf --- /dev/null +++ b/frameworks/Rust/hyper/src/fortunes.rs @@ -0,0 +1,75 @@ +use std::convert::Infallible; + +use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use http::Response; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; +use tokio_postgres::Row; + +use crate::db::POOL; +use crate::{Error, SERVER_HEADER, TEXT_HTML}; + +const QUERY: &str = "SELECT id, message FROM fortune"; + +pub struct Fortune { + pub id: i32, + pub message: String, +} + +impl From<&Row> for Fortune { + fn from(row: &Row) -> Self { + Self { + id: row.get(0), + message: row.get(1), + } + } +} + +pub async fn get() -> crate::Result>> { + let fortunes = tell_fortune().await?; + let content = FortunesTemplate { fortunes }.to_string(); + Response::builder() + .header(SERVER, SERVER_HEADER.clone()) + .header(CONTENT_TYPE, TEXT_HTML.clone()) + .header(CONTENT_LENGTH, content.len()) + .body(Full::from(content).boxed()) + .map_err(Error::from) +} + +async fn tell_fortune() -> crate::Result> { + let db = POOL.get().await?; + let statement = db.prepare_cached(QUERY).await?; + let rows = db.query(&statement, &[]).await?; + let mut fortunes = rows.iter().map(Fortune::from).collect::>(); + + fortunes.push(Fortune { + id: 0, + message: "Additional fortune added at request time.".to_string(), + }); + fortunes.sort_by(|a, b| a.message.cmp(&b.message)); + + Ok(fortunes) +} + +markup::define! { + FortunesTemplate(fortunes: Vec) { + {markup::doctype()} + html { + head { + title { "Fortunes" } + } + body { + table { + tr { th { "id" } th { "message" } } + @for item in fortunes { + tr { + td { {item.id} } + td { {markup::raw(v_htmlescape::escape(&item.message))} } + } + } + } + } + } + } +} diff --git a/frameworks/Rust/hyper/src/json.rs b/frameworks/Rust/hyper/src/json.rs new file mode 100644 index 00000000000..9b6747a40a0 --- /dev/null +++ b/frameworks/Rust/hyper/src/json.rs @@ -0,0 +1,34 @@ +use std::convert::Infallible; + +use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use http::{HeaderValue, Response}; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; +use serde::Serialize; + +use crate::{Error, Result, APPLICATION_JSON, SERVER_HEADER}; + +#[derive(Serialize)] +struct JsonResponse<'a> { + message: &'a str, +} + +static CONTENT: JsonResponse = JsonResponse { + message: "Hello, world!", +}; + +/// The `Content-Length` header value for the JSON response. +/// +/// This is a static value because the length of the JSON response is known at compile time. +static CONTENT_LENGTH_HEADER: HeaderValue = HeaderValue::from_static("27"); + +pub fn get() -> Result>> { + let content = serde_json::to_vec(&CONTENT)?; + Response::builder() + .header(SERVER, SERVER_HEADER.clone()) + .header(CONTENT_TYPE, APPLICATION_JSON.clone()) + .header(CONTENT_LENGTH, CONTENT_LENGTH_HEADER.clone()) + .body(Full::from(content).boxed()) + .map_err(Error::from) +} diff --git a/frameworks/Rust/hyper/src/main.rs b/frameworks/Rust/hyper/src/main.rs index 663ed87afc0..0828ff87152 100644 --- a/frameworks/Rust/hyper/src/main.rs +++ b/frameworks/Rust/hyper/src/main.rs @@ -1,91 +1,211 @@ -use hyper::header::{HeaderValue, CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use std::convert::Infallible; +use std::net::{Ipv4Addr, SocketAddr}; +use std::{io, thread}; + +use clap::{Parser, ValueEnum}; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Empty, Full}; +use hyper::body::{Bytes, Incoming}; +use hyper::header::{HeaderValue, SERVER}; +use hyper::server::conn::http1; use hyper::service::service_fn; -use hyper::{Body, Response, StatusCode}; -use serde::Serialize; +use hyper::{Request, Response, StatusCode}; +use hyper_util::rt::TokioIo; +use socket2::{Domain, SockAddr, Socket}; +use strum::Display; +use thiserror::Error; +use tokio::net::TcpListener; +use tokio::runtime; +use tracing::{error, info}; + +mod db; +mod fortunes; +mod json; +mod multiple_queries; +mod plaintext; +mod single_query; + +static SERVER_HEADER: HeaderValue = HeaderValue::from_static("hyper"); +static APPLICATION_JSON: HeaderValue = HeaderValue::from_static("application/json"); +static TEXT_HTML: HeaderValue = HeaderValue::from_static("text/html; charset=utf-8"); +static TEXT_PLAIN: HeaderValue = HeaderValue::from_static("text/plain"); + +type Result = std::result::Result; + +#[derive(Debug, Error)] +enum Error { + #[error("I/O error: {0}")] + Io(#[from] io::Error), + #[error("Hyper error: {0}")] + Hyper(#[from] hyper::Error), + #[error("Database error: {0}")] + TokioPostgres(#[from] tokio_postgres::Error), + #[error("Http error: {0}")] + Http(#[from] http::Error), + #[error("Database pool error: {0}")] + DbPool(#[from] deadpool_postgres::PoolError), + #[error("Serde error: {0}")] + Serde(#[from] serde_json::Error), +} + +#[derive(Debug, Parser)] +struct Args { + /// The runtime to use. + #[arg(short, long, default_value_t = Runtime::default())] + runtime: Runtime, + + /// The number of threads to use. + /// + /// Defaults to the number of logical CPUs cores available on the system. + /// + /// - For the current thread runtime, this is the number of threads to spawn in addition to the + /// main thread. + /// - For the multi-thread runtime, this is the number of worker threads to configure the + /// runtime to use. + #[arg(short, long, default_value_t = num_cpus::get())] + threads: usize, +} + +#[derive(Clone, Debug, Default, Display, ValueEnum)] +#[strum(serialize_all = "kebab-case")] +enum Runtime { + #[default] + CurrentThread, + MultiThread, +} + +fn main() -> Result<()> { + // Note: this is only here to capture logs outside of the hot path code. Avoid logging messages + // in the hot path code. + tracing_subscriber::fmt().with_thread_ids(true).init(); -mod server; + let args = Args::parse(); + match args.runtime { + Runtime::CurrentThread => run_current_thread(args.threads)?, + Runtime::MultiThread => run_multi_thread(args.threads)?, + } -static HELLO_WORLD: &[u8] = b"Hello, world!"; + Ok(()) +} + +/// Runs the server using multiple current thread runtimes. +fn run_current_thread(threads: usize) -> Result<()> { + info!("Running with {} threads", threads); + + // Spawn a new runtime on each thread. + for _ in 1..threads { + let runtime = runtime::Builder::new_current_thread() + .enable_all() + .build()?; + thread::spawn(|| run_server(runtime)); + } + // Run the server on the main thread. + let runtime = runtime::Builder::new_current_thread() + .enable_all() + .build()?; + run_server(runtime) +} -#[derive(Serialize)] -struct JsonResponse<'a> { - message: &'a str, +/// Runs the server using a single multi-thread runtime. +fn run_multi_thread(threads: usize) -> Result<()> { + let runtime = runtime::Builder::new_multi_thread() + .enable_all() + .worker_threads(threads) + .build()?; + run_server(runtime) } -fn main() { - // It seems most of the other benchmarks create static header values - // for performance, so just play by the same rules here... - let plaintext_len = HeaderValue::from_static("13"); - let plaintext_ct = HeaderValue::from_static("text/plain"); - let json_len = HeaderValue::from_static("27"); - let json_ct = HeaderValue::from_static("application/json"); - let server_header = HeaderValue::from_static("hyper"); - - server::run(move |socket, http, handle| { - // This closure is run for each connection... - - // The plaintext benchmarks use pipelined requests. - http.pipeline_flush(true); - - // Gotta clone these to be able to move into the Service... - let plaintext_len = plaintext_len.clone(); - let plaintext_ct = plaintext_ct.clone(); - let json_len = json_len.clone(); - let json_ct = json_ct.clone(); - let server_header = server_header.clone(); - - // This is the `Service` that will handle the connection. - // `service_fn_ok` is a helper to convert a function that - // returns a Response into a `Service`. - let svc = service_fn(move |req| { - // Gotta clone these to be able to move into future... - let plaintext_len = plaintext_len.clone(); - let plaintext_ct = plaintext_ct.clone(); - let json_len = json_len.clone(); - let json_ct = json_ct.clone(); - let server_header = server_header.clone(); - - async move { - let (req, _body) = req.into_parts(); - // For speed, reuse the allocated header map from the request, - // instead of allocating a new one. Because. - let mut headers = req.headers; - headers.clear(); - - let body = match req.uri.path() { - // Apparently, other benchmarks don't check the method, so we - // don't either. Yay? - "/plaintext" => { - headers.insert(CONTENT_LENGTH, plaintext_len.clone()); - headers.insert(CONTENT_TYPE, plaintext_ct.clone()); - Body::from(HELLO_WORLD) - } - "/json" => { - let rep = JsonResponse { - message: "Hello, world!", - }; - let rep_body = serde_json::to_vec(&rep).unwrap(); - headers.insert(CONTENT_LENGTH, json_len.clone()); - headers.insert(CONTENT_TYPE, json_ct.clone()); - Body::from(rep_body) - } - _ => { - let mut res = Response::new(Body::empty()); - *res.status_mut() = StatusCode::NOT_FOUND; - *res.headers_mut() = headers; - return Ok::<_, std::io::Error>(res); - } - }; - - headers.insert(SERVER, server_header.clone()); - - let mut res = Response::new(body); - *res.headers_mut() = headers; - Ok(res) +fn run_server(runtime: runtime::Runtime) -> Result<()> { + // It's important to use [`Runtime::block_on()`] here and not [`handle::block_on()`] as + // otherwise the runtime will not drive I/O operations. See the [`Handle::block_on`] + // documentation for more information. + runtime.block_on(serve(runtime.handle())) +} + +async fn serve(handle: &runtime::Handle) -> Result<()> { + let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8080)); + let socket = create_socket(addr)?; + + let listener = TcpListener::from_std(socket.into())?; + let addr = listener.local_addr()?; + info!("Listening on: {}", addr); + + // spawn accept loop into a task so it is scheduled on the runtime with all the other tasks. + let accept_loop = accept_loop(handle.clone(), listener); + handle.spawn(accept_loop).await.unwrap() +} + +/// Create a socket that allows reuse of the address and port. +/// +/// This makes it possible for multiple instances of the server task to bind to the same address and +/// port. +fn create_socket(addr: SocketAddr) -> Result { + let domain = match addr { + SocketAddr::V4(_) => Domain::IPV4, + SocketAddr::V6(_) => Domain::IPV6, + }; + let addr = SockAddr::from(addr); + let socket = Socket::new(domain, socket2::Type::STREAM, None)?; + let backlog = 4096; // maximum number of pending connections + #[cfg(unix)] + socket.set_reuse_port(true)?; + socket.set_reuse_address(true)?; + socket.set_nonblocking(true)?; // required for tokio + socket.bind(&addr)?; + socket.listen(backlog)?; + + Ok(socket) +} + +/// Accept loop that accepts incoming connections and spawns a new task to handle each connection. +async fn accept_loop(handle: runtime::Handle, listener: TcpListener) -> Result<()> { + let mut http = http1::Builder::new(); + http.pipeline_flush(true); + + let service = service_fn(router); + loop { + let (stream, _) = listener.accept().await?; + let http = http.clone(); + handle.spawn(async move { + let io = TokioIo::new(stream); + if let Err(_e) = http.serve_connection(io, service).await { + // ignore errors until https://github.com/hyperium/hyper/pull/3863/ is merged + // This PR will allow us to filter out shutdown errors which are expected. + // warn!("Connection error (this may be normal during shutdown): {e}"); } }); + } +} + +/// Routes requests to the appropriate handler. +async fn router(request: Request) -> Result>> { + // The method is always GET, so we don't check it. + match request.uri().path() { + "/ping" => ping(), + "/json" => json::get(), + "/db" => single_query::get().await, + "/queries" => multiple_queries::get(request.uri().query()).await, + "/fortunes" => fortunes::get().await, + "/plaintext" => plaintext::get(), + _ => not_found_error(), + } +} + +/// A handler that returns a "pong" response. +/// +/// This handler is used to verify that the server is running and can respond to requests. It is +/// used by the docker health check command. +fn ping() -> Result>> { + Response::builder() + .body(Full::from("pong").boxed()) + .map_err(Error::from) +} - // Spawn the `serve_connection` future into the runtime. - handle.spawn(http.serve_connection(socket, svc)); - }) +/// A handler that returns a 404 response. +fn not_found_error() -> Result>> { + Response::builder() + .status(StatusCode::NOT_FOUND) + .header(SERVER, SERVER_HEADER.clone()) + .body(Empty::new().boxed()) + .map_err(Error::from) } diff --git a/frameworks/Rust/hyper/src/main_db.rs b/frameworks/Rust/hyper/src/main_db.rs deleted file mode 100644 index 1ac93cd6b31..00000000000 --- a/frameworks/Rust/hyper/src/main_db.rs +++ /dev/null @@ -1,109 +0,0 @@ -use std::fmt::Write; -use std::sync::Arc; - -use hyper::header::{HeaderValue, CONTENT_TYPE, SERVER}; -use hyper::service::service_fn; -use hyper::{Body, Response}; -use std::net::ToSocketAddrs; - -mod db; -mod server; - -fn main() { - //"postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; - let mut psql_config = tokio_postgres::Config::new(); - psql_config - .user("benchmarkdbuser") - .password("benchmarkdbpass") - .dbname("hello_world"); - let psql_addr = ("tfb-database", 5432) - .to_socket_addrs() - .expect("must be able to resolve database hostname") - .next() - .expect("database hostname must resolve to an address"); - - server::run(move |socket, http, handle| { - let http = http.clone(); - let handle2 = handle.clone(); - - let html_ct = HeaderValue::from_static("text/html; charset=utf-8"); - let server_header = HeaderValue::from_static("hyper"); - let config = psql_config.clone(); - - // Before handling any requests, we should grab a DB connection. - let db_fut = async move { - let handle = handle2.clone(); - let db_conn = db::connect(psql_addr, config, handle).await?; - let db_conn = Arc::new(db_conn); - - let html_ct = html_ct.clone(); - let server_header = server_header.clone(); - - // This is the `Service` that will handle the connection. - // `service_fn` is a helper to convert a function that - // returns a Future into a `Service`. - let svc = service_fn(move |req| { - let html_ct = html_ct.clone(); - let server_header = server_header.clone(); - let db_conn = db_conn.clone(); - - async move { - let (req, _body) = req.into_parts(); - // For speed, reuse the allocated header map from the request, - // instead of allocating a new one. Because. - let mut headers = req.headers; - headers.clear(); - - headers.insert(CONTENT_TYPE, html_ct.clone()); - headers.insert(SERVER, server_header.clone()); - - match req.uri.path() { - "/fortunes" => { - let fortunes = db_conn.tell_fortune().await?; - let mut buf = String::with_capacity(2048); - let _ = write!(&mut buf, "{}", FortunesTemplate { fortunes }); - let mut res = Response::new(Body::from(buf)); - *res.headers_mut() = headers; - Ok::<_, Box>(res) - } - _ => { - let mut res = Response::new(Body::empty()); - *res.status_mut() = hyper::StatusCode::NOT_FOUND; - *res.headers_mut() = headers; - Ok(res) - } - } - } - }); - // Spawn the `serve_connection` future into the runtime. - handle2.spawn(http.serve_connection(socket, svc)); - Ok::<_, Box>(()) - }; - - handle.spawn(async move { - let _ = db_fut.await; - }); - }); -} - -markup::define! { - FortunesTemplate(fortunes: Vec) { - {markup::doctype()} - html { - head { - title { "Fortunes" } - } - body { - table { - tr { th { "id" } th { "message" } } - @for item in {fortunes} { - tr { - td { {item.id} } - td { {markup::raw(v_htmlescape::escape(&item.message))} } - } - } - } - } - } - } -} diff --git a/frameworks/Rust/hyper/src/multiple_queries.rs b/frameworks/Rust/hyper/src/multiple_queries.rs new file mode 100644 index 00000000000..f9aa862acad --- /dev/null +++ b/frameworks/Rust/hyper/src/multiple_queries.rs @@ -0,0 +1,59 @@ +use std::convert::Infallible; + +use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use http::Response; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; +use serde::Serialize; +use tokio_postgres::Row; + +use crate::db::POOL; +use crate::{Error, Result, APPLICATION_JSON, SERVER_HEADER}; + +const QUERY: &str = "SELECT id, randomnumber FROM world WHERE id = $1"; + +#[derive(Debug, Serialize)] +pub struct World { + id: i32, + randomnumber: i32, +} + +impl From for World { + fn from(row: Row) -> Self { + World { + id: row.get(0), + randomnumber: row.get(1), + } + } +} + +pub async fn get(query: Option<&str>) -> Result>> { + let count = query + .and_then(|query| query.strip_prefix("count=")) + .and_then(|query| query.parse().ok()) + .unwrap_or(1) + .clamp(1, 500); + + let worlds = query_worlds(count).await?; + let json = serde_json::to_vec(&worlds)?; + + Response::builder() + .header(SERVER, SERVER_HEADER.clone()) + .header(CONTENT_TYPE, APPLICATION_JSON.clone()) + .header(CONTENT_LENGTH, json.len()) + .body(Full::from(json).boxed()) + .map_err(Error::from) +} + +async fn query_worlds(count: usize) -> Result> { + let db = POOL.get().await?; + let statement = db.prepare_cached(QUERY).await?; + let mut worlds = Vec::with_capacity(count); + for _ in 0..count { + let id = fastrand::i32(1..10_000); + let row = db.query_one(&statement, &[&id]).await?; + worlds.push(World::from(row)); + } + Ok(worlds) +} diff --git a/frameworks/Rust/hyper/src/plaintext.rs b/frameworks/Rust/hyper/src/plaintext.rs new file mode 100644 index 00000000000..5ab352edcbe --- /dev/null +++ b/frameworks/Rust/hyper/src/plaintext.rs @@ -0,0 +1,21 @@ +use std::convert::Infallible; + +use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use http::{HeaderValue, Response}; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; + +use crate::{Error, Result, SERVER_HEADER, TEXT_PLAIN}; + +static CONTENT: &[u8] = b"Hello, world!"; +static CONTENT_LENGTH_HEADER: HeaderValue = HeaderValue::from_static("13"); + +pub fn get() -> Result>> { + Response::builder() + .header(SERVER, SERVER_HEADER.clone()) + .header(CONTENT_TYPE, TEXT_PLAIN.clone()) + .header(CONTENT_LENGTH, CONTENT_LENGTH_HEADER.clone()) + .body(Full::from(CONTENT).boxed()) + .map_err(Error::from) +} diff --git a/frameworks/Rust/hyper/src/server.rs b/frameworks/Rust/hyper/src/server.rs deleted file mode 100644 index 32ae0c8cc75..00000000000 --- a/frameworks/Rust/hyper/src/server.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::io; -use std::net::SocketAddr; -use std::thread; - -use hyper::server::conn::Http; -use tokio::net::{TcpListener, TcpStream}; -use tokio::runtime::{Builder as RuntimeBuilder, Handle}; - -pub(crate) fn run(per_connection: F) -where - F: Fn(TcpStream, &mut Http, Handle) + Clone + Send + 'static, -{ - // Spawn a thread for each available core, minus one, since we'll - // reuse the main thread as a server thread as well. - for _ in 1..num_cpus::get() { - let per_connection = per_connection.clone(); - thread::spawn(move || { - server_thread(per_connection); - }); - } - server_thread(per_connection); -} - -fn server_thread(per_connection: F) -where - F: Fn(TcpStream, &mut Http, Handle) + Send + 'static, -{ - let mut http = Http::new(); - http.http1_only(true); - - // Our event loop... - let core = RuntimeBuilder::new_current_thread() - .enable_all() - .build() - .expect("runtime"); - let handle = core.handle(); - - // Bind to 0.0.0.0:8080 - let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); - - // For every accepted connection, spawn an HTTP task - let server = async move { - let tcp = reuse_listener(&addr).expect("couldn't bind to addr"); - loop { - match tcp.accept().await { - Ok((sock, _)) => { - let _ = sock.set_nodelay(true); - per_connection(sock, &mut http, handle.clone()); - } - Err(e) => { - log::warn!("accept error: {}", e) - } - } - } - }; - - core.block_on(server); -} - -fn reuse_listener(addr: &SocketAddr) -> io::Result { - let builder = match *addr { - SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?, - SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?, - }; - - #[cfg(unix)] - { - use net2::unix::UnixTcpBuilderExt; - if let Err(e) = builder.reuse_port(true) { - eprintln!("error setting SO_REUSEPORT: {}", e); - } - } - - builder.reuse_address(true)?; - builder.bind(addr)?; - let listener = builder.listen(1024)?; - listener.set_nonblocking(true)?; - TcpListener::from_std(listener) -} diff --git a/frameworks/Rust/hyper/src/single_query.rs b/frameworks/Rust/hyper/src/single_query.rs new file mode 100644 index 00000000000..62083dd4d3a --- /dev/null +++ b/frameworks/Rust/hyper/src/single_query.rs @@ -0,0 +1,50 @@ +use std::convert::Infallible; + +use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; +use http::Response; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; +use serde::Serialize; +use tokio_postgres::Row; + +use crate::db::POOL; +use crate::{Error, Result, APPLICATION_JSON, SERVER_HEADER}; + +static QUERY: &str = "SELECT id, randomnumber FROM world WHERE id = $1"; + +#[derive(Debug, Serialize)] +pub struct World { + id: i32, + randomnumber: i32, +} + +impl From for World { + fn from(row: Row) -> Self { + World { + id: row.get(0), + randomnumber: row.get(1), + } + } +} + +pub async fn get() -> Result>> { + let id = fastrand::i32(1..10_000); + let world = query_world(id).await?; + let json = serde_json::to_vec(&world)?; + + Response::builder() + .header(SERVER, SERVER_HEADER.clone()) + .header(CONTENT_TYPE, APPLICATION_JSON.clone()) + .header(CONTENT_LENGTH, json.len()) + .body(Full::from(json).boxed()) + .map_err(Error::from) +} + +async fn query_world(id: i32) -> Result { + let db = POOL.get().await?; + let statement = db.prepare_cached(QUERY).await?; + let row = db.query_one(&statement, &[&id]).await?; + let world = World::from(row); + Ok(world) +} From c6920475e3f5fa74d1fbb5a7cbbf4d95a03f8c42 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sun, 23 Mar 2025 16:09:51 -0700 Subject: [PATCH 2/5] hyper: add maintainers --- frameworks/Rust/hyper/benchmark_config.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frameworks/Rust/hyper/benchmark_config.json b/frameworks/Rust/hyper/benchmark_config.json index 62ea21b4347..f9f7ef8f673 100644 --- a/frameworks/Rust/hyper/benchmark_config.json +++ b/frameworks/Rust/hyper/benchmark_config.json @@ -1,5 +1,10 @@ { "framework": "hyper", + "maintainers": [ + "polachok", + "seanmonstar", + "steveklabnik" + ], "tests": [{ "default": { "docker_cmd": "hyper-techempower --runtime current-thread", From a363c3b030ec8677059660c3509de559b566c810 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sun, 23 Mar 2025 21:21:46 -0700 Subject: [PATCH 3/5] fix: don't pre-compute json content-length --- frameworks/Rust/hyper/src/json.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/frameworks/Rust/hyper/src/json.rs b/frameworks/Rust/hyper/src/json.rs index 9b6747a40a0..c80ad50c09a 100644 --- a/frameworks/Rust/hyper/src/json.rs +++ b/frameworks/Rust/hyper/src/json.rs @@ -1,7 +1,7 @@ use std::convert::Infallible; use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; -use http::{HeaderValue, Response}; +use http::Response; use http_body_util::combinators::BoxBody; use http_body_util::{BodyExt, Full}; use hyper::body::Bytes; @@ -18,17 +18,12 @@ static CONTENT: JsonResponse = JsonResponse { message: "Hello, world!", }; -/// The `Content-Length` header value for the JSON response. -/// -/// This is a static value because the length of the JSON response is known at compile time. -static CONTENT_LENGTH_HEADER: HeaderValue = HeaderValue::from_static("27"); - pub fn get() -> Result>> { let content = serde_json::to_vec(&CONTENT)?; Response::builder() .header(SERVER, SERVER_HEADER.clone()) .header(CONTENT_TYPE, APPLICATION_JSON.clone()) - .header(CONTENT_LENGTH, CONTENT_LENGTH_HEADER.clone()) + .header(CONTENT_LENGTH, content.len()) .body(Full::from(content).boxed()) .map_err(Error::from) } From 232989df53d1c9cde63c042482bec25a28e6634d Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sun, 23 Mar 2025 21:22:44 -0700 Subject: [PATCH 4/5] fix: add back socket.set_nodelay(true) --- frameworks/Rust/hyper/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frameworks/Rust/hyper/src/main.rs b/frameworks/Rust/hyper/src/main.rs index 0828ff87152..81b79374172 100644 --- a/frameworks/Rust/hyper/src/main.rs +++ b/frameworks/Rust/hyper/src/main.rs @@ -150,6 +150,7 @@ fn create_socket(addr: SocketAddr) -> Result { #[cfg(unix)] socket.set_reuse_port(true)?; socket.set_reuse_address(true)?; + socket.set_nodelay(true)?; socket.set_nonblocking(true)?; // required for tokio socket.bind(&addr)?; socket.listen(backlog)?; From 1325b3a58fdd3c5b51fb57889ad45c5ecc2a02f8 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sun, 23 Mar 2025 21:23:42 -0700 Subject: [PATCH 5/5] fix: don't precompute plaintext content-length header --- frameworks/Rust/hyper/src/plaintext.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frameworks/Rust/hyper/src/plaintext.rs b/frameworks/Rust/hyper/src/plaintext.rs index 5ab352edcbe..e2a081d2d39 100644 --- a/frameworks/Rust/hyper/src/plaintext.rs +++ b/frameworks/Rust/hyper/src/plaintext.rs @@ -1,7 +1,7 @@ use std::convert::Infallible; use http::header::{CONTENT_LENGTH, CONTENT_TYPE, SERVER}; -use http::{HeaderValue, Response}; +use http::Response; use http_body_util::combinators::BoxBody; use http_body_util::{BodyExt, Full}; use hyper::body::Bytes; @@ -9,13 +9,12 @@ use hyper::body::Bytes; use crate::{Error, Result, SERVER_HEADER, TEXT_PLAIN}; static CONTENT: &[u8] = b"Hello, world!"; -static CONTENT_LENGTH_HEADER: HeaderValue = HeaderValue::from_static("13"); pub fn get() -> Result>> { Response::builder() .header(SERVER, SERVER_HEADER.clone()) .header(CONTENT_TYPE, TEXT_PLAIN.clone()) - .header(CONTENT_LENGTH, CONTENT_LENGTH_HEADER.clone()) + .header(CONTENT_LENGTH, CONTENT.len()) .body(Full::from(CONTENT).boxed()) .map_err(Error::from) }