-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
afb0539
commit 83b928b
Showing
12 changed files
with
340 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
use std::{ | ||
net::{IpAddr, Ipv4Addr, SocketAddr}, | ||
sync::Arc, | ||
time::Instant, | ||
}; | ||
|
||
use bytes::Bytes; | ||
use criterion::{criterion_group, criterion_main, Bencher, Criterion, Throughput}; | ||
use futures_util::{stream::FuturesUnordered, StreamExt}; | ||
use rand::{thread_rng, RngCore}; | ||
|
||
criterion_group!(quic, echo); | ||
criterion_main!(quic); | ||
|
||
fn gen_cert() -> ( | ||
rustls::pki_types::CertificateDer<'static>, | ||
rustls::pki_types::PrivateKeyDer<'static>, | ||
) { | ||
let rcgen::CertifiedKey { cert, key_pair } = | ||
rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); | ||
let cert = cert.der().clone(); | ||
let key_der = key_pair.serialize_der().try_into().unwrap(); | ||
(cert, key_der) | ||
} | ||
|
||
macro_rules! echo_impl { | ||
($send:ident, $recv:ident) => { | ||
loop { | ||
// These are 32 buffers, for reading approximately 32kB at once | ||
let mut bufs: [Bytes; 32] = std::array::from_fn(|_| Bytes::new()); | ||
|
||
match $recv.read_chunks(&mut bufs).await.unwrap() { | ||
Some(n) => { | ||
$send.write_all_chunks(&mut bufs[..n]).await.unwrap(); | ||
} | ||
None => break, | ||
} | ||
} | ||
|
||
let _ = $send.finish(); | ||
}; | ||
} | ||
|
||
fn echo_compio_quic(b: &mut Bencher, content: &[u8], streams: usize) { | ||
use compio_quic::{ClientBuilder, ServerBuilder}; | ||
|
||
let runtime = compio_runtime::Runtime::new().unwrap(); | ||
b.to_async(runtime).iter_custom(|iter| async move { | ||
let (cert, key_der) = gen_cert(); | ||
let server = ServerBuilder::new_with_single_cert(vec![cert.clone()], key_der) | ||
.unwrap() | ||
.bind("127.0.0.1:0") | ||
.await | ||
.unwrap(); | ||
let client = ClientBuilder::new_with_empty_roots() | ||
.with_custom_certificate(cert) | ||
.unwrap() | ||
.with_no_crls() | ||
.bind("127.0.0.1:0") | ||
.await | ||
.unwrap(); | ||
let addr = server.local_addr().unwrap(); | ||
|
||
let (client_conn, server_conn) = futures_util::join!( | ||
async move { | ||
client | ||
.connect(addr, "localhost", None) | ||
.unwrap() | ||
.await | ||
.unwrap() | ||
}, | ||
async move { server.wait_incoming().await.unwrap().await.unwrap() } | ||
); | ||
|
||
let start = Instant::now(); | ||
let handle = compio_runtime::spawn(async move { | ||
while let Ok((mut send, mut recv)) = server_conn.accept_bi().await { | ||
compio_runtime::spawn(async move { | ||
echo_impl!(send, recv); | ||
}) | ||
.detach(); | ||
} | ||
}); | ||
for _i in 0..iter { | ||
let mut futures = (0..streams) | ||
.map(|_| async { | ||
let (mut send, mut recv) = client_conn.open_bi_wait().await.unwrap(); | ||
futures_util::join!( | ||
async { | ||
send.write_all(content).await.unwrap(); | ||
send.finish().unwrap(); | ||
}, | ||
async { | ||
let mut buf = vec![]; | ||
recv.read_to_end(&mut buf).await.unwrap(); | ||
} | ||
); | ||
}) | ||
.collect::<FuturesUnordered<_>>(); | ||
while futures.next().await.is_some() {} | ||
} | ||
drop(handle); | ||
start.elapsed() | ||
}) | ||
} | ||
|
||
fn echo_quinn(b: &mut Bencher, content: &[u8], streams: usize) { | ||
use quinn::{ClientConfig, Endpoint, ServerConfig}; | ||
|
||
let runtime = tokio::runtime::Builder::new_current_thread() | ||
.enable_all() | ||
.build() | ||
.unwrap(); | ||
b.to_async(&runtime).iter_custom(|iter| async move { | ||
let (cert, key_der) = gen_cert(); | ||
let server_config = ServerConfig::with_single_cert(vec![cert.clone()], key_der).unwrap(); | ||
let mut roots = rustls::RootCertStore::empty(); | ||
roots.add(cert).unwrap(); | ||
let client_config = ClientConfig::with_root_certificates(Arc::new(roots)).unwrap(); | ||
let server = Endpoint::server( | ||
server_config, | ||
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0), | ||
) | ||
.unwrap(); | ||
let mut client = | ||
Endpoint::client(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0)).unwrap(); | ||
client.set_default_client_config(client_config); | ||
let addr = server.local_addr().unwrap(); | ||
|
||
let (client_conn, server_conn) = futures_util::join!( | ||
async move { client.connect(addr, "localhost").unwrap().await.unwrap() }, | ||
async move { server.accept().await.unwrap().await.unwrap() } | ||
); | ||
|
||
let start = Instant::now(); | ||
tokio::spawn(async move { | ||
while let Ok((mut send, mut recv)) = server_conn.accept_bi().await { | ||
tokio::spawn(async move { | ||
echo_impl!(send, recv); | ||
}); | ||
} | ||
}); | ||
for _i in 0..iter { | ||
let mut futures = (0..streams) | ||
.map(|_| async { | ||
let (mut send, mut recv) = client_conn.open_bi().await.unwrap(); | ||
tokio::join!( | ||
async { | ||
send.write_all(content).await.unwrap(); | ||
send.finish().unwrap(); | ||
}, | ||
async { | ||
recv.read_to_end(usize::MAX).await.unwrap(); | ||
} | ||
); | ||
}) | ||
.collect::<FuturesUnordered<_>>(); | ||
while futures.next().await.is_some() {} | ||
} | ||
start.elapsed() | ||
}); | ||
} | ||
|
||
fn echo(c: &mut Criterion) { | ||
let mut rng = thread_rng(); | ||
|
||
let mut large_data = [0u8; 1024 * 1024]; | ||
rng.fill_bytes(&mut large_data); | ||
|
||
let mut small_data = [0u8; 10]; | ||
rng.fill_bytes(&mut small_data); | ||
|
||
let mut group = c.benchmark_group("echo-large-data-1-stream"); | ||
group.throughput(Throughput::Bytes((large_data.len() * 2) as u64)); | ||
|
||
group.bench_function("compio-quic", |b| echo_compio_quic(b, &large_data, 1)); | ||
group.bench_function("quinn", |b| echo_quinn(b, &large_data, 1)); | ||
|
||
group.finish(); | ||
|
||
let mut group = c.benchmark_group("echo-large-data-10-streams"); | ||
group.throughput(Throughput::Bytes((large_data.len() * 10 * 2) as u64)); | ||
|
||
group.bench_function("compio-quic", |b| echo_compio_quic(b, &large_data, 10)); | ||
group.bench_function("quinn", |b| echo_quinn(b, &large_data, 10)); | ||
|
||
group.finish(); | ||
|
||
let mut group = c.benchmark_group("echo-small-data-100-streams"); | ||
group.throughput(Throughput::Bytes((small_data.len() * 10 * 2) as u64)); | ||
|
||
group.bench_function("compio-quic", |b| echo_compio_quic(b, &small_data, 100)); | ||
group.bench_function("quinn", |b| echo_quinn(b, &small_data, 100)); | ||
|
||
group.finish(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use std::num::NonZeroUsize; | ||
|
||
use compio_dispatcher::Dispatcher; | ||
use compio_quic::{ClientBuilder, Endpoint, ServerBuilder}; | ||
use compio_runtime::spawn; | ||
use futures_util::{stream::FuturesUnordered, StreamExt}; | ||
|
||
#[compio_macros::main] | ||
async fn main() { | ||
const THREAD_NUM: usize = 5; | ||
const CLIENT_NUM: usize = 10; | ||
|
||
let rcgen::CertifiedKey { cert, key_pair } = | ||
rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); | ||
let cert = cert.der().clone(); | ||
let key_der = key_pair.serialize_der().try_into().unwrap(); | ||
|
||
let server_config = ServerBuilder::new_with_single_cert(vec![cert.clone()], key_der) | ||
.unwrap() | ||
.build(); | ||
let client_config = ClientBuilder::new_with_empty_roots() | ||
.with_custom_certificate(cert) | ||
.unwrap() | ||
.with_no_crls() | ||
.build(); | ||
let mut endpoint = Endpoint::server("127.0.0.1:0", server_config) | ||
.await | ||
.unwrap(); | ||
endpoint.default_client_config = Some(client_config); | ||
|
||
spawn({ | ||
let endpoint = endpoint.clone(); | ||
async move { | ||
let mut futures = FuturesUnordered::from_iter((0..CLIENT_NUM).map(|i| { | ||
let endpoint = &endpoint; | ||
async move { | ||
let conn = endpoint | ||
.connect(endpoint.local_addr().unwrap(), "localhost", None) | ||
.unwrap() | ||
.await | ||
.unwrap(); | ||
let mut send = conn.open_uni().unwrap(); | ||
send.write_all(format!("Hello world {}!", i).as_bytes()) | ||
.await | ||
.unwrap(); | ||
send.finish().unwrap(); | ||
send.stopped().await.unwrap(); | ||
} | ||
})); | ||
while let Some(()) = futures.next().await {} | ||
} | ||
}) | ||
.detach(); | ||
|
||
let dispatcher = Dispatcher::builder() | ||
.worker_threads(NonZeroUsize::new(THREAD_NUM).unwrap()) | ||
.build() | ||
.unwrap(); | ||
let mut handles = FuturesUnordered::new(); | ||
for _i in 0..CLIENT_NUM { | ||
let incoming = endpoint.wait_incoming().await.unwrap(); | ||
let handle = dispatcher | ||
.dispatch(move || async move { | ||
let conn = incoming.await.unwrap(); | ||
let mut recv = conn.accept_uni().await.unwrap(); | ||
let mut buf = vec![]; | ||
recv.read_to_end(&mut buf).await.unwrap(); | ||
println!("{}", std::str::from_utf8(&buf).unwrap()); | ||
}) | ||
.unwrap(); | ||
handles.push(handle); | ||
} | ||
while handles.next().await.is_some() {} | ||
dispatcher.join().await.unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.