Browse Source

fix xitca-web-wasm bench. (#7938)

fakeshadow 2 years ago
parent
commit
635c3b1fa8

File diff suppressed because it is too large
+ 157 - 383
frameworks/Rust/xitca-web/Cargo.lock


+ 22 - 29
frameworks/Rust/xitca-web/Cargo.toml

@@ -6,7 +6,7 @@ edition = "2021"
 [[bin]]
 name = "xitca-web"
 path = "./src/main.rs"
-required-features = ["raw", "sailfish", "simd"]
+required-features = ["raw", "sailfish", "serde"]
 
 [[bin]]
 name = "xitca-web-diesel"
@@ -28,10 +28,8 @@ required-features = ["web"]
 raw = ["xitca-postgres"]
 # diesel-pg orm optional
 orm = ["diesel", "diesel-async", "tang-rs"]
-# simd-json optional
-simd = ["simd-json", "simd-json-derive"]
 # serde optional
-serde = ["dep:serde"]
+serde = ["dep:serde", "serde_json"]
 # web optional
 web = ["xitca-web"]
 # templating optional
@@ -47,40 +45,34 @@ xitca-service = "0.1"
 xitca-unsafe-collection = "0.1"
 
 atoi = "2"
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3.1", features = ["env-filter"] }
 
 # 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 }
+xitca-postgres = { version = "0.1", features = ["single-thread"], optional = true }
 
 # diesel-pg orm optional
-diesel = { version = "2.0.0", default-features = false, features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes"], optional = true }
-diesel-async = { version = "0.1.1", default-features = false, features = ["postgres"], optional = true }
+diesel = { version = "2", default-features = false, features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes"], optional = true }
+diesel-async = { version = "0.2", default-features = false, features = ["postgres"], optional = true }
 tang-rs = { version = "0.2", 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.6.3", default-features = false, optional = true }
-
 # serde optional
 serde = { version = "1", features = ["derive"], optional = true }
+serde_json = { version = "1", optional = true }
 
 # io-uring optional
-tokio-uring = { version = "0.3", features = ["bytes"], optional = true }
+tokio-uring = { version = "0.4", features = ["bytes"], optional = true }
 
 # templating optional
-sailfish = { version = "0.5.0", optional = true }
+sailfish = { version = "0.6", optional = true }
 
 # stuff can not be used or not needed in wasi target
 [target.'cfg(not(target_family = "wasm"))'.dependencies]
-mimalloc = { version = "0.1.29", default-features = false }
-core_affinity = "0.5.10"
-futures-util = { version = "0.3.18", default-features = false, features = ["alloc"] }
-rand = { version = "0.8.5", default-features = false, features = ["min_const_gen", "nightly", "simd_support", "small_rng"] }
-tokio = "1.24.2"
+mimalloc = { version = "0.1", default-features = false }
+futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
+rand = { version = "0.8", default-features = false, features = ["min_const_gen", "nightly", "simd_support", "small_rng"] }
+tokio = "1"
 
 [profile.release]
 lto = true
@@ -89,12 +81,13 @@ codegen-units = 1
 panic = "abort"
 
 [patch.crates-io]
-xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "7a2b6c37011f41fe851ad73480320b2e753c5e7c" }
-
-tokio-uring = { git = "https://github.com/tokio-rs/tokio-uring.git", rev = "8725b81b862cc480be93b1a11c80b9990d51d890" }
+xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-router = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "5462c9ecc1440e1b493281b2e0cdced4a19ad7af" }
+
+mio = { git = "https://github.com/fakeshadow/mio.git", rev = "8f9125153aecb37f638a212fe82df8671bc77a1a" }

+ 7 - 6
frameworks/Rust/xitca-web/benchmark_config.json

@@ -11,7 +11,7 @@
         "update_url": "/updates?q=",
         "port": 8080,
         "approach": "Realistic",
-        "classification": "Platform",
+        "classification": "Micro",
         "database": "Postgres",
         "framework": "xitca-web",
         "language": "Rust",
@@ -50,8 +50,8 @@
         "plaintext_url": "/plaintext",
         "fortune_url": "/fortunes",
         "port": 8080,
-        "approach": "Realistic",
-        "classification": "Micro",
+        "approach": "Stripped",
+        "classification": "Platform",
         "database": "Postgres",
         "framework": "xitca-web",
         "language": "Rust",
@@ -62,13 +62,14 @@
         "database_os": "Linux",
         "display_name": "xitca-web [io-uring]",
         "notes": "",
-        "versus": ""
+        "versus": "",
+        "tags": ["broken"]
       },
       "wasm": {
         "plaintext_url": "/plaintext",
         "port": 8080,
-        "approach": "realistic",
-        "classification": "micro",
+        "approach": "Realistic",
+        "classification": "Micro",
         "database": "none",
         "framework": "xitca-web",
         "language": "rust",

+ 13 - 19
frameworks/Rust/xitca-web/src/db.rs

@@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::HashMap, error::Error, fmt::Write, future:
 
 use futures_util::stream::{FuturesUnordered, StreamExt, TryStreamExt};
 use rand::{rngs::SmallRng, Rng, SeedableRng};
-use xitca_postgres::{Postgres, Statement, ToSql};
+use xitca_postgres::{statement::Statement, Postgres, ToSql};
 use xitca_unsafe_collection::no_hash::NoHashBuilder;
 
 use super::ser::{Fortune, Fortunes, World};
@@ -18,9 +18,7 @@ pub struct Client {
 impl Drop for Client {
     fn drop(&mut self) {
         drop(self.fortune.clone().into_guarded(&self.client));
-
         drop(self.world.clone().into_guarded(&self.client));
-
         for (_, stmt) in std::mem::take(&mut self.updates) {
             drop(stmt.into_guarded(&self.client))
         }
@@ -28,11 +26,9 @@ impl Drop for Client {
 }
 
 pub async fn create(config: &str) -> DbResult<Client> {
-    let (client, conn) = Postgres::new(config.to_string()).connect().await?;
+    let (client, bg_task) = Postgres::new(config.to_string()).connect().await?;
 
-    tokio::task::spawn_local(async move {
-        let _ = conn.await;
-    });
+    tokio::task::spawn_local(bg_task);
 
     let fortune = client.prepare("SELECT * FROM fortune", &[]).await?.leak();
 
@@ -93,16 +89,14 @@ impl Client {
     }
 
     pub fn get_worlds(&self, num: u16) -> impl Future<Output = DbResult<Vec<World>>> + '_ {
-        let worlds = {
-            let mut rng = self.rng.borrow_mut();
-            (0..num)
-                .map(|_| {
-                    let id = (rng.gen::<u32>() % 10_000 + 1) as i32;
-                    self.query_one_world(id)
-                })
-                .collect::<FuturesUnordered<_>>()
-        };
-        worlds.try_collect()
+        let mut rng = self.rng.borrow_mut();
+        (0..num)
+            .map(|_| {
+                let id = (rng.gen::<u32>() % 10_000 + 1) as i32;
+                self.query_one_world(id)
+            })
+            .collect::<FuturesUnordered<_>>()
+            .try_collect()
     }
 
     pub async fn update(&self, num: u16) -> DbResult<Vec<World>> {
@@ -148,11 +142,11 @@ impl Client {
 
         let mut stream = self
             .client
-            .query_raw::<_, &[i32; 0]>(&self.fortune, &[])
+            .query_raw::<&[i32; 0]>(&self.fortune, &[])
             .await?;
 
         while let Some(row) = stream.try_next().await? {
-            items.push(Fortune::new(row.get(0), row.get::<_, String>(1)));
+            items.push(Fortune::new(row.get(0), row.get::<String>(1)));
         }
 
         items.sort_by(|it, next| it.message.cmp(&next.message));

+ 34 - 53
frameworks/Rust/xitca-web/src/main.rs

@@ -5,9 +5,8 @@ mod db;
 mod ser;
 mod util;
 
-use std::{cell::RefCell, convert::Infallible, error::Error, fmt::Debug, io, sync::Mutex};
+use std::{cell::RefCell, convert::Infallible, error::Error, fmt::Debug, io};
 
-use simd_json_derive::Serialize;
 use xitca_http::{
     body::Once,
     bytes::{BufMutWriter, Bytes, BytesMut},
@@ -17,16 +16,12 @@ use xitca_http::{
         self,
         const_header_value::{JSON, TEXT, TEXT_HTML_UTF8},
         header::{CONTENT_TYPE, SERVER},
-        IntoResponse,
+        IntoResponse, RequestExt,
     },
-    request,
-    util::{
-        middleware::TcpConfig,
-        service::{
-            context::{object::ContextObjectConstructor, Context, ContextBuilder},
-            route::get,
-            GenericRouter,
-        },
+    util::service::{
+        context::{object::ContextObjectConstructor, Context, ContextBuilder},
+        route::get,
+        GenericRouter,
     },
     HttpServiceBuilder,
 };
@@ -37,50 +32,36 @@ use self::ser::Message;
 use self::util::{QueryParse, DB_URL, SERVER_HEADER_VALUE};
 
 type Response = http::Response<Once<Bytes>>;
-type Request = request::Request<RequestBody>;
+type Request = http::Request<RequestExt<RequestBody>>;
 type Ctx<'a> = Context<'a, Request, State>;
 
 fn main() -> io::Result<()> {
-    let cores = core_affinity::get_core_ids().unwrap_or_default();
-    let cores = Mutex::new(cores);
-
-    let builder = || {
-        let config = HttpServiceConfig::new()
-            .disable_vectored_write()
-            .max_request_headers::<8>();
-
-        let router = GenericRouter::with_custom_object::<ContextObjectConstructor<_, _>>()
-            .insert("/plaintext", get(fn_service(plain_text)))
-            .insert("/json", get(fn_service(json)))
-            .insert("/db", get(fn_service(db)))
-            .insert("/fortunes", get(fn_service(fortunes)))
-            .insert("/queries", get(fn_service(queries)))
-            .insert("/updates", get(fn_service(updates)))
-            .enclosed_fn(middleware_fn);
-
-        let service = ContextBuilder::new(|| async {
-            db::create(DB_URL).await.map(|client| {
-                let write_buf = RefCell::new(BytesMut::new());
-                State { client, write_buf }
-            })
-        })
-        .service(router);
-
-        let tcp_config = TcpConfig::new().set_nodelay(true);
-
-        HttpServiceBuilder::h1(service)
-            .config(config)
-            .enclosed(tcp_config)
-    };
-
     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)?
+        .bind("xitca-web", "0.0.0.0:8080", || {
+            HttpServiceBuilder::h1(
+                ContextBuilder::new(|| async {
+                    db::create(DB_URL).await.map(|client| State {
+                        client,
+                        write_buf: RefCell::new(BytesMut::new()),
+                    })
+                })
+                .service(
+                    GenericRouter::with_custom_object::<ContextObjectConstructor<_, _>>()
+                        .insert("/plaintext", get(fn_service(plain_text)))
+                        .insert("/json", get(fn_service(json)))
+                        .insert("/db", get(fn_service(db)))
+                        .insert("/fortunes", get(fn_service(fortunes)))
+                        .insert("/queries", get(fn_service(queries)))
+                        .insert("/updates", get(fn_service(updates)))
+                        .enclosed_fn(middleware_fn),
+                ),
+            )
+            .config(
+                HttpServiceConfig::new()
+                    .disable_vectored_write()
+                    .max_request_headers::<8>(),
+            )
+        })?
         .build()
         .wait()
 }
@@ -138,10 +119,10 @@ async fn updates(ctx: Ctx<'_>) -> Result<Response, Box<dyn Error>> {
 
 fn _json<S>(req: Request, state: &State, value: &S) -> Result<Response, Box<dyn Error>>
 where
-    S: ?Sized + Serialize,
+    S: ?Sized + serde::Serialize,
 {
     let mut buf = state.write_buf.borrow_mut();
-    value.json_write(&mut BufMutWriter(&mut *buf))?;
+    serde_json::to_writer(BufMutWriter(&mut *buf), value)?;
     let body = buf.split().freeze();
     let mut res = req.into_response(body);
     res.headers_mut().append(CONTENT_TYPE, JSON);

+ 12 - 21
frameworks/Rust/xitca-web/src/main_iou.rs

@@ -16,32 +16,26 @@ use std::{
     fmt,
     future::{poll_fn, Future},
     io,
+    pin::pin,
 };
 
 use futures_util::stream::Stream;
-use tracing::{span, Level};
-use xitca_http::http::const_header_value::TEXT_HTML_UTF8;
 use xitca_http::{
-    body::{BodySize, Once},
+    body::Once,
     date::DateTimeService,
     h1::proto::context::Context,
     http::{
-        const_header_value::TEXT,
+        const_header_value::{TEXT, TEXT_HTML_UTF8},
         header::{CONTENT_TYPE, SERVER},
-        IntoResponse, Response, StatusCode,
+        IntoResponse, Request, RequestExt, Response, StatusCode,
     },
-    util::{
-        middleware::Logger,
-        service::context::{Context as Ctx, ContextBuilder},
-    },
-    Request,
+    util::service::context::{Context as Ctx, ContextBuilder},
 };
 use xitca_io::{
     bytes::{Buf, Bytes, BytesMut},
     net::TcpStream,
 };
-use xitca_service::{fn_service, ready::ReadyService, Service, ServiceExt};
-use xitca_unsafe_collection::pin;
+use xitca_service::{fn_service, ready::ReadyService, Service};
 
 use self::{
     db::Client,
@@ -49,13 +43,9 @@ use self::{
 };
 
 fn main() -> io::Result<()> {
-    tracing_subscriber::fmt()
-        .with_env_filter("[xitca-iou]=trace")
-        .init();
     xitca_server::Builder::new()
         .bind("xitca-iou", "0.0.0.0:8080", || {
             Http1IOU::new(ContextBuilder::new(|| db::create(DB_URL)).service(fn_service(handler)))
-                .enclosed(Logger::with_span(span!(Level::ERROR, "xitca-iou")))
         })?
         .build()
         .wait()
@@ -140,7 +130,7 @@ where
 // runner for http service.
 impl<S> Service<TcpStream> for Http1IOUService<S>
 where
-    S: Service<Request<()>, Response = Response<Once<Bytes>>>,
+    S: Service<Request<RequestExt<()>>, Response = Response<Once<Bytes>>>,
     S::Error: fmt::Debug,
 {
     type Response = ();
@@ -172,9 +162,8 @@ where
 
                 while let Some((req, _)) = ctx.decode_head::<65535>(&mut read_buf).unwrap() {
                     let (parts, body) = self.service.call(req).await.unwrap().into_parts();
-                    let size = BodySize::from_stream(&body);
-                    let mut encoder = ctx.encode_head(parts, size, &mut write_buf).unwrap();
-                    pin!(body);
+                    let mut encoder = ctx.encode_head(parts, &body, &mut write_buf).unwrap();
+                    let mut body = pin!(body);
                     while let Some(chunk) = poll_fn(|cx| body.as_mut().poll_next(cx)).await {
                         let chunk = chunk.unwrap();
                         encoder.encode(chunk, &mut write_buf);
@@ -193,7 +182,9 @@ where
                     write_buf = w;
                 }
 
-                read_buf.reserve(4096 - read_buf.capacity());
+                if read_buf.capacity() < 256 {
+                    read_buf.reserve(4096);
+                }
             }
 
             Ok(())

+ 8 - 8
frameworks/Rust/xitca-web/src/main_wasm.rs

@@ -19,7 +19,10 @@ fn main() -> io::Result<()> {
 
     HttpServer::new(|| {
         App::new()
-            .at("/plaintext", get(handler_service(plain_text)))
+            .at(
+                "/plaintext",
+                get(handler_service(|| async { "Hello, World!" })),
+            )
             .enclosed_fn(middleware_fn)
             .finish()
     })
@@ -32,11 +35,8 @@ async fn middleware_fn<S, E>(service: &S, ctx: WebRequest<'_>) -> Result<WebResp
 where
     S: for<'r> Service<WebRequest<'r>, Response = WebResponse, Error = E>,
 {
-    let mut res = service.call(ctx).await?;
-    res.headers_mut().append(SERVER, SERVER_HEADER_VALUE);
-    Ok(res)
-}
-
-async fn plain_text() -> &'static str {
-    "Hello, World!"
+    service.call(ctx).await.map(|mut res| {
+        res.headers_mut().append(SERVER, SERVER_HEADER_VALUE);
+        res
+    })
 }

+ 13 - 16
frameworks/Rust/xitca-web/src/ser.rs

@@ -1,21 +1,14 @@
 use std::borrow::Cow;
 
-use sailfish::TemplateOnce;
-
-#[cfg(feature = "serde")]
-use serde::Serialize;
-#[cfg(feature = "simd")]
-use simd_json_derive::Serialize;
-
-#[derive(Serialize)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize))]
 pub struct Message {
     message: &'static str,
 }
 
 impl Message {
-    #[inline]
     #[allow(dead_code)]
-    pub(super) fn new() -> Self {
+    #[inline]
+    pub(super) const fn new() -> Self {
         Self {
             message: "Hello, World!",
         }
@@ -23,17 +16,18 @@ impl Message {
 }
 
 #[allow(non_snake_case)]
+#[derive(Debug)]
 #[cfg_attr(feature = "orm", derive(Queryable))]
-#[derive(Debug, Serialize)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize))]
 pub struct World {
     pub id: i32,
     pub randomnumber: i32,
 }
 
 impl World {
-    #[inline]
     #[allow(dead_code)]
-    pub fn new(id: i32, randomnumber: i32) -> Self {
+    #[inline]
+    pub const fn new(id: i32, randomnumber: i32) -> Self {
         Self { id, randomnumber }
     }
 }
@@ -54,15 +48,18 @@ impl Fortune {
     }
 }
 
-#[derive(TemplateOnce)]
-#[template(path = "fortune.stpl", rm_whitespace = true)]
+#[cfg_attr(
+    feature = "sailfish",
+    derive(sailfish::TemplateOnce),
+    template(path = "fortune.stpl", rm_whitespace = true)
+)]
 pub struct Fortunes {
     items: Vec<Fortune>,
 }
 
 impl Fortunes {
     #[inline]
-    pub fn new(items: Vec<Fortune>) -> Self {
+    pub const fn new(items: Vec<Fortune>) -> Self {
         Self { items }
     }
 }

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

@@ -3,7 +3,7 @@ FROM rust:latest
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-10-27
+RUN rustup default nightly-2023-02-20
 RUN cargo clean
 RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web-diesel --features orm,sailfish,serde,web
 

+ 2 - 2
frameworks/Rust/xitca-web/xitca-web-iou.dockerfile

@@ -3,9 +3,9 @@ FROM rust:latest
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-10-27
+RUN rustup default nightly-2023-02-20
 RUN cargo clean
-RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web-iou --features io-uring,raw,sailfish,simd
+RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web-iou --features io-uring,raw,sailfish,serde
 
 EXPOSE 8080
 

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

@@ -3,14 +3,14 @@ FROM rust:latest
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-10-27
+RUN rustup default nightly-2023-02-20
 RUN rustup target add wasm32-wasi
 RUN cargo clean
 RUN RUSTFLAGS="--cfg tokio_unstable" cargo build --release --bin xitca-web-wasm --target wasm32-wasi --features web
 
-RUN curl --show-error --location --fail https://github.com/bytecodealliance/wasmtime/releases/download/v2.0.0/wasmtime-v2.0.0-x86_64-linux.tar.xz --output wasmtime.tar.xz
+RUN curl --show-error --location --fail https://github.com/bytecodealliance/wasmtime/releases/download/v6.0.0/wasmtime-v6.0.0-x86_64-linux.tar.xz --output wasmtime.tar.xz
 RUN tar -xvf wasmtime.tar.xz
 
 EXPOSE 8080
 
-CMD ./wasmtime-v2.0.0-x86_64-linux/wasmtime ./target/wasm32-wasi/release/xitca-web-wasm.wasm --tcplisten 0.0.0.0:8080 --env FD_COUNT=3
+CMD ./wasmtime-v6.0.0-x86_64-linux/wasmtime ./target/wasm32-wasi/release/xitca-web-wasm.wasm --tcplisten 0.0.0.0:8080 --env FD_COUNT=3

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

@@ -3,9 +3,9 @@ FROM rust:latest
 ADD ./ /xitca-web
 WORKDIR /xitca-web
 
-RUN rustup default nightly-2022-10-27
+RUN rustup default nightly-2023-02-20
 RUN cargo clean
-RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web --features raw,sailfish,simd
+RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin xitca-web --features raw,sailfish,serde
 
 EXPOSE 8080
 

Some files were not shown because too many files changed in this diff