blob: 039affebb97cee8db33c0fe0e60918f71e0d4a9f [file] [log] [blame]
// Copyright (C) 2018, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#[macro_use]
extern crate criterion;
use ring::rand::*;
use criterion::Criterion;
fn handshake(c: &mut Criterion) {
let mut buf = [0; 65535];
let mut config = make_bench_config();
c.bench_function("handshake", move |b| {
b.iter(|| {
let mut pipe =
quiche::testing::Pipe::with_config(&mut config).unwrap();
pipe.handshake(&mut buf).unwrap();
})
});
}
fn stream(c: &mut Criterion) {
let mut buf = [0; 65535];
let mut config = make_bench_config();
let mut pipe = quiche::testing::Pipe::with_config(&mut config).unwrap();
pipe.handshake(&mut buf).unwrap();
let mut send_buf = vec![0; 5_000_000];
SystemRandom::new().fill(&mut send_buf[..]).unwrap();
let mut recv_buf = vec![0; send_buf.len()];
c.bench_function_over_inputs(
"stream",
move |b, &&size| {
b.iter(|| {
pipe.client
.stream_send(4, &send_buf[..size], false)
.unwrap();
let mut recv_len = 0;
while recv_len < size {
pipe.flush_client(&mut buf).unwrap();
let (len, _) = pipe
.server
.stream_recv(4, &mut recv_buf[recv_len..])
.unwrap();
recv_len += len;
pipe.flush_server(&mut buf).unwrap();
}
assert_eq!(recv_len, size);
assert_eq!(&recv_buf[..size], &send_buf[..size]);
})
},
&[128_000, 256_000, 512_000, 1_000_000, 5_000_000],
);
}
fn http3(c: &mut Criterion) {
let mut buf = [0; 65535];
let mut config = make_bench_config();
let h3_config = quiche::h3::Config::new().unwrap();
let mut s =
quiche::h3::testing::Session::with_configs(&mut config, &mut h3_config)
.unwrap();
s.handshake().unwrap();
let mut send_buf = vec![0; 5_000_000];
SystemRandom::new().fill(&mut send_buf[..]).unwrap();
let mut recv_buf = vec![0; send_buf.len()];
let req = [
quiche::h3::Header::new(":method", "GET"),
quiche::h3::Header::new(":scheme", "https"),
quiche::h3::Header::new(":authority", "quic.tech"),
quiche::h3::Header::new(":path", "/test"),
quiche::h3::Header::new("user-agent", "quiche-test"),
];
let resp = [
quiche::h3::Header::new(":status", "200"),
quiche::h3::Header::new("server", "quiche-test"),
];
c.bench_function_over_inputs(
"http3",
move |b, &&size| {
b.iter(|| {
s.client
.send_request(&mut s.pipe.client, &req, true)
.unwrap();
let mut recv_len = 0;
while recv_len < size {
s.pipe.flush_client(&mut buf).unwrap();
match s.server.poll(&mut s.pipe.server) {
Ok((stream, quiche::h3::Event::Headers(_))) => {
s.server
.send_response(
&mut s.pipe.server,
stream,
&resp,
false,
)
.unwrap();
s.server
.send_body(
&mut s.pipe.server,
stream,
&send_buf[..size],
true,
)
.unwrap();
},
_ => (),
}
s.pipe.flush_server(&mut buf).unwrap();
while let Ok(ev) = s.client.poll(&mut s.pipe.client) {
match ev {
(stream_id, quiche::h3::Event::Data) => {
let b = &mut recv_buf[recv_len..size];
if let Ok(r) = s.client.recv_body(
&mut s.pipe.client,
stream_id,
b,
) {
recv_len += r;
}
},
_ => (),
};
}
}
assert_eq!(recv_len, size);
assert_eq!(&recv_buf[..size], &send_buf[..size]);
})
},
&[128_000, 256_000, 512_000, 1_000_000, 5_000_000],
);
}
fn make_bench_config() -> quiche::Config {
let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
config
.load_cert_chain_from_pem_file("examples/cert.crt")
.unwrap();
config
.load_priv_key_from_pem_file("examples/cert.key")
.unwrap();
config
.set_application_protos(quiche::h3::APPLICATION_PROTOCOL)
.unwrap();
config.set_max_packet_size(1350);
config.set_initial_max_data(2u64.pow(62) - 1);
config.set_initial_max_stream_data_bidi_local(2u64.pow(62) - 1);
config.set_initial_max_stream_data_bidi_remote(2u64.pow(62) - 1);
config.set_initial_max_stream_data_uni(150);
config.set_initial_max_streams_bidi(2u64.pow(60) - 1);
config.set_initial_max_streams_uni(5);
config.verify_peer(false);
config
}
criterion_group!(benches, handshake, stream, http3);
criterion_main!(benches);