Skip to content

Commit

Permalink
perf: stack alloc buf might be faster
Browse files Browse the repository at this point in the history
If the requests are ok most of the time, then a 256 byte array should be faster.

test stack_buf_128     ... bench:   2,520,140 ns/iter (+/- 175,758)
test stack_buf_192     ... bench:   2,429,559 ns/iter (+/- 145,934)
test stack_buf_256     ... bench:   2,368,500 ns/iter (+/- 77,421)
test stack_buf_384     ... bench:   5,179,250 ns/iter (+/- 171,965)
test stack_buf_512     ... bench:   5,457,417 ns/iter (+/- 219,768)
test vec_128           ... bench:  10,220,704 ns/iter (+/- 317,712)
test vec_192           ... bench:  10,855,938 ns/iter (+/- 407,135)
test vec_256           ... bench:  10,921,623 ns/iter (+/- 782,854)
test vec_384           ... bench:  10,206,575 ns/iter (+/- 363,215)
test vec_512           ... bench:  10,810,583 ns/iter (+/- 255,277)
test vec_stack_buf_128 ... bench:   6,190,262 ns/iter (+/- 172,463)
test vec_stack_buf_192 ... bench:   7,972,014 ns/iter (+/- 279,520)
test vec_stack_buf_256 ... bench:   6,722,798 ns/iter (+/- 308,850)
test vec_stack_buf_384 ... bench:   6,945,378 ns/iter (+/- 289,744)
test vec_stack_buf_512 ... bench:   6,915,483 ns/iter (+/- 301,180)
  • Loading branch information
kolbma committed Jan 16, 2024
1 parent a9dac9e commit a41fdb7
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 3 deletions.
195 changes: 195 additions & 0 deletions benches/stack_buf_bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#![feature(test)]

use std::io::{Cursor, Read};

extern crate test;

const READERS: &[&[u8]] = &[
&[1u8; 0],
&[2u8; 1],
&[3u8; 8],
&[4u8; 12],
&[5u8; 80],
&[6u8; 200],
&[7u8; 1024],
&[8u8; 4096],
&[9u8; 8192],
&[10u8; 25_000_000],
];

const COUNTS: [usize; 10] = [10000, 100, 100, 50, 50, 10, 10, 10, 5, 1];

const SIZES: [usize; 34] = [
0_usize, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 79, 80, 81, 199, 200, 201, 1023,
1024, 1025, 4095, 4096, 4097, 8191, 8192, 8193, 24_999_999, 25_000_000, 25_000_001,
];

fn stack_buf_bench<const N: usize>(bencher: &mut test::Bencher) {
let readers = std::hint::black_box(READERS);

bencher.iter(|| {
for (idx, reader) in readers.iter().enumerate() {
for _ in 0..COUNTS[idx] {
let mut reader = Cursor::new(*reader);

for size in SIZES {
let mut size = size;
if size == 0 {
continue;
}

let mut buf = &mut [0u8; N][..];
if size < N {
buf = &mut buf[..size];
}

while size > 0 {
match reader.read(buf) {
Ok(0) => {
break;
}
Ok(nr_bytes) => size -= nr_bytes,
Err(err) => {
unreachable!("{}", err);
}
}

if size < N {
buf = &mut buf[..size];
}
}

std::hint::black_box(buf);
}
}
}
});
}

fn vec_bench<const N: usize>(bencher: &mut test::Bencher) {
let readers = std::hint::black_box(READERS);

bencher.iter(|| {
for (idx, reader) in readers.iter().enumerate() {
for _ in 0..COUNTS[idx] {
let mut reader = Cursor::new(*reader);

for size in SIZES {
let mut size = size;
if size == 0 {
continue;
}

let mut buf = vec![0u8; if size > N { N } else { size }];

while size > 0 {
match reader.read(&mut buf) {
Ok(0) => {
break;
}
Ok(nr_bytes) => size -= nr_bytes,
Err(err) => {
unreachable!("{}", err);
}
}

buf.truncate(size);
}
std::hint::black_box(buf);
}
}
}
});
}

fn vec_stack_buf_bench<const N: usize>(bencher: &mut test::Bencher) {
let readers = std::hint::black_box(READERS);

bencher.iter(|| {
for (idx, reader) in readers.iter().enumerate() {
for _ in 0..COUNTS[idx] {
let mut reader = Cursor::new(*reader);

for size in SIZES {
let mut size = size;
if size == 0 {
continue;
}

if size <= N {
let mut buf = &mut [0u8; N][..];
while size > 0 {
match reader.read(buf) {
Ok(0) => {
break;
}
Ok(nr_bytes) => size -= nr_bytes,
Err(err) => {
unreachable!("{}", err);
}
}

if size < N {
buf = &mut buf[..size];
}
}
std::hint::black_box(buf);
} else {
let buf = &mut vec![0u8; N];
while size > 0 {
match reader.read(buf) {
Ok(0) => {
break;
}
Ok(nr_bytes) => size -= nr_bytes,
Err(err) => {
unreachable!("{}", err);
}
}

buf.truncate(size);
}
std::hint::black_box(buf);
};
}
}
}
});
}

macro_rules! create_benches {
( $($fstack:ident, $fvec:ident, $fvecstack:ident, $s:expr),+ ) => {
$(
// #[ignore]
#[bench]
fn $fstack(bencher: &mut test::Bencher) {
stack_buf_bench::<$s>(bencher);
}

// #[ignore]
#[bench]
fn $fvec(bencher: &mut test::Bencher) {
vec_bench::<$s>(bencher);
}

// #[ignore]
#[bench]
fn $fvecstack(bencher: &mut test::Bencher) {
vec_stack_buf_bench::<$s>(bencher);
}
)+
};
( $([$f1:ident, $f2:ident, $f3:ident, $s:expr]),+ ) => {
$(
create_benches!($f1, $f2, $f3, $s);
)+
};
}

create_benches!(
[stack_buf_128, vec_128, vec_stack_buf_128, 128_usize],
[stack_buf_192, vec_192, vec_stack_buf_192, 192_usize],
[stack_buf_256, vec_256, vec_stack_buf_256, 256_usize],
[stack_buf_384, vec_384, vec_stack_buf_384, 384_usize],
[stack_buf_512, vec_512, vec_stack_buf_512, 512_usize]
);
15 changes: 12 additions & 3 deletions src/util/equal_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,17 @@ where
R: Read,
{
fn drop(&mut self) {
let mut buf = vec![0; if self.size > 4096 { 4096 } else { self.size }];
if self.size == 0 {
return;
}

let mut buf = &mut [0u8; 256][..];
if self.size < 256 {
buf = &mut buf[..self.size];
}

while self.size > 0 {
match self.reader.read(&mut buf) {
match self.reader.read(buf) {
Ok(0) => {
if let Some(last_read_signal) = &self.last_read_signal {
last_read_signal.send(Ok(())).ok();
Expand All @@ -74,7 +81,9 @@ where
}
}

buf.truncate(self.size);
if self.size < 256 {
buf = &mut buf[..self.size];
}
}
}
}
Expand Down

1 comment on commit a41fdb7

@kolbma
Copy link
Owner Author

@kolbma kolbma commented on a41fdb7 Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also relevant for tiny-http#252

Please sign in to comment.