Răsfoiți Sursa

update diesel_async. speed up compile time. (#7478)

fakeshadow 3 ani în urmă
părinte
comite
5ada172e00

+ 43 - 17
frameworks/Rust/xitca-web/Cargo.toml

@@ -6,31 +6,56 @@ edition = "2021"
 [[bin]]
 name = "xitca-web"
 path = "./src/main.rs"
+required-features = ["raw", "simd"]
 
 [[bin]]
 name = "xitca-web-diesel"
 path = "./src/main_diesel.rs"
+required-features = ["orm", "serde", "web"]
+
+[features]
+# raw-pg optional
+raw = ["xitca-postgres"]
+# diesel-pg orm optional
+orm = ["diesel", "diesel-async"]
+# simd-json optional
+simd = ["simd-json", "simd-json-derive"]
+# serde optional
+serde = ["dep:serde"]
+# web optional
+web = ["xitca-web"]
 
 [dependencies]
 xitca-http = { version = "0.1", features = ["util-service"] }
 xitca-server = "0.1"
 xitca-service = "0.1"
-xitca-web = { version = "0.1", features = ["json"] }
-xitca-postgres = "0.1"
 xitca-unsafe-collection = "0.1"
 
 atoi = "1.0.0"
 core_affinity = "0.5.10"
-diesel = { version = "2.0.0-rc.0", default-features = false, features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes"]}
-diesel-async = { version = "0.1.0", features = ["postgres"], default-features = false }
 futures-util = { version = "0.3.18", default-features = false, features = ["alloc"] }
 mimalloc = { version = "0.1.29", default-features = false }
 rand = { version = "0.8.5", default-features = false, features = ["min_const_gen", "nightly", "small_rng"] }
-sailfish = "0.3.4"
-serde = "1"
-simd-json = { version = "0.4.15", features = ["hints", "known-key"] }
+sailfish = "0.4"
 tang-rs = "0.2"
-tokio = { version = "1.18.0", features = ["macros", "rt"] }
+tokio = "1.20"
+
+# web optional
+xitca-web = { version = "0.1", features = ["json"], optional = true }
+
+# raw-pg optional
+xitca-postgres = { version = "0.1", default-features = false, features = ["single-thread"], optional = true }
+
+# diesel-pg orm optional
+diesel = { version = "2.0.0-rc.0", default-features = false, features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes"], optional = true }
+diesel-async = { version = "0.1.0", default-features = false, features = ["postgres"], optional = true }
+
+# simd-json optional
+simd-json = { version = "0.6", default-features = false, features = ["swar-number-parsing", "hints"], optional = true }
+simd-json-derive = { version = "0.4", default-features = false, optional = true }
+
+# serde optional
+serde = { version = "1", features = ["derive"], optional = true }
 
 [profile.release]
 lto = true
@@ -39,12 +64,13 @@ codegen-units = 1
 panic = "abort"
 
 [patch.crates-io]
-xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "bcfd33345a77a2e4b291633af9fa340ca6d5f524" }
-
-diesel-async = { git = "https://github.com/weiznich/diesel_async.git", rev = "d74eefd18b7e738b02aa2fa5f8bfd934b1d4db95" }
+xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "4fd97d4bd906995c3a70a50c33fc8ac076693e97" }
+
+diesel = { git = "https://github.com/diesel-rs/diesel.git", rev = "53a4157776d4320fffc11fe73779cc53702843d6" }
+diesel-async = { git = "https://github.com/weiznich/diesel_async.git", rev = "3c9e976c1c30d3aa3d0751b89f72b2ce43869c4f" }

+ 31 - 40
frameworks/Rust/xitca-web/src/db_diesel.rs

@@ -111,12 +111,12 @@ pub async fn create(config: &str) -> io::Result<DieselPool> {
 
 impl DieselPool {
     pub async fn get_world(&self) -> DbResult<World> {
+        use crate::schema::world::dsl::*;
+
         let mut conn = self.pool.get().await?;
 
         let random_id = self.rng.borrow_mut().gen_range(1..10_001);
 
-        use crate::schema::world::dsl::*;
-
         let w = world
             .filter(id.eq(random_id))
             .load::<World>(&mut *conn)
@@ -128,24 +128,19 @@ impl DieselPool {
     }
 
     pub async fn get_worlds(&self, num: u16) -> DbResult<Vec<World>> {
+        use crate::schema::world::dsl::*;
+
         let worlds = {
+            let mut conn = self.pool.get().await?;
+
             let mut rng = self.rng.borrow_mut();
             (0..num)
                 .map(|_| {
                     let w_id = (rng.gen::<u32>() % 10_000 + 1) as i32;
+                    let fut = world.filter(id.eq(w_id)).load::<World>(&mut *conn);
 
-                    async move {
-                        let mut conn = self.pool.get().await?;
-
-                        use crate::schema::world::dsl::*;
-
-                        let w = world
-                            .filter(id.eq(w_id))
-                            .load::<World>(&mut *conn)
-                            .await?
-                            .pop()
-                            .unwrap();
-
+                    async {
+                        let w = fut.await?.pop().unwrap();
                         Ok(w)
                     }
                 })
@@ -159,24 +154,19 @@ impl DieselPool {
         use crate::schema::world::dsl::*;
 
         let worlds = {
+            let mut conn = self.pool.get().await?;
+
             let mut rng = self.rng.borrow_mut();
             (0..num)
                 .map(|_| {
                     let w_id = rng.gen_range::<i32, _>(1..10_001);
                     let new_id = rng.gen_range::<i32, _>(1..10_001);
 
-                    async move {
-                        let mut conn = self.pool.get().await?;
-
-                        let mut w = world
-                            .filter(id.eq(w_id))
-                            .load::<World>(&mut *conn)
-                            .await?
-                            .pop()
-                            .unwrap();
+                    let fut = world.filter(id.eq(w_id)).load::<World>(&mut *conn);
 
+                    async move {
+                        let mut w = fut.await?.pop().unwrap();
                         w.randomnumber = new_id;
-
                         DbResult::Ok(w)
                     }
                 })
@@ -187,28 +177,29 @@ impl DieselPool {
 
         worlds.sort_by_key(|w| w.id);
 
-        let mut conn = self.pool.get().await?;
-
-        conn.transaction(move |conn| {
-            Box::pin(async move {
-                for w in &worlds {
-                    diesel::update(world)
-                        .filter(id.eq(w.id))
-                        .set(randomnumber.eq(w.randomnumber))
-                        .execute(conn)
-                        .await?;
-                }
-                Ok(worlds)
+        self.pool
+            .get()
+            .await?
+            .transaction(move |conn| {
+                Box::pin(async move {
+                    for w in &worlds {
+                        diesel::update(world)
+                            .filter(id.eq(w.id))
+                            .set(randomnumber.eq(w.randomnumber))
+                            .execute(conn)
+                            .await?;
+                    }
+                    Ok(worlds)
+                })
             })
-        })
-        .await
+            .await
     }
 
     pub async fn tell_fortune(&self) -> DbResult<Fortunes> {
-        let mut conn = self.pool.get().await?;
-
         use crate::schema::fortune::dsl::*;
 
+        let mut conn = self.pool.get().await?;
+
         let mut items = fortune.load::<Fortune>(&mut *conn).await?;
 
         items.push(Fortune::new(0, "Additional fortune added at request time."));

+ 23 - 44
frameworks/Rust/xitca-web/src/main.rs

@@ -6,13 +6,14 @@ mod ser;
 mod util;
 
 use std::{
-    cell::{RefCell, RefMut},
+    cell::RefCell,
     convert::Infallible,
     error::Error,
     fmt::Debug,
     sync::{Arc, Mutex},
 };
 
+use simd_json_derive::Serialize;
 use xitca_http::{
     body::Once,
     bytes::{BufMutWriter, Bytes, BytesMut},
@@ -68,7 +69,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
 
         let service = ContextBuilder::new(|| async {
             let client = db::create(db_url).await;
-            Ok::<_, Infallible>(State::new(client))
+            let write_buf = RefCell::new(BytesMut::new());
+            Ok::<_, Infallible>(State { client, write_buf })
         })
         .service(router);
 
@@ -79,29 +81,22 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
             .enclosed(tcp_config)
     };
 
-    let task = async {
-        xitca_server::Builder::new()
-            .on_worker_start(move || {
-                if let Some(core) = cores.lock().unwrap().pop() {
-                    core_affinity::set_for_current(core);
-                }
-                async {}
-            })
-            .bind("xitca-web", "0.0.0.0:8080", builder)?
-            .build()
-            .await
-            .map_err(Into::into)
-    };
-
-    tokio::runtime::Builder::new_current_thread()
-        .enable_all()
-        .build()?
-        .block_on(task)
+    xitca_server::Builder::new()
+        .on_worker_start(move || {
+            if let Some(core) = cores.lock().unwrap().pop() {
+                core_affinity::set_for_current(core);
+            }
+            async {}
+        })
+        .bind("xitca-web", "0.0.0.0:8080", builder)?
+        .build()
+        .wait()
+        .map_err(Into::into)
 }
 
 async fn middleware_fn<S, E>(service: &S, req: Ctx<'_>) -> Result<Response, Infallible>
 where
-    S: for<'r, 'c> Service<Ctx<'c>, Response = Response, Error = E>,
+    S: for<'c> Service<Ctx<'c>, Response = Response, Error = E>,
     E: Debug,
 {
     let mut res = service.call(req).await.unwrap();
@@ -123,14 +118,14 @@ async fn json(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
 
 async fn db(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
     let (req, state) = ctx.into_parts();
-    let world = state.client().get_world().await?;
+    let world = state.client.get_world().await?;
     _json(req, state, &world)
 }
 
 async fn fortunes(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
     let (req, state) = ctx.into_parts();
     use sailfish::TemplateOnce;
-    let fortunes = state.client().tell_fortune().await?.render_once()?;
+    let fortunes = state.client.tell_fortune().await?.render_once()?;
     let mut res = req.into_response(Bytes::from(fortunes));
     res.headers_mut().append(CONTENT_TYPE, TEXT_HTML_UTF8);
     Ok(res)
@@ -139,23 +134,23 @@ async fn fortunes(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
 async fn queries(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
     let (req, state) = ctx.into_parts();
     let num = req.uri().query().parse_query();
-    let worlds = state.client().get_worlds(num).await?;
+    let worlds = state.client.get_worlds(num).await?;
     _json(req, state, worlds.as_slice())
 }
 
 async fn updates(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
     let (req, state) = ctx.into_parts();
     let num = req.uri().query().parse_query();
-    let worlds = state.client().update(num).await?;
+    let worlds = state.client.update(num).await?;
     _json(req, state, worlds.as_slice())
 }
 
 fn _json<S>(req: Request, state: &State, value: &S) -> Result<Response, Box<dyn Error>>
 where
-    S: ?Sized + serde::Serialize,
+    S: ?Sized + Serialize,
 {
-    let mut buf = state.write_buf();
-    simd_json::to_writer(BufMutWriter(&mut *buf), value).unwrap();
+    let mut buf = state.write_buf.borrow_mut();
+    value.json_write(&mut BufMutWriter(&mut *buf)).unwrap();
     let body = buf.split().freeze();
     let mut res = req.into_response(body);
     res.headers_mut().append(CONTENT_TYPE, JSON);
@@ -164,21 +159,5 @@ where
 
 struct State {
     client: Client,
-    // a re-usable buffer for write response data.
     write_buf: RefCell<BytesMut>,
 }
-
-impl State {
-    fn new(client: Client) -> Self {
-        let write_buf = RefCell::new(BytesMut::new());
-        Self { client, write_buf }
-    }
-
-    fn write_buf(&self) -> RefMut<'_, BytesMut> {
-        self.write_buf.borrow_mut()
-    }
-
-    fn client(&self) -> &Client {
-        &self.client
-    }
-}

+ 2 - 3
frameworks/Rust/xitca-web/src/main_diesel.rs

@@ -29,8 +29,7 @@ type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
 
 type Request<'a> = WebRequest<'a, DieselPool>;
 
-#[tokio::main(flavor = "current_thread")]
-async fn main() -> io::Result<()> {
+fn main() -> io::Result<()> {
     let config = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world";
 
     HttpServer::new(move || {
@@ -46,7 +45,7 @@ async fn main() -> io::Result<()> {
     })
     .bind("0.0.0.0:8080")?
     .run()
-    .await
+    .wait()
 }
 
 async fn middleware_fn<S, E>(service: &S, mut ctx: Request<'_>) -> Result<WebResponse, Infallible>

+ 9 - 5
frameworks/Rust/xitca-web/src/ser.rs

@@ -1,10 +1,13 @@
 use std::borrow::Cow;
 
-use diesel::Queryable;
 use sailfish::TemplateOnce;
-use serde::{Deserialize, Serialize};
 
-#[derive(Deserialize, Serialize)]
+#[cfg(feature = "serde")]
+use serde::Serialize;
+#[cfg(feature = "simd")]
+use simd_json_derive::Serialize;
+
+#[derive(Serialize)]
 pub struct Message {
     message: &'static str,
 }
@@ -20,7 +23,8 @@ impl Message {
 }
 
 #[allow(non_snake_case)]
-#[derive(Debug, Serialize, Queryable)]
+#[cfg_attr(feature = "orm", derive(Queryable))]
+#[derive(Debug, Serialize)]
 pub struct World {
     pub id: i32,
     pub randomnumber: i32,
@@ -34,7 +38,7 @@ impl World {
     }
 }
 
-#[derive(Queryable)]
+#[cfg_attr(feature = "orm", derive(Queryable))]
 pub struct Fortune {
     pub id: i32,
     pub message: Cow<'static, str>,

+ 1 - 1
frameworks/Rust/xitca-web/src/util.rs

@@ -4,7 +4,7 @@ use std::cmp;
 
 use xitca_http::http::header::HeaderValue;
 
-pub(super) trait QueryParse {
+pub trait QueryParse {
     fn parse_query(self) -> u16;
 }
 

+ 3 - 3
frameworks/Rust/xitca-web/xitca-web-diesel.dockerfile

@@ -1,11 +1,11 @@
-FROM rust:1.61
+FROM rust:1.62
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-05-30
+RUN rustup default nightly-2022-07-18
 RUN cargo clean
-RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web-diesel
+RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web-diesel --features orm,serde,web
 
 EXPOSE 8080
 

+ 3 - 3
frameworks/Rust/xitca-web/xitca-web.dockerfile

@@ -1,11 +1,11 @@
-FROM rust:1.61
+FROM rust:1.62
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-05-30
+RUN rustup default nightly-2022-07-18
 RUN cargo clean
-RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web
+RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web --features raw,simd
 
 EXPOSE 8080