فهرست منبع

ntex: reduce memory allocations in fortunes bench (#5758)

* reduce memory allocations

* upgrade rustc

* use dynamic buffer
Nikolay Kim 5 سال پیش
والد
کامیت
d273d116dc

+ 5 - 5
frameworks/Rust/ntex/Cargo.toml

@@ -17,19 +17,19 @@ path = "src/main_raw.rs"
 
 [dependencies]
 ntex = "0.1.18"
-snmalloc-rs = "0.2.6"
-yarte = { version = "0.9.8", features = ["fixed"] }
-serde = "1.0"
-serde_derive = "1.0"
+snmalloc-rs = { version = "0.2.15", features = ["native-cpu"] }
+yarte = { version = "0.9.9", features = ["fixed"] }
 env_logger = "0.7"
 random-fast-rng = "0.1.1"
 bytes = "0.5.3"
 atoi = "0.3.2"
 num_cpus = "1.0"
-futures = "0.3.1"
+futures = "0.3.4"
 http = "0.2"
+smallvec = "1.4.0"
 simd-json = "0.3.9"
 simd-json-derive = { git = "https://github.com/simd-lite/simd-json-derive.git" }
+serde = { version = "1.0", features = ["derive"] }
 log = { version = "0.4", features = ["release_max_level_off"] }
 tokio = "=0.2.6"
 tokio-postgres = { git="https://github.com/fafhrd91/postgres.git" }

+ 1 - 1
frameworks/Rust/ntex/ntex-db.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.43.1
+FROM rust:1.44
 
 RUN apt-get update -yqq && apt-get install -yqq cmake g++
 

+ 1 - 1
frameworks/Rust/ntex/ntex-raw.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.43.1
+FROM rust:1.44
 
 RUN apt-get update -yqq && apt-get install -yqq cmake g++
 

+ 1 - 1
frameworks/Rust/ntex/ntex.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.43.1
+FROM rust:1.44
 
 RUN apt-get update -yqq && apt-get install -yqq cmake g++
 

+ 31 - 11
frameworks/Rust/ntex/src/db.rs

@@ -1,6 +1,6 @@
 use std::cell::RefCell;
-use std::fmt::Write;
-use std::io;
+use std::fmt::Write as FmtWrite;
+use std::io::{self, Write};
 
 use bytes::{Bytes, BytesMut};
 use futures::stream::futures_unordered::FuturesUnordered;
@@ -8,10 +8,11 @@ use futures::{Future, FutureExt, StreamExt, TryStreamExt};
 use ntex::web::Error;
 use random_fast_rng::{FastRng, Random};
 use simd_json_derive::Serialize;
+use smallvec::{smallvec, SmallVec};
 use tokio_postgres::types::ToSql;
 use tokio_postgres::{connect, Client, NoTls, Statement};
 
-use crate::utils::{Fortune, Writer};
+use crate::utils::Writer;
 
 #[derive(Serialize, Debug)]
 pub struct World {
@@ -19,6 +20,18 @@ pub struct World {
     pub randomnumber: i32,
 }
 
+#[derive(serde::Serialize, Debug)]
+pub struct Fortune<'a> {
+    pub id: i32,
+    pub message: &'a str,
+}
+
+#[derive(yarte::Template)]
+#[template(path = "fortune.hbs")]
+pub struct FortunesTemplate<'a> {
+    pub fortunes: &'a [Fortune<'a>],
+}
+
 /// Postgres interface
 pub struct PgConnection {
     cl: Client,
@@ -161,12 +174,7 @@ impl PgConnection {
         }
     }
 
-    pub fn tell_fortune(&self) -> impl Future<Output = Result<Vec<Fortune>, io::Error>> {
-        let mut items = vec![Fortune {
-            id: 0,
-            message: "Additional fortune added at request time.".to_string(),
-        }];
-
+    pub fn tell_fortune(&self) -> impl Future<Output = Result<Bytes, io::Error>> {
         let fut = self.cl.query_raw(&self.fortune, &[]);
 
         async move {
@@ -174,18 +182,30 @@ impl PgConnection {
                 .await
                 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{:?}", e)))?;
 
+            let mut rows = SmallVec::<[_; 32]>::new();
             while let Some(row) = stream.next().await {
                 let row = row.map_err(|e| {
                     io::Error::new(io::ErrorKind::Other, format!("{:?}", e))
                 })?;
+                rows.push(row);
+            }
+
+            let mut items: SmallVec<[_; 32]> = smallvec::smallvec![Fortune {
+                id: 0,
+                message: "Additional fortune added at request time.",
+            }];
+            for row in &rows {
                 items.push(Fortune {
                     id: row.get(0),
                     message: row.get(1),
                 });
             }
-
             items.sort_by(|it, next| it.message.cmp(&next.message));
-            Ok(items)
+
+            let mut body = BytesMut::with_capacity(2048);
+            let _ = write!(Writer(&mut body), "{}", FortunesTemplate { fortunes: items.as_ref() });
+
+            Ok(body.freeze())
         }
     }
 }

+ 3 - 15
frameworks/Rust/ntex/src/main_db.rs

@@ -13,13 +13,12 @@ use ntex::http::{HttpService, KeepAlive, Request, Response, StatusCode};
 use ntex::service::{Service, ServiceFactory};
 use ntex::web::Error;
 use simd_json_derive::Serialize;
-use yarte::TemplateFixed;
 
 mod db;
 mod utils;
 
 use crate::db::PgConnection;
-use crate::utils::{FortunesYarteTemplate, Writer};
+use crate::utils::Writer;
 
 struct App {
     db: PgConnection,
@@ -62,19 +61,8 @@ impl Service for App {
                 let fut = self.db.tell_fortune();
 
                 Box::pin(async move {
-                    let fortunes = fut.await?;
-                    let mut body = BytesMut::with_capacity(2048);
-                    unsafe {
-                        // Maybe uninit
-                        body.set_len(2048);
-                        // Before buffer overruns return `None`
-                        let size = FortunesYarteTemplate { fortunes }.call(body.as_mut()).unwrap();
-                        // Bound to init data
-                        body.set_len(size)
-                    };
-
-                    let mut res =
-                        Response::with_body(StatusCode::OK, Body::Bytes(body.freeze()));
+                    let body = fut.await?;
+                    let mut res = Response::with_body(StatusCode::OK, Body::Bytes(body));
                     let hdrs = res.headers_mut();
                     hdrs.insert(SERVER, h_srv);
                     hdrs.insert(CONTENT_TYPE, h_ct);

+ 0 - 15
frameworks/Rust/ntex/src/utils.rs

@@ -3,15 +3,6 @@ use std::{cmp, io};
 
 use atoi::FromRadix10;
 use bytes::BytesMut;
-use serde_derive::Serialize;
-use yarte::TemplateFixed;
-
-#[allow(non_snake_case)]
-#[derive(Serialize, Debug)]
-pub struct Fortune {
-    pub id: i32,
-    pub message: String,
-}
 
 pub const SIZE: usize = 27;
 
@@ -35,9 +26,3 @@ pub fn get_query_param(query: &str) -> u16 {
     };
     cmp::min(500, cmp::max(1, q))
 }
-
-#[derive(TemplateFixed)]
-#[template(path = "fortune.hbs")]
-pub struct FortunesYarteTemplate {
-    pub fortunes: Vec<Fortune>,
-}