Skip to content

Commit 8da4292

Browse files
authored
Improve performance serialize to json at ntex (TechEmpower#5817)
* Improve performance `World` serialize to json at ntex * Use scalar json escape algorithm
1 parent b197b1c commit 8da4292

File tree

9 files changed

+40
-54
lines changed

9 files changed

+40
-54
lines changed

frameworks/Rust/ntex/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ path = "src/main_raw.rs"
1818
[dependencies]
1919
ntex = "0.1.18"
2020
snmalloc-rs = { version = "0.2.15", features = ["native-cpu"] }
21-
yarte = { version = "0.11", features = ["bytes-buf"] }
21+
yarte = { version = "0.11", features = ["bytes-buf", "json"] }
2222
env_logger = "0.7"
2323
random-fast-rng = "0.1.1"
2424
bytes = "0.5.3"

frameworks/Rust/ntex/ntex-db.dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FROM rust:1.44
22

3+
# Disable simd at jsonescape
4+
ENV CARGO_CFG_JSONESCAPE_DISABLE_AUTO_SIMD=
5+
36
RUN apt-get update -yqq && apt-get install -yqq cmake g++
47

58
ADD ./ /ntex

frameworks/Rust/ntex/ntex-raw.dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FROM rust:1.44
22

3+
# Disable simd at jsonescape
4+
ENV CARGO_CFG_JSONESCAPE_DISABLE_AUTO_SIMD=
5+
36
RUN apt-get update -yqq && apt-get install -yqq cmake g++
47

58
ADD ./ /ntex

frameworks/Rust/ntex/ntex.dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FROM rust:1.44
22

3+
# Disable simd at jsonescape
4+
ENV CARGO_CFG_JSONESCAPE_DISABLE_AUTO_SIMD=
5+
36
RUN apt-get update -yqq && apt-get install -yqq cmake g++
47

58
ADD ./ /ntex

frameworks/Rust/ntex/src/db.rs

+4-11
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,15 @@ use std::cell::RefCell;
33
use std::fmt::Write as FmtWrite;
44
use std::io;
55

6-
use bytes::{Bytes, BytesMut};
6+
use bytes::Bytes;
77
use futures::stream::futures_unordered::FuturesUnordered;
88
use futures::{Future, FutureExt, StreamExt, TryStreamExt};
99
use ntex::web::Error;
1010
use random_fast_rng::{FastRng, Random};
11-
use simd_json_derive::Serialize;
1211
use smallvec::{smallvec, SmallVec};
1312
use tokio_postgres::types::ToSql;
1413
use tokio_postgres::{connect, Client, NoTls, Statement};
15-
use yarte::TemplateBytes;
16-
17-
use crate::utils::Writer;
14+
use yarte::{Serialize, TemplateBytes};
1815

1916
#[derive(Serialize, Debug)]
2017
pub struct World {
@@ -91,15 +88,11 @@ impl PgConnection {
9188
Error::from(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)))
9289
})?;
9390

94-
let mut body = BytesMut::with_capacity(40);
95-
World {
91+
Ok(World {
9692
id: row.get(0),
9793
randomnumber: row.get(1),
9894
}
99-
.json_write(&mut Writer(&mut body))
100-
.unwrap();
101-
102-
Ok(body.freeze())
95+
.to_bytes(40))
10396
}
10497
}
10598

frameworks/Rust/ntex/src/main.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
#[global_allocator]
22
static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc;
33

4-
use bytes::{Bytes, BytesMut};
4+
use bytes::Bytes;
55
use ntex::{http, web};
6-
use simd_json_derive::Serialize;
6+
use yarte::Serialize;
77

88
mod utils;
9-
use utils::{Writer, SIZE};
9+
use utils::SIZE;
1010

1111
#[derive(Serialize)]
1212
pub struct Message {
1313
pub message: &'static str,
1414
}
1515

1616
async fn json() -> web::HttpResponse {
17-
let message = Message {
18-
message: "Hello, World!",
19-
};
20-
let mut body = BytesMut::with_capacity(SIZE);
21-
message.json_write(&mut Writer(&mut body)).unwrap();
22-
2317
let mut res = web::HttpResponse::with_body(
2418
http::StatusCode::OK,
25-
http::body::Body::Bytes(body.freeze()),
19+
http::body::Body::Bytes(
20+
Message {
21+
message: "Hello, World!",
22+
}
23+
.to_bytes(SIZE),
24+
),
2625
);
2726
res.headers_mut().insert(
2827
http::header::SERVER,

frameworks/Rust/ntex/src/main_db.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,18 @@ use std::future::Future;
55
use std::pin::Pin;
66
use std::task::{Context, Poll};
77

8-
use bytes::BytesMut;
98
use futures::future::ok;
109
use ntex::http::body::Body;
1110
use ntex::http::header::{HeaderValue, CONTENT_TYPE, SERVER};
1211
use ntex::http::{HttpService, KeepAlive, Request, Response, StatusCode};
1312
use ntex::service::{Service, ServiceFactory};
1413
use ntex::web::Error;
15-
use simd_json_derive::Serialize;
14+
use yarte::Serialize;
1615

1716
mod db;
1817
mod utils;
1918

2019
use crate::db::PgConnection;
21-
use crate::utils::Writer;
2220

2321
struct App {
2422
db: PgConnection,
@@ -77,10 +75,11 @@ impl Service for App {
7775

7876
Box::pin(async move {
7977
let worlds = fut.await?;
80-
let mut body = BytesMut::with_capacity(35 * worlds.len());
81-
worlds.json_write(&mut Writer(&mut body)).unwrap();
82-
let mut res =
83-
Response::with_body(StatusCode::OK, Body::Bytes(body.freeze()));
78+
let size = 35 * worlds.len();
79+
let mut res = Response::with_body(
80+
StatusCode::OK,
81+
Body::Bytes(worlds.to_bytes(size)),
82+
);
8483
let hdrs = res.headers_mut();
8584
hdrs.insert(SERVER, h_srv);
8685
hdrs.insert(CONTENT_TYPE, h_ct);
@@ -95,10 +94,11 @@ impl Service for App {
9594

9695
Box::pin(async move {
9796
let worlds = fut.await?;
98-
let mut body = BytesMut::with_capacity(35 * worlds.len());
99-
worlds.json_write(&mut Writer(&mut body)).unwrap();
100-
let mut res =
101-
Response::with_body(StatusCode::OK, Body::Bytes(body.freeze()));
97+
let size = 35 * worlds.len();
98+
let mut res = Response::with_body(
99+
StatusCode::OK,
100+
Body::Bytes(worlds.to_bytes(size)),
101+
);
102102
let hdrs = res.headers_mut();
103103
hdrs.insert(SERVER, h_srv);
104104
hdrs.insert(CONTENT_TYPE, h_ct);

frameworks/Rust/ntex/src/main_raw.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use ntex::codec::{AsyncRead, AsyncWrite, Decoder};
1111
use ntex::fn_service;
1212
use ntex::http::{h1, Request};
1313
use ntex::rt::net::TcpStream;
14-
use simd_json_derive::Serialize;
14+
use yarte::Serialize;
1515

1616
mod utils;
1717

@@ -37,14 +37,12 @@ impl App {
3737
fn handle_request(&mut self, req: Request) {
3838
match req.path() {
3939
"/json" => {
40-
let message = Message {
41-
message: "Hello, World!",
42-
};
4340
self.write_buf.extend_from_slice(JSON);
4441
self.codec.set_date_header(&mut self.write_buf);
45-
message
46-
.json_write(&mut utils::Writer(&mut self.write_buf))
47-
.unwrap();
42+
Message {
43+
message: "Hello, World!",
44+
}
45+
.to_bytes_mut(&mut self.write_buf);
4846
}
4947
"/plaintext" => {
5048
self.write_buf.extend_from_slice(PLAIN);

frameworks/Rust/ntex/src/utils.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,10 @@
11
#![allow(dead_code)]
2-
use std::{cmp, io};
2+
use std::cmp;
33

44
use atoi::FromRadix10;
5-
use bytes::BytesMut;
65

76
pub const SIZE: usize = 27;
87

9-
pub struct Writer<'a>(pub &'a mut BytesMut);
10-
11-
impl<'a> io::Write for Writer<'a> {
12-
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
13-
self.0.extend_from_slice(buf);
14-
Ok(buf.len())
15-
}
16-
fn flush(&mut self) -> io::Result<()> {
17-
Ok(())
18-
}
19-
}
20-
218
pub fn get_query_param(query: &str) -> u16 {
229
let q = if let Some(pos) = query.find("q") {
2310
u16::from_radix_10(query.split_at(pos + 2).1.as_ref()).0

0 commit comments

Comments
 (0)