Skip to content

Commit 3c1e4dd

Browse files
committed
ntex: optimize allocations
1 parent 269fa6f commit 3c1e4dd

File tree

3 files changed

+78
-29
lines changed

3 files changed

+78
-29
lines changed

frameworks/Rust/ntex/Cargo.toml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "ntex-bench"
2+
name = "ntex-framework"
33
version = "3.0.0"
44
edition = "2018"
55

@@ -60,17 +60,15 @@ tokio = ["ntex/tokio"]
6060
# compio runtime
6161
compio = ["ntex/compio"]
6262

63-
# neon runtime
64-
neon = ["ntex/neon"]
63+
# neon polling runtime
64+
neon = ["ntex/neon-polling"]
6565

66-
# neon runtime
66+
# neon io-uring runtime
6767
neon-uring = ["ntex/neon-uring"]
6868

6969
[dependencies]
70-
ntex = "3.0.0-pre.5"
71-
ntex-neon = "0.1.35"
72-
ntex-net = "3.0.0"
73-
ntex-bytes = { version = "1", features=["simd"] }
70+
ntex = "3.0.0-pre.10"
71+
ntex-bytes = { version = "1.2", features=["simd"] }
7472
mimalloc = { version = "0.1.25", default-features = false }
7573
snmalloc-rs = { version = "0.3.3", features = ["native-cpu"] }
7674
yarte = { version = "0.15", features = ["bytes-buf", "json"] }

frameworks/Rust/ntex/src/db.rs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use std::cell::RefCell;
1+
use std::cell::Cell;
22

33
use nanorand::{Rng, WyRand};
4-
use ntex::util::{Bytes, BytesMut};
4+
use ntex::util::{Bytes, BytesVec, BufMut};
55
use smallvec::SmallVec;
66
use tokio_postgres::{connect, Client, Statement};
77
use yarte::TemplateBytesTrait;
@@ -33,7 +33,7 @@ pub struct PgConnection {
3333
world: Statement,
3434
rng: WyRand,
3535
updates: Statement,
36-
buf: RefCell<BytesMut>,
36+
buf: Cell<Option<BytesVec>>,
3737
}
3838

3939
impl PgConnection {
@@ -55,7 +55,7 @@ impl PgConnection {
5555
world,
5656
updates,
5757
rng: WyRand::new(),
58-
buf: RefCell::new(BytesMut::with_capacity(10 * 1024 * 1024)),
58+
buf: Cell::new(Some(BytesVec::with_capacity(10 * 1024 * 1024))),
5959
}
6060
}
6161
}
@@ -66,17 +66,18 @@ impl PgConnection {
6666

6767
let row = self.cl.query_one(&self.world, &[&random_id]).await.unwrap();
6868

69-
let mut body = self.buf.borrow_mut();
70-
utils::reserve(&mut body, 1024);
69+
let mut body = self.buf.take().unwrap();
7170
sonic_rs::to_writer(
72-
utils::BytesWriter(&mut body),
71+
utils::BVecWriter::new(&mut body),
7372
&World {
7473
id: row.get(0),
7574
randomnumber: row.get(1),
7675
},
7776
)
7877
.unwrap();
79-
body.split().freeze()
78+
let result = body.take_bytes();
79+
self.buf.set(Some(body));
80+
result
8081
}
8182

8283
pub async fn get_worlds(&self, num: usize) -> Bytes {
@@ -96,10 +97,11 @@ impl PgConnection {
9697
})
9798
}
9899

99-
let mut body = self.buf.borrow_mut();
100-
utils::reserve(&mut body, 2 * 1024);
101-
sonic_rs::to_writer(utils::BytesWriter(&mut body), &worlds[..]).unwrap();
102-
body.split().freeze()
100+
let mut body = self.buf.take().unwrap();
101+
sonic_rs::to_writer(utils::BVecWriter::new(&mut body), &worlds[..]).unwrap();
102+
let result = body.take_bytes();
103+
self.buf.set(Some(body));
104+
result
103105
}
104106

105107
pub async fn update(&self, num: usize) -> Bytes {
@@ -131,10 +133,11 @@ impl PgConnection {
131133

132134
update.await.unwrap();
133135

134-
let mut body = self.buf.borrow_mut();
135-
utils::reserve(&mut body, 2 * 1024);
136-
sonic_rs::to_writer(utils::BytesWriter(&mut body), &worlds[..]).unwrap();
137-
body.split().freeze()
136+
let mut body = self.buf.take().unwrap();
137+
sonic_rs::to_writer(utils::BVecWriter::new(&mut body), &worlds[..]).unwrap();
138+
let result = body.take_bytes();
139+
self.buf.set(Some(body));
140+
result
138141
}
139142

140143
pub async fn tell_fortune(&self) -> Bytes {
@@ -151,17 +154,20 @@ impl PgConnection {
151154
}));
152155
fortunes.sort_by(|it, next| it.message.cmp(&next.message));
153156

154-
let mut body = std::mem::replace(&mut *self.buf.borrow_mut(), BytesMut::new());
155-
utils::reserve(&mut body, 4 * 1024);
157+
let mut body = self.buf.take().unwrap();
158+
let remaining = body.remaining_mut();
159+
if remaining < 4 * 1024 {
160+
body.reserve(128 * 1024);
161+
}
156162

157163
FortunesTemplate {
158164
fortunes: &fortunes,
159165
}
160166
.write_call(&mut body);
161167
fortunes.clear();
162168

163-
let result = body.split().freeze();
164-
let _ = std::mem::replace(&mut *self.buf.borrow_mut(), body);
169+
let result = body.take_bytes();
170+
self.buf.set(Some(body));
165171
result
166172
}
167173
}

frameworks/Rust/ntex/src/utils.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::{cmp, io, io::Write, mem::MaybeUninit, slice::from_raw_parts_mut};
33

44
use atoi::FromRadix10;
55
use ntex::http::{header::HeaderValue, HttpServiceConfig, KeepAlive};
6-
use ntex::{io::IoConfig, time::Seconds, util::BufMut, util::Bytes, util::BytesMut, SharedCfg};
6+
use ntex::util::{BufMut, Bytes, BytesMut, BytesVec};
7+
use ntex::{io::IoConfig, time::Seconds, SharedCfg};
78
use sonic_rs::writer::WriteExt;
89

910
pub const HDR_SERVER: HeaderValue = HeaderValue::from_static("N");
@@ -97,3 +98,47 @@ impl WriteExt for BytesWriter<'_> {
9798
Ok(())
9899
}
99100
}
101+
102+
pub struct BVecWriter<'a>(&'a mut BytesVec);
103+
104+
impl<'a> BVecWriter<'a> {
105+
pub fn new(buf: &'a mut BytesVec) -> BVecWriter<'a> {
106+
let remaining = buf.remaining_mut();
107+
if remaining < 2048 {
108+
buf.reserve(HW);
109+
}
110+
Self(buf)
111+
}
112+
}
113+
114+
impl Write for BVecWriter<'_> {
115+
fn write(&mut self, src: &[u8]) -> Result<usize, io::Error> {
116+
self.0.extend_from_slice(src);
117+
Ok(src.len())
118+
}
119+
120+
fn flush(&mut self) -> Result<(), io::Error> {
121+
Ok(())
122+
}
123+
}
124+
125+
impl WriteExt for BVecWriter<'_> {
126+
#[inline(always)]
127+
fn reserve_with(&mut self, additional: usize) -> Result<&mut [MaybeUninit<u8>], io::Error> {
128+
self.0.reserve(additional);
129+
130+
unsafe {
131+
let ptr = self.0.as_mut_ptr().add(self.0.len()) as *mut MaybeUninit<u8>;
132+
Ok(from_raw_parts_mut(ptr, additional))
133+
}
134+
}
135+
136+
#[inline(always)]
137+
unsafe fn flush_len(&mut self, additional: usize) -> io::Result<()> {
138+
unsafe {
139+
let new_len = self.0.len() + additional;
140+
self.0.set_len(new_len);
141+
}
142+
Ok(())
143+
}
144+
}

0 commit comments

Comments
 (0)