/* * Copyright (C) 2020 Fanout, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use condure::connection::testutil::{ BenchServerReqConnection, BenchServerReqHandler, BenchServerStreamConnection, BenchServerStreamHandler, }; use condure::executor::Executor; use condure::future::{AsyncReadExt, AsyncTcpStream, AsyncWriteExt}; use condure::reactor::Reactor; use condure::server::TestServer; use condure::websocket::testutil::{BenchRecvMessage, BenchSendMessage}; use criterion::{criterion_group, criterion_main, Criterion}; use std::io::{self, Write}; use std::net::SocketAddr; use std::str; const REQS_PER_ITER: usize = 10; fn req(addr: SocketAddr) { let reactor = Reactor::new(REQS_PER_ITER * 10); let executor = Executor::new(REQS_PER_ITER); for _ in 0..REQS_PER_ITER { executor .spawn(async move { let mut client = AsyncTcpStream::connect(&[addr]).await.unwrap(); client .write(b"GET /hello HTTP/1.0\r\nHost: example.com\r\n\r\n") .await .unwrap(); let mut resp = [0u8; 1024]; let mut resp = io::Cursor::new(&mut resp[..]); loop { let mut buf = [0; 1024]; let size = client.read(&mut buf).await.unwrap(); if size == 0 { break; } resp.write(&buf[..size]).unwrap(); } let size = resp.position() as usize; let resp = str::from_utf8(&resp.get_ref()[..size]).unwrap(); assert_eq!(resp, "HTTP/1.0 200 OK\r\nContent-Length: 6\r\n\r\nworld\n"); }) .unwrap(); } executor.run(|timeout| reactor.poll(timeout)).unwrap(); } fn criterion_benchmark(c: &mut Criterion) { { let t = BenchServerReqHandler::new(); c.bench_function("req_handler", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchServerStreamHandler::new(); c.bench_function("stream_handler", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchServerReqConnection::new(); c.bench_function("req_connection", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchServerStreamConnection::new(); c.bench_function("stream_connection", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchSendMessage::new(false); c.bench_function("ws_send", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchSendMessage::new(true); c.bench_function("ws_send_deflate", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchRecvMessage::new(false); c.bench_function("ws_recv", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let t = BenchRecvMessage::new(true); c.bench_function("ws_recv_deflate", |b| { b.iter_batched_ref(|| t.init(), |i| t.run(i), criterion::BatchSize::SmallInput) }); } { let server = TestServer::new(1); let req_addr = server.req_addr(); let stream_addr = server.stream_addr(); c.bench_function("req_server workers=1", |b| b.iter(|| req(req_addr))); c.bench_function("stream_server workers=1", |b| b.iter(|| req(stream_addr))); } { let server = TestServer::new(2); let req_addr = server.req_addr(); let stream_addr = server.stream_addr(); c.bench_function("req_server workers=2", |b| b.iter(|| req(req_addr))); c.bench_function("stream_server workers=2", |b| b.iter(|| req(stream_addr))); } } criterion_group!(benches, criterion_benchmark); criterion_main!(benches);