Skip to content

Commit baa5842

Browse files
authored
[xitca-web] add sync bench. (#8661)
* [xitca-web] add sync bench. * fix wasm build. * add url encode deserialize impl. * update axum. * update dep. reduce loc. * remove toolchain patch. * fix wasm build.
1 parent 04c882e commit baa5842

19 files changed

+784
-305
lines changed

frameworks/Rust/xitca-web/Cargo.lock

Lines changed: 365 additions & 113 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frameworks/Rust/xitca-web/Cargo.toml

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,32 @@ name = "xitca-web-axum"
2323
path = "./src/main_axum.rs"
2424
required-features = ["axum", "io-uring", "pg-sync", "template"]
2525

26+
[[bin]]
27+
name = "xitca-web-sync"
28+
path = "./src/main_sync.rs"
29+
required-features = ["pg-orm", "template", "web-codegen"]
30+
2631
[features]
2732
# pg optional
2833
pg = ["xitca-postgres/single-thread"]
2934
# pg send/sync optional
3035
pg-sync = ["xitca-postgres"]
3136
# pg io_uring optional
3237
pg-iou = ["pg", "xitca-postgres/io-uring"]
38+
# pg orm optional
39+
pg-orm = ["diesel"]
3340
# http router optional
3441
router = ["xitca-http/router"]
3542
# web optional
3643
web = ["xitca-web"]
44+
# web codegen optional
45+
web-codegen = ["xitca-web/codegen", "xitca-web/urlencoded"]
3746
# template optional
3847
template = ["sailfish"]
3948
# io-uring optional
4049
io-uring = ["xitca-http/io-uring", "xitca-server/io-uring"]
4150
# axum optional
42-
axum = ["dep:axum", "http-body", "pin-project-lite", "tower", "tower-http"]
51+
axum = ["dep:axum", "http-body", "tower", "tower-http", "xitca-web/tower-http-compat" ]
4352

4453
[dependencies]
4554
xitca-http = "0.1"
@@ -58,20 +67,21 @@ xitca-web = { version = "0.1", features = ["json"], optional = true }
5867
# raw-pg optional
5968
xitca-postgres = { version = "0.1", optional = true }
6069

70+
# orm optional
71+
diesel = { version = "2", features = ["postgres", "r2d2"], optional = true }
72+
6173
# template optional
6274
sailfish = { version = "0.8", default-features = false, features = ["derive", "perf-inline"], optional = true }
6375

6476
# axum optional
65-
axum = { version = "0.6", optional = true }
66-
http-body = { version = "0.4", optional = true }
67-
pin-project-lite = { version = "0.2", optional = true }
77+
axum = { version = "0.7", optional = true }
78+
http-body = { version = "1", optional = true }
6879
tower = { version = "0.4", optional = true }
69-
tower-http = { version = "0.4", features = ["set-header"], optional = true }
80+
tower-http = { version = "0.5", features = ["set-header"], optional = true }
7081

7182
# stuff can not be used or not needed in wasi target
7283
[target.'cfg(not(target_family = "wasm"))'.dependencies]
7384
futures-core = { version = "0.3", default-features = false }
74-
mimalloc = { version = "0.1", default-features = false }
7585
nanorand = { version = "0.7", default-features = false, features = ["tls"] }
7686
tokio = "1"
7787

@@ -82,13 +92,5 @@ codegen-units = 1
8292
panic = "abort"
8393

8494
[patch.crates-io]
85-
xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
86-
xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
87-
xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
88-
xitca-router = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
89-
xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
90-
xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
91-
xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
92-
xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" }
93-
95+
xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "d79f510197e0f36534fe22b7a467c55dbd683681" }
9496
mio = { git = "https://github.com/fakeshadow/mio.git", rev = "52b72d372bfe5807755b7f5e3e1edf282954d6ba" }

frameworks/Rust/xitca-web/benchmark_config.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@
8585
"display_name": "axum [xitca]",
8686
"notes": "",
8787
"versus": ""
88+
},
89+
"sync": {
90+
"json_url": "/json",
91+
"plaintext_url": "/plaintext",
92+
"db_url": "/db",
93+
"fortune_url": "/fortunes",
94+
"query_url": "/queries?q=",
95+
"update_url": "/updates?q=",
96+
"port": 8080,
97+
"approach": "realistic",
98+
"classification": "micro",
99+
"database": "postgres",
100+
"framework": "xitca-web [sync]",
101+
"language": "rust",
102+
"orm": "full",
103+
"platform": "none",
104+
"webserver": "xitca-server",
105+
"os": "linux",
106+
"database_os": "linux",
107+
"display_name": "xitca-web [sync]",
108+
"notes": "",
109+
"versus": ""
88110
}
89111
}
90112
]

frameworks/Rust/xitca-web/rust-toolchain.toml

Lines changed: 0 additions & 2 deletions
This file was deleted.

frameworks/Rust/xitca-web/src/db.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::{collections::HashMap, fmt::Write, future::IntoFuture};
22

3-
use xitca_postgres::{statement::Statement, AsyncIterator, Postgres};
3+
use xitca_postgres::{statement::Statement, AsyncLendingIterator, Postgres};
44
use xitca_unsafe_collection::no_hash::NoHashBuilder;
55

66
use super::{
77
ser::{Fortune, Fortunes, World},
8-
util::{HandleResult, Rand},
8+
util::{HandleResult, Rand, DB_URL},
99
};
1010

1111
pub struct Client {
@@ -29,8 +29,8 @@ impl Drop for Client {
2929
}
3030
}
3131

32-
pub async fn create(config: &str) -> HandleResult<Client> {
33-
let (client, driver) = Postgres::new(config.to_string()).connect().await?;
32+
pub async fn create() -> HandleResult<Client> {
33+
let (client, driver) = Postgres::new(DB_URL.to_string()).connect().await?;
3434

3535
tokio::spawn(tokio::task::unconstrained(driver.into_future()));
3636

@@ -91,11 +91,10 @@ impl Client {
9191
self.client
9292
.query_raw(&self.world, [id])
9393
.await?
94-
.next()
95-
.await
96-
.ok_or_else(|| format!("World {id} does not exist"))?
94+
.try_next()
95+
.await?
9796
.map(|row| World::new(row.get_raw(0), row.get_raw(1)))
98-
.map_err(Into::into)
97+
.ok_or_else(|| format!("World does not exist").into())
9998
}
10099

101100
pub async fn get_worlds(&self, num: u16) -> HandleResult<Vec<World>> {
@@ -110,8 +109,8 @@ impl Client {
110109
worlds.reserve(num as usize);
111110

112111
let mut res = pipe.run().await?;
113-
while let Some(mut item) = res.next().await.transpose()? {
114-
while let Some(row) = item.next().await.transpose()? {
112+
while let Some(mut item) = res.try_next().await? {
113+
while let Some(row) = item.try_next().await? {
115114
worlds.push(World::new(row.get_raw(0), row.get_raw(1)))
116115
}
117116
}
@@ -146,8 +145,8 @@ impl Client {
146145
let mut r_ids = params.into_iter().skip(1).step_by(2);
147146

148147
let mut res = pipe.run().await?;
149-
while let Some(mut item) = res.next().await.transpose()? {
150-
while let Some(row) = item.next().await.transpose()? {
148+
while let Some(mut item) = res.try_next().await? {
149+
while let Some(row) = item.try_next().await? {
151150
let r_id = r_ids.next().unwrap();
152151
worlds.push(World::new(row.get_raw(0), r_id))
153152
}
@@ -161,7 +160,7 @@ impl Client {
161160
items.push(Fortune::new(0, "Additional fortune added at request time."));
162161

163162
let mut stream = self.client.query_raw::<[i32; 0]>(&self.fortune, []).await?;
164-
while let Some(row) = stream.next().await.transpose()? {
163+
while let Some(row) = stream.try_next().await? {
165164
items.push(Fortune::new(row.get_raw(0), row.get_raw::<String>(1)));
166165
}
167166
items.sort_by(|it, next| it.message.cmp(&next.message));
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use std::sync::{Arc, Mutex};
2+
3+
use diesel::{prelude::*, r2d2};
4+
5+
use crate::{
6+
ser::{Fortune, Fortunes, World},
7+
util::{Error, HandleResult, Rand, DB_URL},
8+
};
9+
10+
pub type Pool = Arc<_Pool>;
11+
12+
pub struct _Pool {
13+
pool: r2d2::Pool<r2d2::ConnectionManager<PgConnection>>,
14+
rng: Mutex<Rand>,
15+
}
16+
17+
pub fn create() -> std::io::Result<Arc<_Pool>> {
18+
r2d2::Builder::new()
19+
.max_size(256)
20+
.min_idle(Some(256))
21+
.test_on_check_out(false)
22+
.idle_timeout(None)
23+
.max_lifetime(None)
24+
.build(r2d2::ConnectionManager::new(DB_URL))
25+
.map_err(std::io::Error::other)
26+
.map(|pool| {
27+
Arc::new(_Pool {
28+
pool,
29+
rng: Mutex::new(Rand::default()),
30+
})
31+
})
32+
}
33+
34+
#[cold]
35+
#[inline(never)]
36+
fn not_found() -> Error {
37+
format!("world not found").into()
38+
}
39+
40+
impl _Pool {
41+
pub fn get_world(&self) -> HandleResult<World> {
42+
use crate::schema::world::dsl::*;
43+
44+
let w_id = self.rng.lock().unwrap().gen_id();
45+
let mut conn = self.pool.get()?;
46+
world
47+
.filter(id.eq(w_id))
48+
.load(&mut conn)?
49+
.pop()
50+
.ok_or_else(not_found)
51+
}
52+
53+
pub fn get_worlds(&self, num: u16) -> HandleResult<Vec<World>> {
54+
use crate::schema::world::dsl::*;
55+
56+
let mut conn = self.pool.get()?;
57+
(0..num)
58+
.map(|_| {
59+
let w_id = self.rng.lock().unwrap().gen_id();
60+
world
61+
.filter(id.eq(w_id))
62+
.load::<World>(&mut conn)?
63+
.pop()
64+
.ok_or_else(not_found)
65+
})
66+
.collect()
67+
}
68+
69+
pub fn update(&self, num: u16) -> HandleResult<Vec<World>> {
70+
use crate::schema::world::dsl::*;
71+
72+
let mut worlds = {
73+
let mut conn = self.pool.get()?;
74+
let worlds = (0..num)
75+
.map(|_| {
76+
let mut rng = self.rng.lock().unwrap();
77+
let w_id = rng.gen_id();
78+
let r_id = rng.gen_id();
79+
drop(rng);
80+
world
81+
.filter(id.eq(w_id))
82+
.load::<World>(&mut conn)?
83+
.pop()
84+
.map(|mut w| {
85+
w.randomnumber = r_id;
86+
w
87+
})
88+
.ok_or_else(not_found)
89+
})
90+
.collect::<HandleResult<Vec<_>>>()?;
91+
92+
worlds.iter().try_for_each(|w| {
93+
diesel::update(world)
94+
.filter(id.eq(w.id))
95+
.set(randomnumber.eq(w.randomnumber))
96+
.execute(&mut conn)
97+
.map(|_| ())
98+
})?;
99+
100+
worlds
101+
};
102+
103+
worlds.sort_by_key(|w| w.id);
104+
105+
Ok(worlds)
106+
}
107+
108+
pub fn tell_fortune(&self) -> HandleResult<Fortunes> {
109+
use crate::schema::fortune::dsl::*;
110+
111+
let mut items = {
112+
let mut conn = self.pool.get()?;
113+
fortune.load::<Fortune>(&mut conn)?
114+
};
115+
116+
items.push(Fortune::new(0, "Additional fortune added at request time."));
117+
items.sort_by(|it, next| it.message.cmp(&next.message));
118+
119+
Ok(Fortunes::new(items))
120+
}
121+
}

frameworks/Rust/xitca-web/src/main.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
#[global_allocator]
2-
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
3-
41
mod db;
52
mod ser;
63
mod util;
@@ -20,14 +17,12 @@ use xitca_http::{
2017
};
2118
use xitca_service::{fn_service, Service, ServiceExt};
2219

23-
use self::{
24-
ser::{json_response, Message},
25-
util::{context_mw, HandleResult, QueryParse, SERVER_HEADER_VALUE},
26-
};
20+
use ser::{json_response, Message};
21+
use util::{context_mw, HandleResult, QueryParse, SERVER_HEADER_VALUE};
2722

28-
type Response = http::Response<Once<Bytes>>;
2923
type Request = http::Request<RequestExt<RequestBody>>;
30-
type Ctx<'a> = self::util::Ctx<'a, Request>;
24+
type Response = http::Response<Once<Bytes>>;
25+
type Ctx<'a> = util::Ctx<'a, Request>;
3126

3227
fn main() -> std::io::Result<()> {
3328
let service = Router::new()
@@ -40,7 +35,6 @@ fn main() -> std::io::Result<()> {
4035
.enclosed_fn(middleware_fn)
4136
.enclosed(context_mw())
4237
.enclosed(HttpServiceBuilder::h1().io_uring());
43-
4438
xitca_server::Builder::new()
4539
.bind("xitca-web", "0.0.0.0:8080", service)?
4640
.build()

0 commit comments

Comments
 (0)