Skip to content

Commit 996962f

Browse files
authored
[xitca-web] enable more optimization (#10360)
* [xitca-web] enable more optimization * remove all usage of explict pipeline * dep update * update toasty to support cow<str> * dep dedup * dep update * improve compile time * improve compile time
1 parent 6fc55b0 commit 996962f

18 files changed

+347
-485
lines changed

frameworks/Rust/xitca-web/Cargo.lock

Lines changed: 187 additions & 280 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: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ edition = "2024"
66
[[bin]]
77
name = "xitca-web"
88
path = "./src/main.rs"
9-
required-features = ["io-uring", "pg", "router", "template"]
9+
required-features = ["io-uring", "json", "pg", "router", "template"]
1010

1111
[[bin]]
12-
name = "xitca-web-unrealistic"
13-
path = "./src/main_unrealistic.rs"
14-
required-features = ["perf", "pg", "template"]
12+
name = "xitca-web-barebone"
13+
path = "./src/main_barebone.rs"
14+
required-features = ["perf", "perf-json", "pg", "template"]
1515

1616
[[bin]]
1717
name = "xitca-web-diesel"
1818
path = "./src/main_orm.rs"
19-
required-features = ["diesel", "template", "web-codegen"]
19+
required-features = ["diesel", "perf", "template", "web-codegen"]
2020

2121
[[bin]]
2222
name = "xitca-web-toasty"
2323
path = "./src/main_orm.rs"
24-
required-features = ["toasty", "template", "web-codegen"]
24+
required-features = ["perf", "template", "toasty", "web-codegen"]
2525

2626
[features]
2727
# pg client optional
@@ -41,7 +41,11 @@ template = ["dep:sailfish"]
4141
# io-uring optional
4242
io-uring = ["dep:tokio-uring", "xitca-http/io-uring", "xitca-server/io-uring"]
4343
# unrealistic performance optimization
44-
perf = ["dep:core_affinity", "dep:mimalloc", "tokio/parking_lot", "simd-json", "simd-json-derive"]
44+
perf = ["dep:core_affinity", "dep:mimalloc", "tokio/parking_lot"]
45+
# regular json serializer
46+
json = ["serde_json"]
47+
# performance optimization json serializer
48+
perf-json = ["sonic-rs"]
4549

4650
[dependencies]
4751
xitca-http = "0.7"
@@ -52,8 +56,7 @@ xitca-unsafe-collection = "0.2"
5256

5357
atoi = "2"
5458
httparse = "1"
55-
serde = { version = "1" }
56-
serde_json = { version = "1" }
59+
serde_core = { version = "1" }
5760

5861
# web optional
5962
xitca-web = { version = "0.7", features = ["json"], optional = true }
@@ -63,7 +66,7 @@ xitca-postgres = { version = "0.3", optional = true }
6366

6467
# diesel orm optional
6568
diesel = { version = "2", features = ["postgres"], optional = true }
66-
diesel-async = { version = "0.7", features = ["bb8", "postgres"], optional = true }
69+
diesel-async = { version = "0.7", optional = true }
6770
xitca-postgres-diesel = { version = "0.2", default-features = false, optional = true }
6871
futures-util = { version = "0.3", default-features = false, optional = true }
6972

@@ -80,12 +83,14 @@ tokio-uring = { version = "0.5", optional = true }
8083
# perf optional
8184
core_affinity = { version = "0.8.1", optional = true }
8285
mimalloc = { version = "0.1", default-features = false, optional = true }
83-
simd-json = { version = "0.17", optional = true }
84-
simd-json-derive = { version = "0.18", default-features = false, optional = true }
86+
87+
# json optioanl
88+
serde_json = { version = "1", optional = true }
89+
sonic-rs = { version = "0.5.6", optional = true }
8590

8691
futures-core = { version = "0.3", default-features = false }
8792
rand = { version = "0.9", features = ["os_rng", "small_rng"], default-features = false }
88-
tokio = "1.41"
93+
tokio = "1.48"
8994

9095
[profile.release]
9196
lto = true
@@ -94,17 +99,18 @@ codegen-units = 1
9499
panic = "abort"
95100

96101
[patch.crates-io]
97-
xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "7671975" }
102+
xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "fb5dcba" }
98103
xitca-postgres-toasty = { git = "https://github.com/fakeshadow/xitca-postgres-toasty", rev = "04bedb8" }
99104

100105
# personal fork for efficient toasty engine fine tuned with pipelined xitca-postgres client
101106
toasty = { git = "https://github.com/fakeshadow/toasty", branch = "engine" }
102107
toasty-core = { git = "https://github.com/fakeshadow/toasty", branch = "engine" }
103108
toasty-sql = { git = "https://github.com/fakeshadow/toasty", branch = "engine" }
104-
105-
xitca-codegen = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
106-
xitca-http = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
107-
xitca-postgres = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
108-
xitca-server = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
109-
xitca-service = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
110-
xitca-web = { git = "http://github.com/HFQR/xitca-web", rev = "cf70ed7" }
109+
tokio-uring = { git = "http://github.com/fakeshadow/tokio-uring", rev = "97d9a98" }
110+
111+
xitca-codegen = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }
112+
xitca-http = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }
113+
xitca-postgres = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }
114+
xitca-server = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }
115+
xitca-service = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }
116+
xitca-web = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" }

frameworks/Rust/xitca-web/benchmark_config.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@
2424
"notes": "",
2525
"versus": ""
2626
},
27-
"unrealistic": {
27+
"barebone": {
2828
"json_url": "/json",
2929
"plaintext_url": "/plaintext",
3030
"db_url": "/db",
3131
"fortune_url": "/fortunes",
3232
"query_url": "/queries?q=",
3333
"update_url": "/updates?q=",
3434
"port": 8080,
35-
"approach": "Stripped",
35+
"approach": "Realistic",
3636
"classification": "Platform",
3737
"database": "Postgres",
3838
"framework": "xitca-web",
@@ -42,7 +42,7 @@
4242
"webserver": "xitca-server",
4343
"os": "Linux",
4444
"database_os": "Linux",
45-
"display_name": "xitca-web [unrealistic]",
45+
"display_name": "xitca-web [barebone]",
4646
"notes": "",
4747
"versus": ""
4848
},

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

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
#[path = "./db_util.rs"]
22
mod db_util;
33

4-
use core::cell::RefCell;
5-
6-
use xitca_postgres::{Execute, iter::AsyncLendingIterator, pipeline::Pipeline, pool::Pool};
4+
use xitca_postgres::{Execute, iter::AsyncLendingIterator, pool::Pool};
75

86
use super::{
97
ser::{Fortune, Fortunes, World},
10-
util::{DB_URL, HandleResult},
8+
util::{DB_URL, HandleResult, Rand},
119
};
1210

13-
use db_util::{FORTUNE_STMT, Shared, UPDATE_STMT, WORLD_STMT, not_found};
11+
use db_util::{FORTUNE_STMT, UPDATE_STMT, WORLD_STMT, not_found};
1412

1513
pub struct Client {
1614
pool: Pool,
17-
shared: RefCell<Shared>,
15+
rng: core::cell::RefCell<Rand>,
1816
}
1917

2018
pub async fn create() -> HandleResult<Client> {
2119
Ok(Client {
2220
pool: Pool::builder(DB_URL).capacity(1).build()?,
23-
shared: Default::default(),
21+
rng: Default::default(),
2422
})
2523
}
2624

2725
impl Client {
2826
pub async fn get_world(&self) -> HandleResult<World> {
2927
let mut conn = self.pool.get().await?;
3028
let stmt = WORLD_STMT.execute(&mut conn).await?;
31-
let id = self.shared.borrow_mut().0.gen_id();
29+
let id = self.rng.borrow_mut().gen_id();
3230
let mut res = stmt.bind([id]).query(&conn.consume()).await?;
3331
let row = res.try_next().await?.ok_or_else(not_found)?;
3432
Ok(World::new(row.get(0), row.get(1)))
@@ -38,19 +36,21 @@ impl Client {
3836
let mut conn = self.pool.get().await?;
3937
let stmt = WORLD_STMT.execute(&mut conn).await?;
4038

41-
let mut res = {
42-
let (ref mut rng, ref mut buf) = *self.shared.borrow_mut();
43-
let mut pipe = Pipeline::with_capacity_from_buf(num as _, buf);
44-
rng.gen_multi()
45-
.take(num as _)
46-
.try_for_each(|id| stmt.bind([id]).query(&mut pipe))?;
47-
pipe.query(&conn.consume())?
48-
};
39+
let get = self
40+
.rng
41+
.borrow_mut()
42+
.gen_multi()
43+
.take(num as _)
44+
.map(|id| stmt.bind([id]).query(&conn))
45+
.collect::<Vec<_>>();
46+
47+
drop(conn);
4948

5049
let mut worlds = Vec::with_capacity(num as _);
5150

52-
while let Some(mut item) = res.try_next().await? {
53-
let row = item.try_next().await?.ok_or_else(not_found)?;
51+
for get in get {
52+
let mut res = get.await?;
53+
let row = res.try_next().await?.ok_or_else(not_found)?;
5454
worlds.push(World::new(row.get(0), row.get(1)));
5555
}
5656

@@ -62,32 +62,32 @@ impl Client {
6262
let world_stmt = WORLD_STMT.execute(&mut conn).await?;
6363
let update_stmt = UPDATE_STMT.execute(&mut conn).await?;
6464

65-
let (mut res, worlds) = {
66-
let (ref mut rng, ref mut buf) = *self.shared.borrow_mut();
67-
let mut pipe = Pipeline::with_capacity_from_buf((num + 1) as _, buf);
68-
65+
let (get, update, worlds) = {
66+
let mut rng = self.rng.borrow_mut();
6967
let mut ids = rng.gen_multi().take(num as _).collect::<Vec<_>>();
7068
ids.sort();
7169

72-
let (rngs, worlds) = ids
70+
let (get, rngs, worlds) = ids
7371
.iter()
7472
.cloned()
7573
.zip(rng.gen_multi())
7674
.map(|(id, rand)| {
77-
world_stmt.bind([id]).query(&mut pipe)?;
78-
HandleResult::Ok((rand, World::new(id, rand)))
75+
let get = world_stmt.bind([id]).query(&conn);
76+
(get, rand, World::new(id, rand))
7977
})
80-
.collect::<HandleResult<(Vec<_>, Vec<_>)>>()?;
81-
update_stmt.bind([&ids, &rngs]).query(&mut pipe)?;
82-
(pipe.query(&conn.consume())?, worlds)
78+
.collect::<(Vec<_>, Vec<_>, Vec<_>)>();
79+
80+
let update = update_stmt.bind([&ids, &rngs]).query(&conn.consume());
81+
82+
(get, update, worlds)
8383
};
8484

85-
while let Some(mut item) = res.try_next().await? {
86-
while let Some(row) = item.try_next().await? {
87-
let _rand = row.get::<i32>(1);
88-
}
85+
for fut in get {
86+
let _rand = fut.await?.try_next().await?.ok_or_else(not_found)?.get::<i32>(1);
8987
}
9088

89+
update.await?;
90+
9191
Ok(worlds)
9292
}
9393

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

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use diesel::prelude::*;
2-
use diesel_async::{
3-
RunQueryDsl,
4-
pooled_connection::{AsyncDieselConnectionManager, bb8},
5-
};
2+
use diesel_async::{AsyncConnection, RunQueryDsl};
63
use futures_util::future::{TryFutureExt, TryJoinAll, try_join};
74
use xitca_postgres_diesel::AsyncPgConnection;
85

@@ -12,18 +9,13 @@ use crate::{
129
};
1310

1411
pub struct Pool {
15-
pool: bb8::Pool<AsyncPgConnection>,
12+
pool: AsyncPgConnection,
1613
rng: core::cell::RefCell<Rand>,
1714
}
1815

1916
impl Pool {
2017
pub async fn create() -> HandleResult<Self> {
21-
let pool = bb8::Pool::builder()
22-
.max_size(1)
23-
.min_idle(Some(1))
24-
.test_on_check_out(false)
25-
.build(AsyncDieselConnectionManager::new(DB_URL))
26-
.await?;
18+
let pool = AsyncPgConnection::establish(DB_URL).await?;
2719

2820
Ok(Self {
2921
pool,
@@ -36,8 +28,7 @@ impl Pool {
3628
use schema::world::dsl::*;
3729

3830
let w_id = self.rng.borrow_mut().gen_id();
39-
let mut conn = self.pool.get().await?;
40-
world.filter(id.eq(w_id)).first(&mut conn).map_err(Into::into)
31+
world.filter(id.eq(w_id)).first(&mut &self.pool).map_err(Into::into)
4132
}
4233
.await
4334
}
@@ -46,12 +37,11 @@ impl Pool {
4637
{
4738
use schema::world::dsl::*;
4839

49-
let mut conn = self.pool.get().await?;
5040
self.rng
5141
.borrow_mut()
5242
.gen_multi()
5343
.take(num as _)
54-
.map(|w_id| world.filter(id.eq(w_id)).first(&mut conn).map_err(Into::into))
44+
.map(|w_id| world.filter(id.eq(w_id)).first(&mut &self.pool).map_err(Into::into))
5545
.collect::<TryJoinAll<_>>()
5646
}
5747
.await
@@ -61,7 +51,6 @@ impl Pool {
6151
{
6252
use schema::world::dsl::*;
6353

64-
let mut conn = self.pool.get().await?;
6554
let mut rng = self.rng.borrow_mut();
6655
let mut params = Vec::with_capacity(num as _);
6756

@@ -71,7 +60,7 @@ impl Pool {
7160
.take(num as _)
7261
.zip(rng.gen_multi())
7362
.map(|(w_id, rng)| {
74-
let get = world.filter(id.eq(w_id)).first::<World>(&mut conn);
63+
let get = world.filter(id.eq(w_id)).first::<World>(&mut &self.pool);
7564

7665
params.push((w_id, rng));
7766

@@ -84,7 +73,7 @@ impl Pool {
8473
.collect::<TryJoinAll<_>>();
8574

8675
let sql = update_query_from_ids(params);
87-
let update = diesel::sql_query(sql).execute(&mut conn).map_err(Into::into);
76+
let update = diesel::sql_query(sql).execute(&mut &self.pool).map_err(Into::into);
8877

8978
try_join(get, update)
9079
}
@@ -96,8 +85,7 @@ impl Pool {
9685
{
9786
use schema::fortune::dsl::*;
9887

99-
let mut conn = self.pool.get().await?;
100-
fortune.load(&mut conn).map_err(Into::into)
88+
fortune.load(&mut &self.pool).map_err(Into::into)
10189
}
10290
.await
10391
.map(Fortunes::new)

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::{
66
util::{DB_URL, HandleResult, Rand},
77
};
88

9-
// this is not a realistic connection pool.
109
pub struct Pool {
1110
db: Db,
1211
rng: core::cell::RefCell<Rand>,

0 commit comments

Comments
 (0)