From fb591d95e82783a1a5550d4691f4a2f21974e3d4 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Sat, 21 Sep 2024 19:10:40 +0800 Subject: [PATCH 1/9] [xitca-web] add bench for async orm --- frameworks/Rust/xitca-web/Cargo.lock | 290 +++++++++++++++--- frameworks/Rust/xitca-web/Cargo.toml | 34 +- .../Rust/xitca-web/benchmark_config.json | 22 ++ frameworks/Rust/xitca-web/src/db.rs | 24 +- .../Rust/xitca-web/src/db_diesel_async.rs | 153 +++++++++ frameworks/Rust/xitca-web/src/main_iou.rs | 79 ++++- frameworks/Rust/xitca-web/src/main_orm.rs | 67 ++++ frameworks/Rust/xitca-web/src/ser.rs | 4 +- .../Rust/xitca-web/xitca-web-orm.dockerfile | 10 + 9 files changed, 610 insertions(+), 73 deletions(-) create mode 100644 frameworks/Rust/xitca-web/src/db_diesel_async.rs create mode 100644 frameworks/Rust/xitca-web/src/main_orm.rs create mode 100644 frameworks/Rust/xitca-web/xitca-web-orm.dockerfile diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 14daebadc05..25c03fca364 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -45,9 +45,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" dependencies = [ "async-trait", "axum-core", @@ -68,16 +68,16 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sync_wrapper 1.0.1", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" dependencies = [ "async-trait", "bytes", @@ -88,7 +88,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] @@ -114,6 +114,18 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bb8" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10cf871f3ff2ce56432fddc2615ac7acc3aa22ca321f8fea800846fbb32f188" +dependencies = [ + "async-trait", + "futures-util", + "parking_lot", + "tokio", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -135,6 +147,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -143,15 +161,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.18" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -230,6 +248,20 @@ dependencies = [ "r2d2", ] +[[package]] +name = "diesel-async" +version = "0.5.0" +source = "git+https://github.com/weiznich/diesel_async#5b8262b86d8ed0e13adbbc4aee39500b9931ef8d" +dependencies = [ + "async-trait", + "bb8", + "diesel", + "futures-util", + "scoped-futures", + "tokio", + "tokio-postgres", +] + [[package]] name = "diesel_derives" version = "2.2.3" @@ -316,12 +348,39 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + [[package]] name = "futures-task" version = "0.3.30" @@ -335,6 +394,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", + "futures-macro", + "futures-sink", "futures-task", "pin-project-lite", "pin-utils", @@ -472,6 +533,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.158" @@ -643,26 +713,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -695,9 +745,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9" +checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f" dependencies = [ "bytes", "fallible-iterator", @@ -715,9 +765,9 @@ dependencies = [ [[package]] name = "pq-sys" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92c30dd81695321846d4dfe348da67b1752ebb61cd1549d203a7b57e323c435" +checksum = "f6cc05d7ea95200187117196eee9edd0644424911821aeb28a18ce60ea0b8793" dependencies = [ "vcpkg", ] @@ -853,6 +903,16 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "scoped-futures" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467" +dependencies = [ + "cfg-if", + "pin-utils", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1048,6 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", + "bytes", "libc", "mio", "parking_lot", @@ -1057,6 +1118,32 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tokio-postgres" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand", + "socket2 0.5.7", + "tokio", + "tokio-util", + "whoami", +] + [[package]] name = "tokio-uring" version = "0.5.0" @@ -1072,19 +1159,42 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "tower" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -1155,9 +1265,9 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -1186,6 +1296,88 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1337,9 +1529,10 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=0cda225#0cda2254f98b40f21bc3170dd8983f16444f0bd0" +source = "git+https://github.com/HFQR/xitca-web.git?rev=55afa4a#55afa4a0ef421019ad3fa7e2e56c526ef53df89d" dependencies = [ "fallible-iterator", + "futures-core", "percent-encoding", "phf", "postgres-protocol", @@ -1350,6 +1543,19 @@ dependencies = [ "xitca-unsafe-collection", ] +[[package]] +name = "xitca-postgres-diesel" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel#7d004873ada7e76cd34eda2d2f07454ef4bd32c4" +dependencies = [ + "diesel", + "diesel-async", + "futures-core", + "scoped-futures", + "tokio", + "xitca-postgres", +] + [[package]] name = "xitca-router" version = "0.3.0" @@ -1396,7 +1602,9 @@ dependencies = [ "atoi", "axum", "diesel", + "diesel-async", "futures-core", + "futures-util", "http-body", "mimalloc", "rand", @@ -1404,11 +1612,13 @@ dependencies = [ "serde", "serde_json", "tokio", - "tower", + "tokio-uring", + "tower 0.4.13", "tower-http", "xitca-http", "xitca-io", "xitca-postgres", + "xitca-postgres-diesel", "xitca-server", "xitca-service", "xitca-unsafe-collection", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 6c16d2d7a54..be064d13911 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -23,28 +23,35 @@ name = "xitca-web-axum" path = "./src/main_axum.rs" required-features = ["axum", "io-uring", "perf", "pg-sync", "template"] +[[bin]] +name = "xitca-web-orm" +path = "./src/main_orm.rs" +required-features = ["pg-orm-async", "template", "web-codegen"] + [[bin]] name = "xitca-web-sync" path = "./src/main_sync.rs" required-features = ["pg-orm", "template", "web-codegen"] [features] -# pg optional +# pg client optional pg = ["dep:xitca-postgres"] -# pg send/sync optional +# pg client send/sync optional pg-sync = ["dep:xitca-postgres"] -# pg orm optional -pg-orm = ["dep:diesel"] +# diesel orm optional +pg-orm = ["diesel/r2d2"] +# diesel async orm optional +pg-orm-async = ["dep:diesel", "dep:diesel-async", "dep:xitca-postgres-diesel", "futures-util"] # http router optional router = ["xitca-http/router"] # web optional web = ["dep:xitca-web"] -# web codegen optional +# web with macros optional web-codegen = ["xitca-web/codegen", "xitca-web/urlencoded"] # template optional template = ["dep:sailfish"] # io-uring optional -io-uring = ["xitca-http/io-uring", "xitca-server/io-uring"] +io-uring = ["dep:tokio-uring", "xitca-http/io-uring", "xitca-server/io-uring"] # axum optional axum = ["dep:axum", "dep:http-body", "dep:tower", "dep:tower-http", "xitca-web/tower-http-compat" ] # unrealistic performance optimization @@ -68,7 +75,12 @@ xitca-web = { version = "0.6", features = ["json"], optional = true } xitca-postgres = { version = "0.1", optional = true } # orm optional -diesel = { version = "2", features = ["postgres", "r2d2"], optional = true } +diesel = { version = "2", features = ["postgres"], optional = true } + +# orm async optional +diesel-async = { version = "0.5", features = ["bb8", "postgres"], optional = true } +xitca-postgres-diesel = { version = "0.1", optional = true } +futures-util = { version = "0.3", default-features = false, optional = true } # template optional sailfish = { version = "0.9", default-features = false, features = ["derive", "perf-inline"], optional = true } @@ -79,6 +91,9 @@ http-body = { version = "1", optional = true } tower = { version = "0.4", optional = true } tower-http = { version = "0.5", features = ["set-header"], optional = true } +# io-uring optional +tokio-uring = { version = "0.5", optional = true } + # perf optional mimalloc = { version = "0.1", default-features = false, optional = true } @@ -95,5 +110,8 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "0cda225" } +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "55afa4a" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } + +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel" } +diesel-async = { git = "https://github.com/weiznich/diesel_async" } diff --git a/frameworks/Rust/xitca-web/benchmark_config.json b/frameworks/Rust/xitca-web/benchmark_config.json index f4c152eb729..8de5174f0db 100755 --- a/frameworks/Rust/xitca-web/benchmark_config.json +++ b/frameworks/Rust/xitca-web/benchmark_config.json @@ -86,6 +86,28 @@ "notes": "", "versus": "" }, + "orm": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "port": 8080, + "approach": "realistic", + "classification": "fullstack", + "database": "postgres", + "framework": "xitca-web [orm]", + "language": "rust", + "orm": "full", + "platform": "none", + "webserver": "xitca-server", + "os": "linux", + "database_os": "linux", + "display_name": "xitca-web [orm]", + "notes": "", + "versus": "" + }, "sync": { "json_url": "/json", "plaintext_url": "/plaintext", diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 818804341b1..07a46777f27 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -2,7 +2,7 @@ #![allow(clippy::unnecessary_lazy_evaluations)] use xitca_io::bytes::BytesMut; -use xitca_postgres::{pipeline::Pipeline, pool::Pool, AsyncLendingIterator, Type}; +use xitca_postgres::{pipeline::Pipeline, pool::Pool, types::Type, AsyncLendingIterator}; use super::{ ser::{Fortune, Fortunes, World}, @@ -21,11 +21,9 @@ pub struct Client { type Shared = (Rand, BytesMut); const FORTUNE_SQL: &str = "SELECT * FROM fortune"; - const FORTUNE_SQL_TYPES: &[Type] = &[]; const WORLD_SQL: &str = "SELECT * FROM world WHERE id=$1"; - const WORLD_SQL_TYPES: &[Type] = &[Type::INT4]; fn update_query(num: usize) -> Box { @@ -71,18 +69,18 @@ impl Client { pub async fn get_world(&self) -> HandleResult { let mut conn = self.pool.get().await?; - let stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; + let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; let id = self.shared().0.gen_id(); let mut res = conn.consume().query_raw(&stmt, [id])?; let row = res.try_next().await?.ok_or_else(|| "World does not exist")?; - Ok(World::new(row.get_raw(0), row.get_raw(1))) + Ok(World::new(row.get(0), row.get(1))) } pub async fn get_worlds(&self, num: u16) -> HandleResult> { let len = num as usize; let mut conn = self.pool.get().await?; - let stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; + let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; let mut res = { let (ref mut rng, ref mut buf) = *self.shared(); @@ -95,7 +93,7 @@ impl Client { while let Some(mut item) = res.try_next().await? { while let Some(row) = item.try_next().await? { - worlds.push(World::new(row.get_raw(0), row.get_raw(1))) + worlds.push(World::new(row.get(0), row.get(1))) } } @@ -108,8 +106,8 @@ impl Client { let update = self.updates.get(len).ok_or_else(|| "num out of bound")?; let mut conn = self.pool.get().await?; - let world_stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; - let update_stmt = conn.prepare(update, &[]).await?; + let world_stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; + let update_stmt = conn.prepare_cache(update, &[]).await?; let mut params = Vec::with_capacity(len); @@ -133,7 +131,7 @@ impl Client { while let Some(mut item) = res.try_next().await? { while let Some(row) = item.try_next().await? { let r_id = r_ids.next().unwrap()[1]; - worlds.push(World::new(row.get_raw(0), r_id)) + worlds.push(World::new(row.get(0), r_id)) } } @@ -145,11 +143,11 @@ impl Client { items.push(Fortune::new(0, "Additional fortune added at request time.")); let mut conn = self.pool.get().await?; - let stmt = conn.prepare(FORTUNE_SQL, FORTUNE_SQL_TYPES).await?; - let mut res = conn.consume().query_raw::<[i32; 0]>(&stmt, [])?; + let stmt = conn.prepare_cache(FORTUNE_SQL, FORTUNE_SQL_TYPES).await?; + let mut res = conn.consume().query_raw::<_, [i32; 0]>(&stmt, [])?; while let Some(row) = res.try_next().await? { - items.push(Fortune::new(row.get_raw(0), row.get_raw::(1))); + items.push(Fortune::new(row.get(0), row.get::(1))); } items.sort_by(|it, next| it.message.cmp(&next.message)); diff --git a/frameworks/Rust/xitca-web/src/db_diesel_async.rs b/frameworks/Rust/xitca-web/src/db_diesel_async.rs new file mode 100644 index 00000000000..fdd93e43a74 --- /dev/null +++ b/frameworks/Rust/xitca-web/src/db_diesel_async.rs @@ -0,0 +1,153 @@ +use std::{ + io, + sync::{Arc, Mutex}, +}; + +use diesel::prelude::*; +use diesel_async::{ + pooled_connection::{bb8, AsyncDieselConnectionManager}, + RunQueryDsl, +}; +use futures_util::{ + future::join, + stream::{FuturesUnordered, TryStreamExt}, +}; +use xitca_postgres_diesel::AsyncPgConnection; + +use crate::{ + ser::{Fortune, Fortunes, World}, + util::{bulk_update_gen, Error, HandleResult, Rand, DB_URL}, +}; + +pub type Pool = Arc<_Pool>; + +pub struct _Pool { + pool: bb8::Pool, + rng: Mutex, +} + +pub async fn create() -> io::Result> { + bb8::Pool::builder() + .max_size(1) + .min_idle(Some(1)) + .test_on_check_out(false) + .build(AsyncDieselConnectionManager::new(DB_URL)) + .await + .map_err(io::Error::other) + .map(|pool| { + Arc::new(_Pool { + pool, + rng: Mutex::new(Rand::default()), + }) + }) +} + +#[cold] +#[inline(never)] +fn not_found() -> Error { + "world not found".into() +} + +impl _Pool { + pub async fn get_world(&self) -> HandleResult { + use crate::schema::world::dsl::*; + { + let w_id = self.rng.lock().unwrap().gen_id(); + let mut conn = self.pool.get().await?; + world.filter(id.eq(w_id)).load(&mut conn) + } + .await? + .pop() + .ok_or_else(not_found) + } + + pub async fn get_worlds(&self, num: u16) -> HandleResult> { + use crate::schema::world::dsl::*; + { + let mut conn = self.pool.get().await?; + let mut rng = self.rng.lock().unwrap(); + (0..num) + .map(|_| { + let w_id = rng.gen_id(); + let fut = world.filter(id.eq(w_id)).load::(&mut conn); + async { fut.await?.pop().ok_or_else(not_found) } + }) + .collect::>() + } + .try_collect() + .await + } + + pub async fn update(&self, num: u16) -> HandleResult> { + use crate::schema::world::dsl::*; + + let mut rngs = Vec::with_capacity(num as _); + + let (select_res, update_res) = { + let mut conn = self.pool.get().await?; + + let mut rng = self.rng.lock().unwrap(); + + let select = (0..num) + .map(|_| { + let w_id = rng.gen_id(); + let num = rng.gen_id(); + + rngs.push((w_id, num)); + + let fut = world.filter(id.eq(w_id)).load::(&mut conn); + + async move { + fut.await? + .pop() + .map(|mut w| { + w.randomnumber = num; + w + }) + .ok_or_else(not_found) + } + }) + .collect::>(); + + rngs.sort_by(|(a, _), (b, _)| a.cmp(b)); + + let update = diesel::sql_query(update_query(&rngs)).execute(&mut conn); + + join(select.try_collect::>(), update) + } + .await; + + update_res?; + let mut worlds = select_res?; + + worlds.sort_by_key(|w| w.id); + + Ok(worlds) + } + + pub async fn tell_fortune(&self) -> HandleResult { + use crate::schema::fortune::dsl::*; + + let mut items = { + let mut conn = self.pool.get().await?; + fortune.load::(&mut conn) + } + .await?; + + items.push(Fortune::new(0, "Additional fortune added at request time.")); + items.sort_by(|it, next| it.message.cmp(&next.message)); + + Ok(Fortunes::new(items)) + } +} + +// diesel does not support high level bulk update api. use raw sql to bypass the limitation. +// relate discussion: https://github.com/diesel-rs/diesel/discussions/2879 +fn update_query(ids: &[(i32, i32)]) -> String { + bulk_update_gen(|query| { + use std::fmt::Write; + ids.iter().for_each(|(w_id, num)| { + write!(query, "({}::int,{}::int),", w_id, num).unwrap(); + }); + }) +} diff --git a/frameworks/Rust/xitca-web/src/main_iou.rs b/frameworks/Rust/xitca-web/src/main_iou.rs index f66eb8778e6..b97ee5bff56 100644 --- a/frameworks/Rust/xitca-web/src/main_iou.rs +++ b/frameworks/Rust/xitca-web/src/main_iou.rs @@ -1,6 +1,8 @@ -// used as reference of if/how moving from epoll to io-uring(or mixture of the two) make sense for -// network io. +// reference of if/how moving from epoll to io-uring(or mixture of the two) make sense for network io. +// with comment on explaining why some practice are unrealistic +// custom global memory allocation don't affect real world performance in noticeable amount. +// in real world they should be used for reason like security, debug/profiling capability etc. #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; @@ -15,7 +17,7 @@ use xitca_http::{ http::{self, header::SERVER, StatusCode}, HttpServiceBuilder, }; -use xitca_service::{fn_service, ServiceExt}; +use xitca_service::{fn_service, Service, ServiceExt}; use self::{ ser::{error_response, IntoResponse, Message, Request}, @@ -23,21 +25,78 @@ use self::{ }; fn main() -> io::Result<()> { - let service = fn_service(handler) - .enclosed(context_mw()) - .enclosed(HttpServiceBuilder::h1().io_uring()); - xitca_server::Builder::new() - .bind("xitca-iou", "0.0.0.0:8080", service)? - .build() - .wait() + let addr = "0.0.0.0:8080".parse().unwrap(); + + let cores = std::thread::available_parallelism().map(|num| num.get()).unwrap_or(56); + + let handle = core::iter::repeat_with(|| { + std::thread::spawn(move || { + tokio_uring::start(async { + let service = std::rc::Rc::new( + fn_service(handler) + .enclosed(context_mw()) + .enclosed(HttpServiceBuilder::h1().io_uring()) + .call(()) + .await + .unwrap(), + ); + + let socket = tokio::net::TcpSocket::new_v4()?; + socket.set_reuseaddr(true)?; + // unrealistic due to following reason: + // 1. this only works good on unix system. + // 2. no resource distribution adjustment between sockets on different threads. causing uneven workload + // where some threads are idle while others busy. resulting in overall increased latency + socket.set_reuseport(true)?; + socket.bind(addr)?; + let listener = socket.listen(1024)?; + + let service = fn_service(handler) + .enclosed(context_mw()) + .enclosed(HttpServiceBuilder::h1().io_uring()) + .call(()) + .await + .unwrap(); + + let service = std::rc::Rc::new(service); + + loop { + match listener.accept().await { + Ok((stream, addr)) => { + let stream = stream.into_std()?; + let stream = xitca_io::net::io_uring::TcpStream::from_std(stream); + let service = service.clone(); + tokio::task::spawn_local(async move { + let _ = service.call((stream, addr)).await; + }); + } + Err(e) => return Err(e), + }; + } + }) + }) + }) + .take(cores) + .collect::>(); + + // unrealistic due to no signal handling, not shutdown handling. when killing this process all resources that + // need clean async shutdown will be leaked. + for handle in handle { + handle.join().unwrap()?; + } + + Ok(()) } async fn handler(ctx: Ctx<'_, Request>) -> Result, Infallible> { let (req, state) = ctx.into_parts(); + // unrealistic due to lack of http method check let mut res = match req.uri().path() { + // unrealistic due to lack of dynamic route matching. "/plaintext" => req.text_response().unwrap(), "/json" => req.json_response(state, &Message::new()).unwrap(), "/db" => { + // unrealistic due to no error handling. any db/serialization error will cause process crash let world = state.client.get_world().await.unwrap(); req.json_response(state, &world).unwrap() } diff --git a/frameworks/Rust/xitca-web/src/main_orm.rs b/frameworks/Rust/xitca-web/src/main_orm.rs new file mode 100644 index 00000000000..86e8037ac2e --- /dev/null +++ b/frameworks/Rust/xitca-web/src/main_orm.rs @@ -0,0 +1,67 @@ +mod db_diesel_async; +mod schema; +mod ser; +mod util; + +use serde::Serialize; +use xitca_web::{ + codegen::route, + handler::{html::Html, json::Json, query::Query, state::StateRef, text::Text}, + http::{header::SERVER, WebResponse}, + route::get, + App, +}; + +use db_diesel_async::Pool; +use ser::Num; +use util::{HandleResult, SERVER_HEADER_VALUE}; + +fn main() -> std::io::Result<()> { + App::new() + .with_async_state(db_diesel_async::create) + .at("/plaintext", get(Text("Hello, World!"))) + .at("/json", get(Json(ser::Message::new()))) + .at_typed(db) + .at_typed(fortunes) + .at_typed(queries) + .at_typed(updates) + .map(header) + .serve() + .disable_vectored_write() + .bind("0.0.0.0:8080")? + .run() + .wait() +} + +fn header(mut res: WebResponse) -> WebResponse { + res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE); + res +} + +#[route("/db", method = get)] +async fn db(StateRef(pool): StateRef<'_, Pool>) -> HandleResult> { + pool.get_world().await.map(Json) +} + +#[route("/fortunes", method = get)] +async fn fortunes(StateRef(pool): StateRef<'_, Pool>) -> HandleResult> { + use sailfish::TemplateOnce; + let html = pool.tell_fortune().await?.render_once()?; + Ok(Html(html)) +} + +#[route("/queries", method = get)] +async fn queries( + Query(Num(num)): Query, + StateRef(pool): StateRef<'_, Pool>, +) -> HandleResult> { + pool.get_worlds(num).await.map(Json) +} + +#[route("/updates", method = get)] +async fn updates( + Query(Num(num)): Query, + StateRef(pool): StateRef<'_, Pool>, +) -> HandleResult> { + pool.update(num).await.map(Json) +} diff --git a/frameworks/Rust/xitca-web/src/ser.rs b/frameworks/Rust/xitca-web/src/ser.rs index 53dcff13cf0..e7a1de8a178 100644 --- a/frameworks/Rust/xitca-web/src/ser.rs +++ b/frameworks/Rust/xitca-web/src/ser.rs @@ -33,7 +33,7 @@ impl Message { pub struct Num(pub u16); -#[cfg_attr(feature = "pg-orm", derive(diesel::Queryable))] +#[cfg_attr(any(feature = "pg-orm", feature = "pg-orm-async"), derive(diesel::Queryable))] pub struct World { pub id: i32, pub randomnumber: i32, @@ -46,7 +46,7 @@ impl World { } } -#[cfg_attr(feature = "pg-orm", derive(diesel::Queryable))] +#[cfg_attr(any(feature = "pg-orm", feature = "pg-orm-async"), derive(diesel::Queryable))] pub struct Fortune { pub id: i32, pub message: Cow<'static, str>, diff --git a/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile b/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile new file mode 100644 index 00000000000..06e40825b00 --- /dev/null +++ b/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile @@ -0,0 +1,10 @@ +FROM rust:1.81 + +ADD ./ /xitca-web +WORKDIR /xitca-web + +RUN cargo build --release --bin xitca-web-orm --features pg-orm-async,template,web-codegen + +EXPOSE 8080 + +CMD ./target/release/xitca-web-orm From 746b31465ec019d5768bbe0e026423717d846cb8 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Sat, 21 Sep 2024 19:16:27 +0800 Subject: [PATCH 2/9] dep fix --- frameworks/Rust/xitca-web/Cargo.lock | 4 ++-- frameworks/Rust/xitca-web/Cargo.toml | 4 ++-- frameworks/Rust/xitca-web/src/main_iou.rs | 11 +---------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 25c03fca364..dd5be988de3 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -251,7 +251,7 @@ dependencies = [ [[package]] name = "diesel-async" version = "0.5.0" -source = "git+https://github.com/weiznich/diesel_async#5b8262b86d8ed0e13adbbc4aee39500b9931ef8d" +source = "git+https://github.com/weiznich/diesel_async?rev=5b8262b#5b8262b86d8ed0e13adbbc4aee39500b9931ef8d" dependencies = [ "async-trait", "bb8", @@ -1546,7 +1546,7 @@ dependencies = [ [[package]] name = "xitca-postgres-diesel" version = "0.1.0" -source = "git+https://github.com/fakeshadow/xitca-postgres-diesel#7d004873ada7e76cd34eda2d2f07454ef4bd32c4" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=7d00487#7d004873ada7e76cd34eda2d2f07454ef4bd32c4" dependencies = [ "diesel", "diesel-async", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index be064d13911..ee919c1b3d8 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -113,5 +113,5 @@ panic = "abort" xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "55afa4a" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } -xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel" } -diesel-async = { git = "https://github.com/weiznich/diesel_async" } +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "7d00487" } +diesel-async = { git = "https://github.com/weiznich/diesel_async", rev = "5b8262b" } diff --git a/frameworks/Rust/xitca-web/src/main_iou.rs b/frameworks/Rust/xitca-web/src/main_iou.rs index b97ee5bff56..3aebffa7e1a 100644 --- a/frameworks/Rust/xitca-web/src/main_iou.rs +++ b/frameworks/Rust/xitca-web/src/main_iou.rs @@ -2,7 +2,7 @@ // with comment on explaining why some practice are unrealistic // custom global memory allocation don't affect real world performance in noticeable amount. -// in real world they should be used for reason like security, debug/profiling capability etc. +// in real world they should be used for reason like security, debug/profiling capability etc. #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; @@ -32,15 +32,6 @@ fn main() -> io::Result<()> { let handle = core::iter::repeat_with(|| { std::thread::spawn(move || { tokio_uring::start(async { - let service = std::rc::Rc::new( - fn_service(handler) - .enclosed(context_mw()) - .enclosed(HttpServiceBuilder::h1().io_uring()) - .call(()) - .await - .unwrap(), - ); - let socket = tokio::net::TcpSocket::new_v4()?; socket.set_reuseaddr(true)?; // unrealistic due to following reason: From 598b4ea609126c68feb3e16f2dea3ba672d13ce9 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Sun, 22 Sep 2024 02:28:41 +0800 Subject: [PATCH 3/9] use release build of xitca-postgres --- frameworks/Rust/xitca-web/Cargo.lock | 5 +++-- frameworks/Rust/xitca-web/Cargo.toml | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index dd5be988de3..c1fa3eb27dd 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -1529,7 +1529,8 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=55afa4a#55afa4a0ef421019ad3fa7e2e56c526ef53df89d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37aa7cc74ea36c08586e6fc86a94955924159d61cbb5df4adba2ef9d799951d6" dependencies = [ "fallible-iterator", "futures-core", @@ -1546,7 +1547,7 @@ dependencies = [ [[package]] name = "xitca-postgres-diesel" version = "0.1.0" -source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=7d00487#7d004873ada7e76cd34eda2d2f07454ef4bd32c4" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=8addeca#8addeca29b98c4bfb97b045ffe75b9fd82f565c5" dependencies = [ "diesel", "diesel-async", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index ee919c1b3d8..60ed25a28c6 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -110,8 +110,7 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "55afa4a" } -mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "8addeca" } -xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "7d00487" } diesel-async = { git = "https://github.com/weiznich/diesel_async", rev = "5b8262b" } +mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } From 6ee7bb05b9649eaf37e104625cfb631d86f64437 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 25 Sep 2024 02:51:02 +0800 Subject: [PATCH 4/9] fix framework naming --- frameworks/Rust/xitca-web/Cargo.lock | 210 +++--------------- frameworks/Rust/xitca-web/Cargo.toml | 18 +- .../Rust/xitca-web/benchmark_config.json | 32 +-- frameworks/Rust/xitca-web/src/db.rs | 45 +--- frameworks/Rust/xitca-web/src/main_axum.rs | 150 ------------- .../Rust/xitca-web/xitca-web-axum.dockerfile | 10 - 6 files changed, 44 insertions(+), 421 deletions(-) delete mode 100644 frameworks/Rust/xitca-web/src/main_axum.rs delete mode 100644 frameworks/Rust/xitca-web/xitca-web-axum.dockerfile diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index c1fa3eb27dd..fb8edf2ff3f 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -19,9 +19,9 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -43,56 +43,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "axum" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tower 0.5.1", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.1", - "tower-layer", - "tower-service", -] - [[package]] name = "backtrace" version = "0.3.74" @@ -470,29 +420,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - [[package]] name = "httparse" version = "1.9.4" @@ -544,9 +471,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libmimalloc-sys" @@ -585,12 +512,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "md-5" version = "0.10.6" @@ -616,12 +537,6 @@ dependencies = [ "libmimalloc-sys", ] -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -833,9 +748,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "62871f2d65009c0256aed1b9cfeeb8ac272833c404e13d53d400cd0dad7a2ac0" dependencies = [ "bitflags 2.6.0", ] @@ -846,12 +761,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - [[package]] name = "ryu" version = "1.0.18" @@ -951,16 +860,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1074,18 +973,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - [[package]] name = "tinyvec" version = "1.8.0" @@ -1172,66 +1059,12 @@ dependencies = [ "tokio", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" -dependencies = [ - "bitflags 2.6.0", - "bytes", - "http", - "http-body", - "http-body-util", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-core", ] @@ -1241,9 +1074,6 @@ name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] [[package]] name = "typenum" @@ -1544,6 +1374,23 @@ dependencies = [ "xitca-unsafe-collection", ] +[[package]] +name = "xitca-postgres" +version = "0.2.0" +source = "git+https://github.com/HFQR/xitca-web.git?rev=7e6534f#7e6534f002296a178f0fe00261dc3be975031053" +dependencies = [ + "fallible-iterator", + "futures-core", + "percent-encoding", + "phf", + "postgres-protocol", + "postgres-types", + "tokio", + "tracing", + "xitca-io", + "xitca-unsafe-collection", +] + [[package]] name = "xitca-postgres-diesel" version = "0.1.0" @@ -1554,7 +1401,7 @@ dependencies = [ "futures-core", "scoped-futures", "tokio", - "xitca-postgres", + "xitca-postgres 0.1.0", ] [[package]] @@ -1601,12 +1448,10 @@ name = "xitca-web" version = "0.1.0" dependencies = [ "atoi", - "axum", "diesel", "diesel-async", "futures-core", "futures-util", - "http-body", "mimalloc", "rand", "sailfish", @@ -1614,11 +1459,9 @@ dependencies = [ "serde_json", "tokio", "tokio-uring", - "tower 0.4.13", - "tower-http", "xitca-http", "xitca-io", - "xitca-postgres", + "xitca-postgres 0.2.0", "xitca-postgres-diesel", "xitca-server", "xitca-service", @@ -1633,14 +1476,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd4f8f16791ea2a8845f617f1e87887f917835e0603d01f03a51e638b9613d0c" dependencies = [ "futures-core", - "http-body", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", "tokio", - "tower-layer", - "tower-service", "xitca-codegen", "xitca-http", "xitca-server", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 60ed25a28c6..21e9e8ef1cf 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -18,11 +18,6 @@ name = "xitca-web-wasm" path = "./src/main_wasm.rs" required-features = ["web"] -[[bin]] -name = "xitca-web-axum" -path = "./src/main_axum.rs" -required-features = ["axum", "io-uring", "perf", "pg-sync", "template"] - [[bin]] name = "xitca-web-orm" path = "./src/main_orm.rs" @@ -36,8 +31,6 @@ required-features = ["pg-orm", "template", "web-codegen"] [features] # pg client optional pg = ["dep:xitca-postgres"] -# pg client send/sync optional -pg-sync = ["dep:xitca-postgres"] # diesel orm optional pg-orm = ["diesel/r2d2"] # diesel async orm optional @@ -52,8 +45,6 @@ web-codegen = ["xitca-web/codegen", "xitca-web/urlencoded"] template = ["dep:sailfish"] # io-uring optional io-uring = ["dep:tokio-uring", "xitca-http/io-uring", "xitca-server/io-uring"] -# axum optional -axum = ["dep:axum", "dep:http-body", "dep:tower", "dep:tower-http", "xitca-web/tower-http-compat" ] # unrealistic performance optimization perf = ["dep:mimalloc", "tokio/parking_lot"] @@ -72,7 +63,7 @@ serde_json = { version = "1" } xitca-web = { version = "0.6", features = ["json"], optional = true } # raw-pg optional -xitca-postgres = { version = "0.1", optional = true } +xitca-postgres = { version = "0.2", optional = true } # orm optional diesel = { version = "2", features = ["postgres"], optional = true } @@ -85,12 +76,6 @@ futures-util = { version = "0.3", default-features = false, optional = true } # template optional sailfish = { version = "0.9", default-features = false, features = ["derive", "perf-inline"], optional = true } -# axum optional -axum = { version = "0.7", optional = true, default-features = false, features = ["json", "query"] } -http-body = { version = "1", optional = true } -tower = { version = "0.4", optional = true } -tower-http = { version = "0.5", features = ["set-header"], optional = true } - # io-uring optional tokio-uring = { version = "0.5", optional = true } @@ -110,6 +95,7 @@ codegen-units = 1 panic = "abort" [patch.crates-io] +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "7e6534f" } xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "8addeca" } diesel-async = { git = "https://github.com/weiznich/diesel_async", rev = "5b8262b" } diff --git a/frameworks/Rust/xitca-web/benchmark_config.json b/frameworks/Rust/xitca-web/benchmark_config.json index 8de5174f0db..973d1961472 100755 --- a/frameworks/Rust/xitca-web/benchmark_config.json +++ b/frameworks/Rust/xitca-web/benchmark_config.json @@ -35,14 +35,14 @@ "approach": "Stripped", "classification": "Platform", "database": "Postgres", - "framework": "xitca-web [unrealistic]", + "framework": "xitca-web", "language": "Rust", "orm": "Raw", "platform": "None", "webserver": "xitca-server", "os": "Linux", "database_os": "Linux", - "display_name": "xitca-web [unrealistic]", + "display_name": "xitca-web [iou]", "notes": "", "versus": "" }, @@ -53,7 +53,7 @@ "approach": "Realistic", "classification": "Micro", "database": "none", - "framework": "xitca-web [wasm]", + "framework": "xitca-web", "language": "rust", "orm": "raw", "platform": "none", @@ -64,28 +64,6 @@ "notes": "", "versus": "" }, - "axum": { - "json_url": "/json", - "plaintext_url": "/plaintext", - "db_url": "/db", - "fortune_url": "/fortunes", - "query_url": "/queries?q=", - "update_url": "/updates?q=", - "port": 8080, - "approach": "realistic", - "classification": "micro", - "database": "postgres", - "framework": "axum [xitca]", - "language": "rust", - "orm": "raw", - "platform": "none", - "webserver": "xitca-server", - "os": "linux", - "database_os": "linux", - "display_name": "axum [xitca]", - "notes": "", - "versus": "" - }, "orm": { "json_url": "/json", "plaintext_url": "/plaintext", @@ -97,7 +75,7 @@ "approach": "realistic", "classification": "fullstack", "database": "postgres", - "framework": "xitca-web [orm]", + "framework": "xitca-web", "language": "rust", "orm": "full", "platform": "none", @@ -119,7 +97,7 @@ "approach": "realistic", "classification": "micro", "database": "postgres", - "framework": "xitca-web [sync]", + "framework": "xitca-web", "language": "rust", "orm": "full", "platform": "none", diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 07a46777f27..33a6d81cc57 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -11,10 +11,7 @@ use super::{ pub struct Client { pool: Pool, - #[cfg(not(feature = "pg-sync"))] shared: std::cell::RefCell, - #[cfg(feature = "pg-sync")] - shared: std::sync::Mutex, updates: Box<[Box]>, } @@ -39,39 +36,21 @@ fn update_query(num: usize) -> Box { pub async fn create() -> HandleResult { let pool = Pool::builder(DB_URL).capacity(1).build()?; - - let shared = (Rand::default(), BytesMut::new()); - - let updates = core::iter::once(Box::from("")) - .chain((1..=500).map(update_query)) - .collect(); - Ok(Client { pool, - #[cfg(not(feature = "pg-sync"))] - shared: std::cell::RefCell::new(shared), - #[cfg(feature = "pg-sync")] - shared: std::sync::Mutex::new(shared), - updates, + shared: std::cell::RefCell::new((Rand::default(), BytesMut::new())), + updates: core::iter::once(Box::from("")) + .chain((1..=500).map(update_query)) + .collect(), }) } impl Client { - #[cfg(not(feature = "pg-sync"))] - fn shared(&self) -> std::cell::RefMut<'_, Shared> { - self.shared.borrow_mut() - } - - #[cfg(feature = "pg-sync")] - fn shared(&self) -> std::sync::MutexGuard<'_, Shared> { - self.shared.lock().unwrap() - } - pub async fn get_world(&self) -> HandleResult { let mut conn = self.pool.get().await?; let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; - let id = self.shared().0.gen_id(); - let mut res = conn.consume().query_raw(&stmt, [id])?; + let id = self.shared.borrow_mut().0.gen_id(); + let mut res = conn.consume().query(stmt.bind([id]))?; let row = res.try_next().await?.ok_or_else(|| "World does not exist")?; Ok(World::new(row.get(0), row.get(1))) } @@ -83,9 +62,9 @@ impl Client { let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; let mut res = { - let (ref mut rng, ref mut buf) = *self.shared(); + let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); let mut pipe = Pipeline::with_capacity_from_buf(len, buf); - (0..num).try_for_each(|_| pipe.query_raw(&stmt, [rng.gen_id()]))?; + (0..num).try_for_each(|_| pipe.query(stmt.bind([rng.gen_id()])))?; conn.consume().pipeline(pipe)? }; @@ -112,15 +91,15 @@ impl Client { let mut params = Vec::with_capacity(len); let mut res = { - let (ref mut rng, ref mut buf) = *self.shared(); + let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); let mut pipe = Pipeline::with_capacity_from_buf(len + 1, buf); (0..num).try_for_each(|_| { let w_id = rng.gen_id(); let r_id = rng.gen_id(); params.push([w_id, r_id]); - pipe.query_raw(&world_stmt, [w_id]) + pipe.query(world_stmt.bind([w_id])) })?; - pipe.query_raw(&update_stmt, sort_update_params(¶ms))?; + pipe.query(update_stmt.bind(sort_update_params(¶ms)))?; conn.consume().pipeline(pipe)? }; @@ -144,7 +123,7 @@ impl Client { let mut conn = self.pool.get().await?; let stmt = conn.prepare_cache(FORTUNE_SQL, FORTUNE_SQL_TYPES).await?; - let mut res = conn.consume().query_raw::<_, [i32; 0]>(&stmt, [])?; + let mut res = conn.consume().query(&stmt)?; while let Some(row) = res.try_next().await? { items.push(Fortune::new(row.get(0), row.get::(1))); diff --git a/frameworks/Rust/xitca-web/src/main_axum.rs b/frameworks/Rust/xitca-web/src/main_axum.rs deleted file mode 100644 index 02fdfba8a20..00000000000 --- a/frameworks/Rust/xitca-web/src/main_axum.rs +++ /dev/null @@ -1,150 +0,0 @@ -//! show case of axum running on proper thread per core server with io-uring enabled. - -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -mod db; -mod ser; -mod util; - -use std::sync::Arc; - -use axum::{ - extract::{Json, Query, State}, - http::{ - header::{HeaderValue, SERVER}, - StatusCode, - }, - response::{Html, IntoResponse, Response}, - routing::{get, Router}, -}; -use tower_http::set_header::SetResponseHeaderLayer; - -use crate::{db::Client, ser::Num, tower_compat::TowerHttp}; - -fn main() -> std::io::Result<()> { - let service = TowerHttp::service(|| async { - let cli = db::create().await?; - let service = Router::new() - .route("/plaintext", get(plain_text)) - .route("/json", get(json)) - .route("/db", get(db)) - .route("/fortunes", get(fortunes)) - .route("/queries", get(queries)) - .route("/updates", get(updates)) - .with_state(Arc::new(cli)) - .layer(SetResponseHeaderLayer::if_not_present( - SERVER, - HeaderValue::from_static("A"), - )); - Ok(service) - }); - xitca_server::Builder::new() - .bind("xitca-axum", "0.0.0.0:8080", service)? - .build() - .wait() -} - -async fn plain_text() -> &'static str { - "Hello, World!" -} - -async fn json() -> impl IntoResponse { - Json(ser::Message::new()) -} - -async fn db(State(cli): State>) -> impl IntoResponse { - cli.get_world().await.map(Json).map_err(Error) -} - -async fn fortunes(State(cli): State>) -> impl IntoResponse { - use sailfish::TemplateOnce; - cli.tell_fortune() - .await - .map_err(Error)? - .render_once() - .map(Html) - .map_err(|e| Error(Box::new(e))) -} - -async fn queries(State(cli): State>, Query(Num(num)): Query) -> impl IntoResponse { - cli.get_worlds(num).await.map(Json).map_err(Error) -} - -async fn updates(State(cli): State>, Query(Num(num)): Query) -> impl IntoResponse { - cli.update(num).await.map(Json).map_err(Error) -} - -struct Error(util::Error); - -impl IntoResponse for Error { - fn into_response(self) -> Response { - let mut res = self.0.to_string().into_response(); - *res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - res - } -} - -// compat module between xitca-http and axum. -mod tower_compat { - use core::{cell::RefCell, fmt, future::Future, marker::PhantomData}; - - use std::net::SocketAddr; - - use http_body::Body; - use xitca_http::{ - bytes::Bytes, - h1::RequestBody, - http::{Request, RequestExt, Response}, - HttpServiceBuilder, - }; - use xitca_io::net::io_uring::TcpStream; - use xitca_service::{fn_build, middleware::UncheckedReady, ready::ReadyService, Service, ServiceExt}; - use xitca_web::service::tower_http_compat::{CompatReqBody, CompatResBody}; - - pub struct TowerHttp { - service: RefCell, - _p: PhantomData, - } - - impl TowerHttp { - pub fn service( - func: F, - ) -> impl Service, Error = impl fmt::Debug> - where - F: Fn() -> Fut + Send + Sync + Clone, - Fut: Future>, - S: tower::Service, ()>>, Response = Response>, - S::Error: fmt::Debug, - B: Body + Send + 'static, - { - fn_build(move |_| { - let func = func.clone(); - async move { - func().await.map(|service| TowerHttp { - service: RefCell::new(service), - _p: PhantomData, - }) - } - }) - .enclosed(UncheckedReady) - .enclosed(HttpServiceBuilder::h1().io_uring()) - } - } - - impl Service>> for TowerHttp - where - S: tower::Service, ()>>, Response = Response>, - { - type Response = Response>; - type Error = S::Error; - - async fn call(&self, req: Request>) -> Result { - let (parts, ext) = req.into_parts(); - let req = Request::from_parts(parts, CompatReqBody::new(ext, ())); - let fut = self.service.borrow_mut().call(req); - let (parts, body) = fut.await?.into_parts(); - Ok(Response::from_parts(parts, CompatResBody::new(body))) - } - } -} diff --git a/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile b/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile deleted file mode 100644 index 3c6271834ea..00000000000 --- a/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM rust:1.81 - -ADD ./ /xitca-web -WORKDIR /xitca-web - -RUN cargo build --release --bin xitca-web-axum --features axum,io-uring,perf,pg-sync,template - -EXPOSE 8080 - -CMD ./target/release/xitca-web-axum From c81e6c1e187c37b9ecfbf1f20fe947b94bbb1c65 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Tue, 1 Oct 2024 23:42:16 +0800 Subject: [PATCH 5/9] dep update --- frameworks/Rust/xitca-web/Cargo.lock | 67 ++++++++++++---------------- frameworks/Rust/xitca-web/Cargo.toml | 3 +- frameworks/Rust/xitca-web/src/db.rs | 55 ++++++++++++----------- 3 files changed, 58 insertions(+), 67 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index fb8edf2ff3f..4128d0a2c8b 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -117,9 +117,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.21" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "shlex", ] @@ -422,9 +422,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -577,9 +577,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "parking_lot" @@ -640,6 +643,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "postgres-protocol" version = "0.6.7" @@ -748,9 +757,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62871f2d65009c0256aed1b9cfeeb8ac272833c404e13d53d400cd0dad7a2ac0" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -964,9 +973,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1104,9 +1113,9 @@ dependencies = [ [[package]] name = "unicode-properties" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "vcpkg" @@ -1356,33 +1365,15 @@ dependencies = [ "xitca-unsafe-collection", ] -[[package]] -name = "xitca-postgres" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37aa7cc74ea36c08586e6fc86a94955924159d61cbb5df4adba2ef9d799951d6" -dependencies = [ - "fallible-iterator", - "futures-core", - "percent-encoding", - "phf", - "postgres-protocol", - "postgres-types", - "tokio", - "tracing", - "xitca-io", - "xitca-unsafe-collection", -] - [[package]] name = "xitca-postgres" version = "0.2.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=7e6534f#7e6534f002296a178f0fe00261dc3be975031053" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de2f2b18475daa6bccd462b410619916ad592508a06e9192badff52f30371e6" dependencies = [ "fallible-iterator", "futures-core", "percent-encoding", - "phf", "postgres-protocol", "postgres-types", "tokio", @@ -1394,14 +1385,14 @@ dependencies = [ [[package]] name = "xitca-postgres-diesel" version = "0.1.0" -source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=8addeca#8addeca29b98c4bfb97b045ffe75b9fd82f565c5" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df#5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df" dependencies = [ "diesel", "diesel-async", "futures-core", "scoped-futures", "tokio", - "xitca-postgres 0.1.0", + "xitca-postgres", ] [[package]] @@ -1461,7 +1452,7 @@ dependencies = [ "tokio-uring", "xitca-http", "xitca-io", - "xitca-postgres 0.2.0", + "xitca-postgres", "xitca-postgres-diesel", "xitca-server", "xitca-service", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 21e9e8ef1cf..e7986aa5673 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -95,8 +95,7 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "7e6534f" } -xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "8addeca" } +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df" } diesel-async = { git = "https://github.com/weiznich/diesel_async", rev = "5b8262b" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 33a6d81cc57..75c70be21c8 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,8 +1,14 @@ -// clippy is dumb and have no idea what should be lazy or not -#![allow(clippy::unnecessary_lazy_evaluations)] +use std::cell::RefCell; use xitca_io::bytes::BytesMut; -use xitca_postgres::{pipeline::Pipeline, pool::Pool, types::Type, AsyncLendingIterator}; +use xitca_postgres::{ + iter::AsyncLendingIterator, + pipeline::Pipeline, + pool::Pool, + statement::{Statement, StatementNamed}, + types::Type, + Execute, ExecuteMut, +}; use super::{ ser::{Fortune, Fortunes, World}, @@ -11,17 +17,14 @@ use super::{ pub struct Client { pool: Pool, - shared: std::cell::RefCell, + shared: RefCell, updates: Box<[Box]>, } type Shared = (Rand, BytesMut); -const FORTUNE_SQL: &str = "SELECT * FROM fortune"; -const FORTUNE_SQL_TYPES: &[Type] = &[]; - -const WORLD_SQL: &str = "SELECT * FROM world WHERE id=$1"; -const WORLD_SQL_TYPES: &[Type] = &[Type::INT4]; +const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); +const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); fn update_query(num: usize) -> Box { bulk_update_gen(|query| { @@ -35,10 +38,9 @@ fn update_query(num: usize) -> Box { } pub async fn create() -> HandleResult { - let pool = Pool::builder(DB_URL).capacity(1).build()?; Ok(Client { - pool, - shared: std::cell::RefCell::new((Rand::default(), BytesMut::new())), + pool: Pool::builder(DB_URL).capacity(1).build()?, + shared: RefCell::new((Rand::default(), BytesMut::new())), updates: core::iter::once(Box::from("")) .chain((1..=500).map(update_query)) .collect(), @@ -48,10 +50,10 @@ pub async fn create() -> HandleResult { impl Client { pub async fn get_world(&self) -> HandleResult { let mut conn = self.pool.get().await?; - let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; + let stmt = WORLD_STMT.execute_mut(&mut conn).await?; let id = self.shared.borrow_mut().0.gen_id(); - let mut res = conn.consume().query(stmt.bind([id]))?; - let row = res.try_next().await?.ok_or_else(|| "World does not exist")?; + let mut res = stmt.bind([id]).query(&conn.consume()).await?; + let row = res.try_next().await?.ok_or("request World does not exist")?; Ok(World::new(row.get(0), row.get(1))) } @@ -59,13 +61,13 @@ impl Client { let len = num as usize; let mut conn = self.pool.get().await?; - let stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; + let stmt = WORLD_STMT.execute_mut(&mut conn).await?; let mut res = { let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); let mut pipe = Pipeline::with_capacity_from_buf(len, buf); - (0..num).try_for_each(|_| pipe.query(stmt.bind([rng.gen_id()])))?; - conn.consume().pipeline(pipe)? + (0..num).try_for_each(|_| stmt.bind([rng.gen_id()]).query_mut(&mut pipe))?; + pipe.query(&conn.consume())? }; let mut worlds = Vec::with_capacity(len); @@ -82,11 +84,10 @@ impl Client { pub async fn update(&self, num: u16) -> HandleResult> { let len = num as usize; - let update = self.updates.get(len).ok_or_else(|| "num out of bound")?; - + let update = self.updates.get(len).ok_or("request num is out of range")?; let mut conn = self.pool.get().await?; - let world_stmt = conn.prepare_cache(WORLD_SQL, WORLD_SQL_TYPES).await?; - let update_stmt = conn.prepare_cache(update, &[]).await?; + let world_stmt = WORLD_STMT.execute_mut(&mut conn).await?; + let update_stmt = Statement::named(update, &[]).execute_mut(&mut conn).await?; let mut params = Vec::with_capacity(len); @@ -97,10 +98,10 @@ impl Client { let w_id = rng.gen_id(); let r_id = rng.gen_id(); params.push([w_id, r_id]); - pipe.query(world_stmt.bind([w_id])) + world_stmt.bind([w_id]).query_mut(&mut pipe) })?; - pipe.query(update_stmt.bind(sort_update_params(¶ms)))?; - conn.consume().pipeline(pipe)? + update_stmt.bind(sort_update_params(¶ms)).query_mut(&mut pipe)?; + pipe.query(&conn.consume())? }; let mut worlds = Vec::with_capacity(len); @@ -122,8 +123,8 @@ impl Client { items.push(Fortune::new(0, "Additional fortune added at request time.")); let mut conn = self.pool.get().await?; - let stmt = conn.prepare_cache(FORTUNE_SQL, FORTUNE_SQL_TYPES).await?; - let mut res = conn.consume().query(&stmt)?; + let stmt = FORTUNE_STMT.execute_mut(&mut conn).await?; + let mut res = stmt.query(&conn.consume()).await?; while let Some(row) = res.try_next().await? { items.push(Fortune::new(row.get(0), row.get::(1))); From f31fdc029d889c26dba7667bdf648ee8f7159beb Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 2 Oct 2024 12:52:12 +0800 Subject: [PATCH 6/9] fix build --- frameworks/Rust/xitca-web/Cargo.lock | 6 +++--- frameworks/Rust/xitca-web/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 4128d0a2c8b..ef3dabd7db6 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -1367,9 +1367,9 @@ dependencies = [ [[package]] name = "xitca-postgres" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de2f2b18475daa6bccd462b410619916ad592508a06e9192badff52f30371e6" +checksum = "46046cb7a3d4fcfb5c858bab0651c73bb45c0c5f9f0f53dd4eb991f2d6e5d6f4" dependencies = [ "fallible-iterator", "futures-core", @@ -1385,7 +1385,7 @@ dependencies = [ [[package]] name = "xitca-postgres-diesel" version = "0.1.0" -source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df#5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=ae93ee9#ae93ee95277e281fb87b351c42bfc2fc5a56703a" dependencies = [ "diesel", "diesel-async", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index e7986aa5673..61b28d3ffb4 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -95,7 +95,7 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "5fb1e6d5f0f20cfb5ef0833a44dc209b1f46f1df" } +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "ae93ee9" } diesel-async = { git = "https://github.com/weiznich/diesel_async", rev = "5b8262b" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } From f7c57a4faf6e0be8e021866963f2e04b113c17e8 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 2 Oct 2024 19:05:30 +0800 Subject: [PATCH 7/9] add unrealistic db impl --- .../Rust/xitca-web/src/db_unrealistic.rs | 178 ++++++++++++++++++ frameworks/Rust/xitca-web/src/main_iou.rs | 5 +- 2 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 frameworks/Rust/xitca-web/src/db_unrealistic.rs diff --git a/frameworks/Rust/xitca-web/src/db_unrealistic.rs b/frameworks/Rust/xitca-web/src/db_unrealistic.rs new file mode 100644 index 00000000000..838b097529c --- /dev/null +++ b/frameworks/Rust/xitca-web/src/db_unrealistic.rs @@ -0,0 +1,178 @@ +//! this module is unrealistic. related issue: +//! https://github.com/TechEmpower/FrameworkBenchmarks/issues/8790 + +use std::cell::RefCell; + +use xitca_io::bytes::BytesMut; +use xitca_postgres::{ + iter::AsyncLendingIterator, + pipeline::Pipeline, + statement::{Statement, StatementNamed}, + types::Type, + Execute, ExecuteMut, +}; + +use super::{ + ser::{Fortune, Fortunes, World}, + util::{bulk_update_gen, HandleResult, Rand, DB_URL}, +}; + +pub struct Client { + cli: xitca_postgres::Client, + shared: RefCell, + fortune: Statement, + world: Statement, + updates: Box<[Statement]>, +} + +type Shared = (Rand, BytesMut); + +const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); +const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); + +fn update_query(num: usize) -> Box { + bulk_update_gen(|query| { + use std::fmt::Write; + (1..=num).fold((1, query), |(idx, query), _| { + write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); + (idx + 2, query) + }); + }) + .into_boxed_str() +} + +pub async fn create() -> HandleResult { + let (cli, mut drv) = xitca_postgres::Postgres::new(DB_URL).connect().await?; + + tokio::task::spawn(tokio::task::unconstrained(async move { + while drv.try_next().await?.is_some() {} + HandleResult::Ok(()) + })); + + let world = WORLD_STMT.execute(&cli).await?.leak(); + let fortune = FORTUNE_STMT.execute(&cli).await?.leak(); + + let mut updates = vec![Statement::default()]; + + for update in (1..=500).map(update_query).into_iter() { + let stmt = Statement::named(&update, &[]).execute(&cli).await?.leak(); + updates.push(stmt); + } + + Ok(Client { + cli, + shared: RefCell::new((Rand::default(), BytesMut::new())), + world, + fortune, + updates: updates.into_boxed_slice(), + }) +} + +impl Client { + pub async fn get_world(&self) -> HandleResult { + let id = self.shared.borrow_mut().0.gen_id(); + let mut res = self.world.bind([id]).query(&self.cli).await?; + let row = res.try_next().await?.ok_or("request World does not exist")?; + Ok(World::new(row.get(0), row.get(1))) + } + + pub async fn get_worlds(&self, num: u16) -> HandleResult> { + let len = num as usize; + + let mut res = { + let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); + let mut pipe = Pipeline::with_capacity_from_buf(len, buf); + (0..num).try_for_each(|_| self.world.bind([rng.gen_id()]).query_mut(&mut pipe))?; + pipe.query(&self.cli)? + }; + + let mut worlds = Vec::with_capacity(len); + + while let Some(mut item) = res.try_next().await? { + while let Some(row) = item.try_next().await? { + worlds.push(World::new(row.get(0), row.get(1))) + } + } + + Ok(worlds) + } + + pub async fn update(&self, num: u16) -> HandleResult> { + let len = num as usize; + + let mut params = Vec::with_capacity(len); + + let mut res = { + let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); + let mut pipe = Pipeline::with_capacity_from_buf(len + 1, buf); + (0..num).try_for_each(|_| { + let w_id = rng.gen_id(); + let r_id = rng.gen_id(); + params.push([w_id, r_id]); + self.world.bind([w_id]).query_mut(&mut pipe) + })?; + self.updates[len] + .bind(sort_update_params(¶ms)) + .query_mut(&mut pipe)?; + pipe.query(&self.cli)? + }; + + let mut worlds = Vec::with_capacity(len); + + let mut r_ids = params.into_iter(); + + while let Some(mut item) = res.try_next().await? { + while let Some(row) = item.try_next().await? { + let r_id = r_ids.next().unwrap()[1]; + worlds.push(World::new(row.get(0), r_id)) + } + } + + Ok(worlds) + } + + pub async fn tell_fortune(&self) -> HandleResult { + let mut items = Vec::with_capacity(32); + items.push(Fortune::new(0, "Additional fortune added at request time.")); + + let mut res = self.fortune.query(&self.cli).await?; + + while let Some(row) = res.try_next().await? { + items.push(Fortune::new(row.get(0), row.get::(1))); + } + + items.sort_by(|it, next| it.message.cmp(&next.message)); + + Ok(Fortunes::new(items)) + } +} + +fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator { + let mut params = params.to_owned(); + params.sort_by(|a, b| a[0].cmp(&b[0])); + + struct ParamIter(I); + + impl Iterator for ParamIter + where + I: Iterator, + { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + + // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring + // it's size hint. possible to cause runtime panic. + impl ExactSizeIterator for ParamIter where I: Iterator {} + + ParamIter(params.into_iter().flatten()) +} diff --git a/frameworks/Rust/xitca-web/src/main_iou.rs b/frameworks/Rust/xitca-web/src/main_iou.rs index 3aebffa7e1a..bad7094a3f0 100644 --- a/frameworks/Rust/xitca-web/src/main_iou.rs +++ b/frameworks/Rust/xitca-web/src/main_iou.rs @@ -6,6 +6,7 @@ #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +#[path = "db_unrealistic.rs"] mod db; mod ser; mod util; @@ -86,8 +87,10 @@ async fn handler(ctx: Ctx<'_, Request>) -> Result req.text_response().unwrap(), "/json" => req.json_response(state, &Message::new()).unwrap(), + // all database related categories are unrealistic. please reference db_unrealistic module for detail. "/db" => { - // unrealistic due to no error handling. any db/serialization error will cause process crash + // unrealistic due to no error handling. any db/serialization error will cause process crash. + // the same goes for all following unwraps on database related functions. let world = state.client.get_world().await.unwrap(); req.json_response(state, &world).unwrap() } From 6efb874c5477a28aba34cbba02a02ce75eb4bfc1 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Thu, 3 Oct 2024 16:18:27 +0800 Subject: [PATCH 8/9] dedup --- frameworks/Rust/xitca-web/src/db.rs | 63 +++--------------- .../Rust/xitca-web/src/db_unrealistic.rs | 64 +++---------------- frameworks/Rust/xitca-web/src/db_util.rs | 53 +++++++++++++++ 3 files changed, 69 insertions(+), 111 deletions(-) create mode 100644 frameworks/Rust/xitca-web/src/db_util.rs diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 75c70be21c8..ad75d6f8bbe 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,46 +1,29 @@ +#[path = "./db_util.rs"] +mod db_util; + use std::cell::RefCell; -use xitca_io::bytes::BytesMut; use xitca_postgres::{ - iter::AsyncLendingIterator, - pipeline::Pipeline, - pool::Pool, - statement::{Statement, StatementNamed}, - types::Type, - Execute, ExecuteMut, + iter::AsyncLendingIterator, pipeline::Pipeline, pool::Pool, statement::Statement, Execute, ExecuteMut, }; use super::{ ser::{Fortune, Fortunes, World}, - util::{bulk_update_gen, HandleResult, Rand, DB_URL}, + util::{HandleResult, DB_URL}, }; +use db_util::{sort_update_params, update_query, Shared, FORTUNE_STMT, WORLD_STMT}; + pub struct Client { pool: Pool, shared: RefCell, updates: Box<[Box]>, } -type Shared = (Rand, BytesMut); - -const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); -const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); - -fn update_query(num: usize) -> Box { - bulk_update_gen(|query| { - use std::fmt::Write; - (1..=num).fold((1, query), |(idx, query), _| { - write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); - (idx + 2, query) - }); - }) - .into_boxed_str() -} - pub async fn create() -> HandleResult { Ok(Client { pool: Pool::builder(DB_URL).capacity(1).build()?, - shared: RefCell::new((Rand::default(), BytesMut::new())), + shared: Default::default(), updates: core::iter::once(Box::from("")) .chain((1..=500).map(update_query)) .collect(), @@ -135,33 +118,3 @@ impl Client { Ok(Fortunes::new(items)) } } - -fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator { - let mut params = params.to_owned(); - params.sort_by(|a, b| a[0].cmp(&b[0])); - - struct ParamIter(I); - - impl Iterator for ParamIter - where - I: Iterator, - { - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } - } - - // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring - // it's size hint. possible to cause runtime panic. - impl ExactSizeIterator for ParamIter where I: Iterator {} - - ParamIter(params.into_iter().flatten()) -} diff --git a/frameworks/Rust/xitca-web/src/db_unrealistic.rs b/frameworks/Rust/xitca-web/src/db_unrealistic.rs index 838b097529c..7b04449a716 100644 --- a/frameworks/Rust/xitca-web/src/db_unrealistic.rs +++ b/frameworks/Rust/xitca-web/src/db_unrealistic.rs @@ -1,22 +1,20 @@ //! this module is unrealistic. related issue: //! https://github.com/TechEmpower/FrameworkBenchmarks/issues/8790 +#[path = "./db_util.rs"] +mod db_util; + use std::cell::RefCell; -use xitca_io::bytes::BytesMut; -use xitca_postgres::{ - iter::AsyncLendingIterator, - pipeline::Pipeline, - statement::{Statement, StatementNamed}, - types::Type, - Execute, ExecuteMut, -}; +use xitca_postgres::{iter::AsyncLendingIterator, pipeline::Pipeline, statement::Statement, Execute, ExecuteMut}; use super::{ ser::{Fortune, Fortunes, World}, - util::{bulk_update_gen, HandleResult, Rand, DB_URL}, + util::{HandleResult, DB_URL}, }; +use db_util::{sort_update_params, update_query, Shared, FORTUNE_STMT, WORLD_STMT}; + pub struct Client { cli: xitca_postgres::Client, shared: RefCell, @@ -25,22 +23,6 @@ pub struct Client { updates: Box<[Statement]>, } -type Shared = (Rand, BytesMut); - -const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); -const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); - -fn update_query(num: usize) -> Box { - bulk_update_gen(|query| { - use std::fmt::Write; - (1..=num).fold((1, query), |(idx, query), _| { - write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); - (idx + 2, query) - }); - }) - .into_boxed_str() -} - pub async fn create() -> HandleResult { let (cli, mut drv) = xitca_postgres::Postgres::new(DB_URL).connect().await?; @@ -61,7 +43,7 @@ pub async fn create() -> HandleResult { Ok(Client { cli, - shared: RefCell::new((Rand::default(), BytesMut::new())), + shared: Default::default(), world, fortune, updates: updates.into_boxed_slice(), @@ -146,33 +128,3 @@ impl Client { Ok(Fortunes::new(items)) } } - -fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator { - let mut params = params.to_owned(); - params.sort_by(|a, b| a[0].cmp(&b[0])); - - struct ParamIter(I); - - impl Iterator for ParamIter - where - I: Iterator, - { - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } - } - - // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring - // it's size hint. possible to cause runtime panic. - impl ExactSizeIterator for ParamIter where I: Iterator {} - - ParamIter(params.into_iter().flatten()) -} diff --git a/frameworks/Rust/xitca-web/src/db_util.rs b/frameworks/Rust/xitca-web/src/db_util.rs new file mode 100644 index 00000000000..19879333427 --- /dev/null +++ b/frameworks/Rust/xitca-web/src/db_util.rs @@ -0,0 +1,53 @@ +use xitca_io::bytes::BytesMut; +use xitca_postgres::{ + statement::{Statement, StatementNamed}, + types::Type, +}; + +use crate::util::{bulk_update_gen, Rand}; + +pub(super) type Shared = (Rand, BytesMut); + +pub(super) const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); +pub(super) const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); + +pub(super) fn update_query(num: usize) -> Box { + bulk_update_gen(|query| { + use std::fmt::Write; + (1..=num).fold((1, query), |(idx, query), _| { + write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); + (idx + 2, query) + }); + }) + .into_boxed_str() +} + +pub(super) fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator { + let mut params = params.to_owned(); + params.sort_by(|a, b| a[0].cmp(&b[0])); + + struct ParamIter(I); + + impl Iterator for ParamIter + where + I: Iterator, + { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + + // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring + // it's size hint. possible to cause runtime panic. + impl ExactSizeIterator for ParamIter where I: Iterator {} + + ParamIter(params.into_iter().flatten()) +} From fd5183b21ad3ff5a2fa5afbc3585544c83b650ea Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Thu, 3 Oct 2024 23:41:39 +0800 Subject: [PATCH 9/9] improve compile time --- frameworks/Rust/xitca-web/Cargo.lock | 76 ++-------------------------- frameworks/Rust/xitca-web/Cargo.toml | 2 +- frameworks/Rust/xitca-web/src/ser.rs | 37 +++++++++++--- 3 files changed, 37 insertions(+), 78 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index ef3dabd7db6..403825284f1 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -271,18 +271,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "fnv" version = "1.0.7" @@ -400,15 +388,6 @@ dependencies = [ "digest", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "http" version = "1.1.0" @@ -485,17 +464,6 @@ dependencies = [ "libc", ] -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall", -] - [[package]] name = "lock_api" version = "0.4.12" @@ -554,7 +522,7 @@ dependencies = [ "hermit-abi", "libc", "wasi", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -784,34 +752,9 @@ checksum = "d4d5cd6d4f24f3ab107e949ab424738cf55b03deddce3b184c46985d7b1394ef" dependencies = [ "itoap", "ryu", - "sailfish-macros", "version_check", ] -[[package]] -name = "sailfish-compiler" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7254ec7b3651f7f723a9073153f5dcddc1f2bf1bf8d1b23ac71c236ef6360d2b" -dependencies = [ - "filetime", - "home", - "memchr", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sailfish-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00812289fe1891c191cc2d9db461352fc410619e07ec2bb748faaa06412619d0" -dependencies = [ - "proc-macro2", - "sailfish-compiler", -] - [[package]] name = "scheduled-thread-pool" version = "0.2.7" @@ -945,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1011,7 +954,7 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1092,9 +1035,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -1248,15 +1191,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-targets" version = "0.52.6" diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 61b28d3ffb4..cc2e5e425ba 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -74,7 +74,7 @@ xitca-postgres-diesel = { version = "0.1", optional = true } futures-util = { version = "0.3", default-features = false, optional = true } # template optional -sailfish = { version = "0.9", default-features = false, features = ["derive", "perf-inline"], optional = true } +sailfish = { version = "0.9", default-features = false, features = ["perf-inline"], optional = true } # io-uring optional tokio-uring = { version = "0.5", optional = true } diff --git a/frameworks/Rust/xitca-web/src/ser.rs b/frameworks/Rust/xitca-web/src/ser.rs index e7a1de8a178..d00cdf6c956 100644 --- a/frameworks/Rust/xitca-web/src/ser.rs +++ b/frameworks/Rust/xitca-web/src/ser.rs @@ -62,16 +62,41 @@ impl Fortune { } } -// TODO: use another template engine with faster compile time.(preferably with no proc macro) -#[cfg_attr( - feature = "template", - derive(sailfish::TemplateOnce), - template(path = "fortune.stpl", rm_whitespace = true) -)] pub struct Fortunes { items: Vec, } +// this is roughly the code generated by sailfish::TemplateOnce macro. +// using the macro does not have any perf cost and this piece of code is expanded manually to speed up compile time of +// bench to reduce resource usage of bench runner +#[cfg(feature = "template")] +impl sailfish::TemplateOnce for Fortunes { + fn render_once(self) -> sailfish::RenderResult { + use sailfish::runtime::{Buffer, Render}; + + const PREFIX: &str = "\n\nFortunes\n\n\n\n"; + const SUFFIX: &str = "\n
idmessage
\n\n"; + + let mut buf = Buffer::with_capacity(2048); + + buf.push_str(PREFIX); + for item in self.items { + buf.push_str(""); + Render::render_escaped(&item.id, &mut buf)?; + buf.push_str(""); + Render::render_escaped(&item.message, &mut buf)?; + buf.push_str(""); + } + buf.push_str(SUFFIX); + + Ok(buf.into_string()) + } + + fn render_once_to(self, _: &mut sailfish::runtime::Buffer) -> Result<(), sailfish::runtime::RenderError> { + unimplemented!("") + } +} + impl Fortunes { #[inline] pub const fn new(items: Vec) -> Self {