diff --git a/Cargo.toml b/Cargo.toml index a0ad89c..2677fd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ http = "1.1.0" http-body = "1.0.1" http-body-util = "0.1.2" hyper = "1.4.1" -hyper-rustls = { version = "0.27.3", features = ["http2"] } hyper-util = { version = "0.1.8", features = ["server", "tokio", "server-auto", "server-graceful", "service"] } pin-project = "1.1.5" rand = "0.9.0-alpha.2" @@ -40,13 +39,16 @@ pprof = { version = "0.13.0", features = ["flamegraph"], optional = true} [dev-dependencies] criterion = { version = "0.5.1", features = ["html_reports", "async_tokio"] } +hyper-rustls = { version = "0.27.3", features = ["http1", "http2"] } +hyper-util = { version = "0.1.8", features = ["client", "client-legacy", "http2"] } hyper = { version = "1.4.1", features = ["client"] } -tokio = { version = "1.40", features = ["rt", "net", "test-util"] } +tokio = { version = "1.40", features = ["rt-multi-thread", "net", "test-util", "time"] } tokio-util = { version = "0.7.12", features = ["compat"] } tracing-subscriber = "0.3.18" num_cpus = "1.16.0" ring = "0.17.8" rcgen = "0.13.1" +reqwest = { version = "0.12.7", features = ["rustls-tls", "http2"] } [[bench]] name = "hello_world_tower_hyper_tls_tcp" @@ -58,4 +60,4 @@ jemalloc = ["tikv-jemallocator"] dev-profiling = ["pprof"] [profile.release] -debug = true \ No newline at end of file +debug = true diff --git a/benches/hello_world_tower_hyper_tls_tcp.rs b/benches/hello_world_tower_hyper_tls_tcp.rs index 4312419..679bbe5 100644 --- a/benches/hello_world_tower_hyper_tls_tcp.rs +++ b/benches/hello_world_tower_hyper_tls_tcp.rs @@ -24,15 +24,14 @@ use std::sync::Arc; use bytes::Bytes; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use http::{Request, Response, StatusCode, Uri}; -use http_body_util::{BodyExt, Empty, Full}; +use http_body_util::{BodyExt, Full}; use hyper::body::Incoming; -use hyper_rustls::HttpsConnectorBuilder; -use hyper_util::client::legacy::Client; use hyper_util::rt::TokioExecutor; use hyper_util::server::conn::auto::Builder as HttpConnectionBuilder; use hyper_util::service::TowerToHyperService; use rcgen::{CertificateParams, DistinguishedName, KeyPair}; -use rustls::crypto::aws_lc_rs::Ticketer; +use reqwest::Client; +use rustls::crypto::aws_lc_rs::{default_provider, Ticketer}; use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; use rustls::server::ServerSessionMemoryCache; use rustls::{ClientConfig, RootCertStore, ServerConfig}; @@ -275,25 +274,19 @@ async fn start_server( } async fn send_request( - client: &Client< - hyper_rustls::HttpsConnector, - Empty, - >, + client: &Client, url: Uri, ) -> Result<(Duration, usize), Box> { let start = Instant::now(); - let res = client.get(url).await?; + let res = client.get(url.to_string()).send().await?; assert_eq!(res.status(), StatusCode::OK); - let body = res.into_body().collect().await?.to_bytes(); + let body = res.bytes().await?; assert_eq!(&body[..], b"Hello, World!"); Ok((start.elapsed(), body.len())) } async fn concurrent_benchmark( - client: &Client< - hyper_rustls::HttpsConnector, - Empty, - >, + client: &Client, url: Uri, num_requests: usize, ) -> (Duration, Vec, usize) { @@ -322,22 +315,46 @@ async fn concurrent_benchmark( } fn bench_server(c: &mut Criterion) { - let server_runtime = Arc::new(create_optimized_runtime(num_cpus::get() / 2).unwrap()); + let bench_runtime = create_optimized_runtime(num_cpus::get() / 2).unwrap(); + + let (server_addr, shutdown_tx, client) = bench_runtime.block_on(async { + // Install the default provider for AWS LC RS crypto + default_provider().install_default().unwrap(); - let (server_addr, shutdown_tx, client) = server_runtime.block_on(async { let tls_config = generate_shared_ecdsa_config(); let (server_addr, shutdown_tx) = start_server(tls_config.server_config.clone()) .await .expect("Failed to start server"); info!("Server started on {}", server_addr); - let https = HttpsConnectorBuilder::new() - .with_tls_config(tls_config.client_config) - .https_or_http() - .enable_http1() - .build(); - - let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(https); + // Unfortunately hyper based http2 seems pretty busted here + // around not finding the tokio runtime timer + // https://github.com/rustls/hyper-rustls/issues/287 + // let https = HttpsConnectorBuilder::new() + // .with_tls_config(tls_config.client_config) + // .https_or_http() + // .enable_all_versions() + // .build(); + // + // let client: Client<_, Empty> = Client::builder(TokioExecutor::new()) + // .timer(TokioTimer::new()) + // .pool_timer(TokioTimer::new()) + // .build(https); + + let client = reqwest::Client::builder() + .use_rustls_tls() + // This breaks for the same reason that the hyper-tls/hyper client does + //.http2_prior_knowledge() + // Increase connection pool size for better concurrency + .pool_max_idle_per_host(1250) + // Enable TCP keepalive + .tcp_keepalive(Some(Duration::from_secs(10))) + // Disable automatic redirect following to reduce overhead + .redirect(reqwest::redirect::Policy::none()) + // Use preconfigured TLS settings from the shared config + .use_preconfigured_tls(tls_config.client_config) + .build() + .expect("Failed to build reqwest client"); (server_addr, shutdown_tx, client) }); @@ -358,8 +375,7 @@ fn bench_server(c: &mut Criterion) { group.bench_function("serial_latency", |b| { let client = client.clone(); let url = url.clone(); - let client_runtime = create_optimized_runtime(num_cpus::get() / 2).unwrap(); - b.to_async(client_runtime) + b.to_async(&bench_runtime) .iter(|| async { send_request(&client, url.clone()).await.unwrap() }); }); @@ -373,8 +389,7 @@ fn bench_server(c: &mut Criterion) { |b, &num_requests| { let client = client.clone(); let url = url.clone(); - let client_runtime = create_optimized_runtime(num_cpus::get() / 2).unwrap(); - b.to_async(client_runtime).iter(|| async { + b.to_async(&bench_runtime).iter(|| async { concurrent_benchmark(&client, url.clone(), num_requests).await }); }, @@ -383,7 +398,7 @@ fn bench_server(c: &mut Criterion) { group.finish(); - server_runtime.block_on(async { + bench_runtime.block_on(async { shutdown_tx.send(()).unwrap(); tokio::time::sleep(Duration::from_secs(1)).await; }); diff --git a/flamegraph.svg b/flamegraph.svg deleted file mode 100644 index 8aff83e..0000000 --- a/flamegraph.svg +++ /dev/null @@ -1,491 +0,0 @@ -Flame Graph Reset ZoomSearch bytes::bytes::shared_clone (1 samples, 0.30%)core::ptr::drop_in_place<alloc::boxed::Box<tokio::runtime::task::core::Cell<hello_world_tower_hyper_tls_tcp::concurrent_benchmark::{{closure}}::{{closure}},alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>>> (1 samples, 0.30%)core::ptr::drop_in_place<hyper_util::client::legacy::client::Error> (3 samples, 0.90%)core::ptr::drop_in_place<hyper_util::client::legacy::connect::http::ConnectError> (2 samples, 0.60%)_rjem_je_sdallocx_default (1 samples, 0.30%)_rjem_je_tcache_bin_flush_small (1 samples, 0.30%)hello_world_tow (6 samples, 1.79%)h.._start (6 samples, 1.79%)_..__libc_start_main (6 samples, 1.79%)_..main (6 samples, 1.79%)m..std::rt::lang_start_internal (6 samples, 1.79%)s..std::rt::lang_start::{{closure}} (6 samples, 1.79%)s..std::sys::backtrace::__rust_begin_short_backtrace (6 samples, 1.79%)s..hello_world_tower_hyper_tls_tcp::main (6 samples, 1.79%)h..criterion::benchmark_group::BenchmarkGroup<M>::bench_with_input (6 samples, 1.79%)c..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (6 samples, 1.79%)<..criterion::bencher::AsyncBencher<A,M>::iter (6 samples, 1.79%)c..<tokio::runtime::runtime::Runtime as criterion::async_executor::AsyncExecutor>::block_on (6 samples, 1.79%)<..tokio::task::spawn::spawn (1 samples, 0.30%)_rjem_je_tsd_cleanup (1 samples, 0.30%)tcache_destroy.constprop.0 (1 samples, 0.30%)_rjem_je_tcache_bin_flush_small (1 samples, 0.30%)_rjem_je_arena_slab_dalloc (1 samples, 0.30%)pac_dalloc_impl (1 samples, 0.30%)_rjem_je_extent_record (1 samples, 0.30%)extent_try_coalesce_impl (1 samples, 0.30%)extent_merge_impl.constprop.0 (1 samples, 0.30%)_rjem_je_edata_cache_put (1 samples, 0.30%)std::sys::sync::mutex::futex::Mutex::lock_contended (8 samples, 2.39%)st..syscall (6 samples, 1.79%)s..std::sys::sync::condvar::futex::Condvar::wait_timeout (13 samples, 3.88%)std:..syscall (5 samples, 1.49%)std::sys::sync::mutex::futex::Mutex::lock_contended (2 samples, 0.60%)syscall (1 samples, 0.30%)syscall (2 samples, 0.60%)__file_change_detection_for_path (2 samples, 0.60%)fstatat64 (2 samples, 0.60%)__lll_lock_wake_private (2 samples, 0.60%)__lll_lock_wait_private (1 samples, 0.30%)__resolv_context_get (7 samples, 2.09%)_..__lll_lock_wake_private (3 samples, 0.90%)__resolv_context_put (3 samples, 0.90%)__clock_gettime (1 samples, 0.30%)__res_context_mkquery (2 samples, 0.60%)__ns_name_compress (1 samples, 0.30%)__ns_name_pack (1 samples, 0.30%)__poll (1 samples, 0.30%)__socket (3 samples, 0.90%)<std::sys_common::net::LookupHost as core::convert::TryFrom<(&str,u16)>>::try_from::{{closure}} (23 samples, 6.87%)<std::sys..getaddrinfo (23 samples, 6.87%)getaddrin.._nss_dns_gethostbyname4_r (9 samples, 2.69%)_n..__res_context_search (9 samples, 2.69%)__..__res_context_query (8 samples, 2.39%)__..__res_context_send (5 samples, 1.49%)ioctl (1 samples, 0.30%)<(&str,u16) as std::net::socket_addr::ToSocketAddrs>::to_socket_addrs (25 samples, 7.46%)<(&str,u16..core::net::parser::Parser::read_ipv4_addr (2 samples, 0.60%)tokio::runtime::scheduler::multi_thread::worker::<impl tokio::runtime::scheduler::multi_thread::handle::Handle>::next_remote_task (2 samples, 0.60%)std::sys::sync::mutex::futex::Mutex::lock_contended (1 samples, 0.30%)syscall (1 samples, 0.30%)tokio::runtime::time::<impl tokio::runtime::time::handle::Handle>::process_at_time (3 samples, 0.90%)tokio::runtime::time::<impl tokio::runtime::time::handle::Handle>::process_at_sharded_time (3 samples, 0.90%)tokio::runtime::io::driver::Driver::turn (3 samples, 0.90%)epoll_wait (2 samples, 0.60%)tokio::runtime::scheduler::multi_thread::worker::Context::park_timeout (8 samples, 2.39%)to..tokio::runtime::time::Driver::park_internal (4 samples, 1.19%)tokio::runtime::time::wheel::Wheel::next_expiration (1 samples, 0.30%)<rustls::client::hs::ExpectServerHelloOrHelloRetryRequest as rustls::common_state::State<rustls::client::client_conn::ClientConnectionData>>::handle (1 samples, 0.30%)<rustls::client::hs::ExpectServerHello as rustls::common_state::State<rustls::client::client_conn::ClientConnectionData>>::handle (1 samples, 0.30%)rustls::hash_hs::HandshakeHashBuffer::start_hash (1 samples, 0.30%)<futures_util::future::either::Either<A,B> as core::future::future::Future>::poll (3 samples, 0.90%)<hyper_rustls::connector::HttpsConnector<T> as tower_service::Service<http::uri::Uri>>::call::{{closure}} (2 samples, 0.60%)tokio_rustls::common::Stream<IO,C>::read_io (2 samples, 0.60%)<rustls::client::tls13::ExpectCertificateOrCompressedCertificateOrCertReq as rustls::common_state::State<rustls::client::client_conn::ClientConnectionData>>::handle (1 samples, 0.30%)<rustls::client::tls13::ExpectCompressedCertificate as rustls::common_state::State<rustls::client::client_conn::ClientConnectionData>>::handle (1 samples, 0.30%)<rustls::compress::feat_zlib_rs::ZlibRsDecompressor as rustls::compress::CertDecompressor>::decompress (1 samples, 0.30%)zlib_rs::inflate::State::len (1 samples, 0.30%)zlib_rs::inflate::State::check (1 samples, 0.30%)zlib_rs::adler32::adler32 (1 samples, 0.30%)<rustls::conn::ConnectionCommon<T> as rustls::conn::connection::PlaintextSink>::write (1 samples, 0.30%)rustls::common_state::CommonState::send_appdata_encrypt (1 samples, 0.30%)rustls::common_state::CommonState::send_single_fragment (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::tls13::GcmMessageEncrypter as rustls::crypto::cipher::MessageEncrypter>::encrypt (1 samples, 0.30%)aws_lc_rs::aead::unbound_key::UnboundKey::seal_in_place_append_tag (1 samples, 0.30%)aws_lc_0_21_1_EVP_AEAD_CTX_seal (1 samples, 0.30%)aead_aes_gcm_tls13_seal_scatter (1 samples, 0.30%)aead_aes_gcm_seal_scatter_impl (1 samples, 0.30%)aws_lc_0_21_1_CRYPTO_gcm128_aad (1 samples, 0.30%)hyper::proto::h1::conn::Conn<I,B,T>::poll_flush (2 samples, 0.60%)<tokio_rustls::client::TlsStream<IO> as tokio::io::async_write::AsyncWrite>::poll_write (2 samples, 0.60%)rustls::vecbuf::ChunkVecBuffer::write_to (1 samples, 0.30%)rustls::vecbuf::ChunkVecBuffer::consume (1 samples, 0.30%)<futures_util::future::future::Map<Fut,F> as core::future::future::Future>::poll (7 samples, 2.09%)<..<hyper::client::conn::http1::upgrades::UpgradeableConnection<I,B> as core::future::future::Future>::poll (4 samples, 1.19%)hyper::proto::h1::io::Buffered<T,B>::poll_read_from_io (1 samples, 0.30%)<hyper_util::rt::tokio::TokioIo<T> as hyper::rt::io::Read>::poll_read (1 samples, 0.30%)<http_body_util::combinators::collect::Collect<T> as core::future::future::Future>::poll (1 samples, 0.30%)<hyper::body::incoming::Incoming as http_body::Body>::poll_frame (1 samples, 0.30%)<hyper::proto::h1::dispatch::Server<S,hyper::body::incoming::Incoming> as hyper::proto::h1::dispatch::Dispatch>::recv_msg (1 samples, 0.30%)<hyper_util::server::conn::auto::UpgradeableConnection<I,S,E> as core::future::future::Future>::poll (2 samples, 0.60%)<hyper::server::conn::http1::UpgradeableConnection<I,S> as core::future::future::Future>::poll (2 samples, 0.60%)hyper::proto::h1::conn::Conn<I,B,T>::poll_read_head (1 samples, 0.30%)http::header::map::HeaderMap<T>::try_append2 (1 samples, 0.30%)_rjem_malloc (1 samples, 0.30%)_rjem_malloc (1 samples, 0.30%)accept4 (4 samples, 1.19%)<core::pin::Pin<P> as futures_core::stream::Stream>::poll_next (6 samples, 1.79%)<..tokio::io::poll_evented::PollEvented<E>::new_with_interest (1 samples, 0.30%)tokio::runtime::io::registration_set::RegistrationSet::allocate (1 samples, 0.30%)<tokio::io::poll_evented::PollEvented<E> as core::ops::drop::Drop>::drop (1 samples, 0.30%)epoll_ctl (1 samples, 0.30%)__close (6 samples, 1.79%)_..<rustls::crypto::aws_lc_rs::hash::Hash as rustls::crypto::hash::Hash>::start (1 samples, 0.30%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.30%)rustls::common_state::CommonState::send_msg (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::hash::Context as rustls::crypto::hash::Context>::fork_finish (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::hash::Context as rustls::crypto::hash::Context>::update (1 samples, 0.30%)aws_lc_0_21_1_EVP_DigestUpdate (1 samples, 0.30%)sha384_update (1 samples, 0.30%)aws_lc_0_21_1_SHA512_Update (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)aws_lc_0_21_1_BN_uadd (1 samples, 0.30%)aws_lc_0_21_1_bn_uadd_consttime (1 samples, 0.30%)aws_lc_0_21_1_bn_add_words (1 samples, 0.30%)aws_lc_0_21_1_bn_is_bit_set_words (1 samples, 0.30%)aws_lc_0_21_1_BN_mod_inverse_blinded (3 samples, 0.90%)aws_lc_0_21_1_BN_mod_inverse_odd (3 samples, 0.90%)bn_cmp_words_consttime (1 samples, 0.30%)bn_mulx4x_mont (1 samples, 0.30%)aws_lc_0_21_1_BN_BLINDING_convert (6 samples, 1.79%)a..aws_lc_0_21_1_BN_mod_mul_montgomery (3 samples, 0.90%)bn_sqr8x_mont (2 samples, 0.60%)aws_lc_0_21_1_bn_sqrx8x_internal (2 samples, 0.60%)aws_lc_0_21_1_BN_from_montgomery (1 samples, 0.30%)bn_from_montgomery_in_place (1 samples, 0.30%)aws_lc_0_21_1_BN_mod_mul_montgomery (2 samples, 0.60%)bn_sqr8x_mont (2 samples, 0.60%)aws_lc_0_21_1_bn_sqrx8x_internal (2 samples, 0.60%)aws_lc_0_21_1_BN_mod_exp_mont (3 samples, 0.90%)aws_lc_0_21_1_BN_num_bits (1 samples, 0.30%)aws_lc_0_21_1_bn_minimal_width (1 samples, 0.30%)aws_lc_0_21_1_bn_gather5 (1 samples, 0.30%)bn_mulx4x_mont_gather5 (3 samples, 0.90%)mulx4x_internal (3 samples, 0.90%)__bn_postx4x_internal (3 samples, 0.90%)aws_lc_0_21_1_bn_sqrx8x_internal (109 samples, 32.54%)aws_lc_0_21_1_bn_sqrx8x_internalbn_powerx5 (152 samples, 45.37%)bn_powerx5mulx4x_internal (39 samples, 11.64%)mulx4x_internalrustls::server::tls13::client_hello::emit_certificate_verify_tls13 (171 samples, 51.04%)rustls::server::tls13::client_hello::emit_certificate_verify_tls13<rustls::crypto::aws_lc_rs::sign::RsaSigner as rustls::crypto::signer::Signer>::sign (169 samples, 50.45%)<rustls::crypto::aws_lc_rs::sign::RsaSigner as rustls::crypto::signer::Signer>::signaws_lc_0_21_1_EVP_DigestSignFinal (169 samples, 50.45%)aws_lc_0_21_1_EVP_DigestSignFinalpkey_rsa_sign (169 samples, 50.45%)pkey_rsa_signaws_lc_0_21_1_RSA_sign_pss_mgf1 (169 samples, 50.45%)aws_lc_0_21_1_RSA_sign_pss_mgf1aws_lc_0_21_1_rsa_default_sign_raw (169 samples, 50.45%)aws_lc_0_21_1_rsa_default_sign_rawaws_lc_0_21_1_rsa_default_private_transform (169 samples, 50.45%)aws_lc_0_21_1_rsa_default_private_transformaws_lc_0_21_1_BN_mod_exp_mont_consttime (159 samples, 47.46%)aws_lc_0_21_1_BN_mod_exp_mont_consttimebn_sqr8x_mont (3 samples, 0.90%)aws_lc_0_21_1_bn_sqrx8x_internal (3 samples, 0.90%)rustls::server::tls13::client_hello::emit_compressed_certificate_tls13 (3 samples, 0.90%)<rustls::crypto::aws_lc_rs::hash::Context as rustls::crypto::hash::Context>::update (3 samples, 0.90%)aws_lc_0_21_1_EVP_DigestUpdate (3 samples, 0.90%)sha384_update (3 samples, 0.90%)aws_lc_0_21_1_SHA512_Update (3 samples, 0.90%)aws_lc_0_21_1_sha512_block_data_order_nohw (3 samples, 0.90%)rustls::tls13::key_schedule::KeySchedule::set_encrypter (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::tls13::RingHkdfExpander as rustls::crypto::tls13::HkdfExpander>::expand_slice (1 samples, 0.30%)aws_lc_rs::hkdf::Okm<L>::fill (1 samples, 0.30%)aws_lc_0_21_1_HKDF_expand (1 samples, 0.30%)aws_lc_0_21_1_HMAC_Final (1 samples, 0.30%)aws_lc_0_21_1_SHA384_Final (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)aws_lc_0_21_1_HKDF_expand (1 samples, 0.30%)aws_lc_0_21_1_HMAC_Final (1 samples, 0.30%)aws_lc_0_21_1_SHA384_Final (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)rustls::server::tls13::client_hello::emit_finished_tls13 (4 samples, 1.19%)rustls::tls13::key_schedule::KeyScheduleTraffic::new (3 samples, 0.90%)rustls::tls13::key_schedule::KeySchedule::derive_logged_secret (3 samples, 0.90%)<rustls::crypto::aws_lc_rs::tls13::RingHkdfExpander as rustls::crypto::tls13::HkdfExpander>::expand_block (3 samples, 0.90%)aws_lc_rs::hkdf::Okm<L>::fill (3 samples, 0.90%)aws_lc_0_21_1_HKDF (3 samples, 0.90%)aws_lc_0_21_1_HKDF_extract (2 samples, 0.60%)aws_lc_0_21_1_HMAC (2 samples, 0.60%)aws_lc_0_21_1_HMAC_Final (1 samples, 0.30%)aws_lc_0_21_1_SHA384_Final (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::hash::Context as rustls::crypto::hash::Context>::finish (1 samples, 0.30%)aws_lc_0_21_1_EVP_DigestFinal (1 samples, 0.30%)aws_lc_0_21_1_EVP_DigestFinal_ex (1 samples, 0.30%)sha384_final (1 samples, 0.30%)aws_lc_0_21_1_SHA384_Final (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)rustls::crypto::SupportedKxGroup::start_and_complete (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::kx::KxGroup as rustls::crypto::SupportedKxGroup>::start (1 samples, 0.30%)aws_lc_0_21_1_EVP_PKEY_keygen (1 samples, 0.30%)pkey_x25519_keygen (1 samples, 0.30%)aws_lc_0_21_1_X25519_keypair (1 samples, 0.30%)aws_lc_0_21_1_RAND_bytes (1 samples, 0.30%)aws_lc_0_21_1_RAND_bytes_with_additional_data.part.0 (1 samples, 0.30%)aws_lc_0_21_1_CTR_DRBG_generate (1 samples, 0.30%)ctr_drbg_update.part.0 (1 samples, 0.30%)aws_lc_0_21_1_aes_ctr_set_key (1 samples, 0.30%)aws_lc_0_21_1_aes_hw_set_encrypt_key (1 samples, 0.30%)rustls::tls13::key_schedule::KeyScheduleHandshakeStart::into_handshake (1 samples, 0.30%)rustls::tls13::key_schedule::KeySchedule::derive_logged_secret (1 samples, 0.30%)<rustls::crypto::aws_lc_rs::tls13::RingHkdfExpander as rustls::crypto::tls13::HkdfExpander>::expand_block (1 samples, 0.30%)aws_lc_rs::hkdf::Okm<L>::fill (1 samples, 0.30%)aws_lc_0_21_1_HKDF (1 samples, 0.30%)aws_lc_0_21_1_HKDF_expand (1 samples, 0.30%)aws_lc_0_21_1_HMAC_Init_ex (1 samples, 0.30%)aws_lc_0_21_1_SHA512_Update (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)aws_lc_0_21_1_HMAC_Final (1 samples, 0.30%)aws_lc_0_21_1_SHA384_Final (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)hello_world_tower_hyper_tls_tcp::start_server::{{closure}}::{{closure}} (202 samples, 60.30%)hello_world_tower_hyper_tls_tcp::start_server::{{closure}}::{{closure}}tokio_rustls::common::Stream<IO,C>::read_io (189 samples, 56.42%)tokio_rustls::common::Stream<IO,C>::read_io<rustls::server::hs::ExpectClientHello as rustls::common_state::State<rustls::server::server_conn::ServerConnectionData>>::handle (189 samples, 56.42%)<rustls::server::hs::ExpectClientHello as rustls::common_state::State<rustls::server::server_..rustls::server::hs::ExpectClientHello::with_certified_key (188 samples, 56.12%)rustls::server::hs::ExpectClientHello::with_certified_keyrustls::server::tls13::client_hello::emit_server_hello (6 samples, 1.79%)r..rustls::tls13::key_schedule::KeySchedulePreHandshake::into_handshake (3 samples, 0.90%)<rustls::crypto::aws_lc_rs::tls13::RingHkdfExpander as rustls::crypto::tls13::HkdfExpander>::expand_block (3 samples, 0.90%)aws_lc_rs::hkdf::Okm<L>::fill (2 samples, 0.60%)aws_lc_0_21_1_HKDF (2 samples, 0.60%)aws_lc_0_21_1_HKDF_expand (2 samples, 0.60%)aws_lc_0_21_1_HMAC_Init_ex (1 samples, 0.30%)aws_lc_0_21_1_SHA512_Update (1 samples, 0.30%)aws_lc_0_21_1_sha512_block_data_order_nohw (1 samples, 0.30%)hyper_util::client::legacy::client::Client<C,B>::get (3 samples, 0.90%)_rjem_je_malloc_default (1 samples, 0.30%)_rjem_je_tsd_fetch_slow (1 samples, 0.30%)_rjem_je_tsd_tcache_enabled_data_init (1 samples, 0.30%)_rjem_je_tsd_tcache_data_init (1 samples, 0.30%)_rjem_je_large_palloc (1 samples, 0.30%)_rjem_je_arena_extent_alloc_large (1 samples, 0.30%)_rjem_je_pa_alloc (1 samples, 0.30%)pac_alloc_impl (1 samples, 0.30%)pac_alloc_real (1 samples, 0.30%)_rjem_je_ecache_alloc (1 samples, 0.30%)extent_recycle (1 samples, 0.30%)_rjem_je_eset_remove (1 samples, 0.30%)<tokio::io::poll_evented::PollEvented<E> as core::ops::drop::Drop>::drop (1 samples, 0.30%)epoll_ctl (1 samples, 0.30%)<core::pin::Pin<P> as core::future::future::Future>::poll (3 samples, 0.90%)tokio::net::tcp::socket::TcpSocket::connect::{{closure}} (2 samples, 0.60%)__close (1 samples, 0.30%)<hyper_util::client::legacy::connect::http::HttpConnector<R> as tower_service::Service<http::uri::Uri>>::call::{{closure}} (4 samples, 1.19%)setsockopt (1 samples, 0.30%)<futures_util::future::either::Either<A,B> as core::future::future::Future>::poll (5 samples, 1.49%)<hyper_rustls::connector::HttpsConnector<T> as tower_service::Service<http::uri::Uri>>::call::{{closure}} (5 samples, 1.49%)_rjem_je_sdallocx_default (1 samples, 0.30%)_rjem_je_te_event_trigger (1 samples, 0.30%)_rjem_je_tcache_gc_dalloc_event_handler (1 samples, 0.30%)tcache_gc_small (1 samples, 0.30%)_rjem_je_tcache_bin_flush_small (1 samples, 0.30%)_rjem_je_arena_slab_dalloc (1 samples, 0.30%)pac_dalloc_impl (1 samples, 0.30%)_rjem_je_extent_record (1 samples, 0.30%)extent_try_coalesce_impl (1 samples, 0.30%)_rjem_je_emap_try_acquire_edata_neighbor (1 samples, 0.30%)emap_try_acquire_edata_neighbor_impl (1 samples, 0.30%)<http::uri::Uri as core::clone::Clone>::clone (1 samples, 0.30%)bytes::bytes::shared_drop (1 samples, 0.30%)hyper_util::client::legacy::pool::Pool<T,K>::reuse (1 samples, 0.30%)bytes::bytes::shared_clone (1 samples, 0.30%)<hyper_util::client::legacy::pool::Checkout<T,K> as core::future::future::Future>::poll (3 samples, 0.90%)std::sys::sync::mutex::futex::Mutex::lock_contended (1 samples, 0.30%)<http::uri::scheme::Scheme as core::cmp::PartialEq>::eq (1 samples, 0.30%)std::sys::sync::mutex::futex::Mutex::lock_contended (3 samples, 0.90%)syscall (2 samples, 0.60%)<hyper_util::common::lazy::Lazy<F,R> as core::future::future::Future>::poll (12 samples, 3.58%)<hyp..<futures_util::future::either::Either<A,B> as core::future::future::Future>::poll (12 samples, 3.58%)<fut..<hyper_rustls::connector::HttpsConnector<T> as tower_service::Service<http::uri::Uri>>::call::{{closure}} (9 samples, 2.69%)<h..<hyper_util::client::legacy::connect::http::HttpConnector<R> as tower_service::Service<http::uri::Uri>>::call::{{closure}} (9 samples, 2.69%)<h..tokio::runtime::blocking::pool::Spawner::spawn_task (9 samples, 2.69%)to..syscall (4 samples, 1.19%)bytes::bytes::shared_clone (1 samples, 0.30%)core::ptr::drop_in_place<http::request::Parts> (1 samples, 0.30%)core::ptr::drop_in_place<http::uri::Uri> (1 samples, 0.30%)bytes::bytes::shared_drop (1 samples, 0.30%)core::ptr::drop_in_place<hyper_util::client::legacy::client::Client<hyper_rustls::connector::HttpsConnector<hyper_util::client::legacy::connect::http::HttpConnector>,http_body_util::empty::Empty<bytes::bytes::Bytes>>>.5092 (1 samples, 0.30%)core::ptr::drop_in_place<hyper_rustls::connector::HttpsConnector<hyper_util::client::legacy::connect::http::HttpConnector>> (1 samples, 0.30%)core::ptr::drop_in_place<[futures_channel::oneshot::Sender<hyper_util::client::legacy::client::PoolClient<http_body_util::empty::Empty<bytes::bytes::Bytes>>>]> (2 samples, 0.60%)std::sys::sync::mutex::futex::Mutex::lock_contended (2 samples, 0.60%)core::ptr::drop_in_place<hyper_util::client::legacy::pool::Checkout<hyper_util::client::legacy::client::PoolClient<http_body_util::empty::Empty<bytes::bytes::Bytes>>,(http::uri::scheme::Scheme,http::uri::authority::Authority)>> (10 samples, 2.99%)cor..syscall (1 samples, 0.30%)core::ptr::drop_in_place<hyper_util::client::legacy::pool::Pooled<hyper_util::client::legacy::client::PoolClient<http_body_util::empty::Empty<bytes::bytes::Bytes>>,(http::uri::scheme::Scheme,http::uri::authority::Authority)>> (2 samples, 0.60%)<hyper_util::client::legacy::pool::Pooled<T,K> as core::ops::drop::Drop>::drop (2 samples, 0.60%)hyper_util::client::legacy::pool::PoolInner<T,K>::put (2 samples, 0.60%)core::hash::BuildHasher::hash_one (2 samples, 0.60%)<std::hash::random::DefaultHasher as core::hash::Hasher>::write.6187 (1 samples, 0.30%)tokio::runtime::task::core::Core<T,S>::poll (254 samples, 75.82%)tokio::runtime::task::core::Core<T,S>::pollhyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}} (38 samples, 11.34%)hyper_util::clien..hyper_util::client::legacy::client::Client<C,B>::connect_to (1 samples, 0.30%)tokio::runtime::scheduler::multi_thread::worker::Context::run_task (255 samples, 76.12%)tokio::runtime::scheduler::multi_thread::worker::Context::run_tasktokio::runtime::task::raw::poll (255 samples, 76.12%)tokio::runtime::task::raw::polltokio::runtime::task::harness::Harness<T,S>::complete (1 samples, 0.30%)tokio::runtime::scheduler::multi_thread::worker::<impl tokio::runtime::task::Schedule for alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>::release (1 samples, 0.30%)tokio::runtime::task::harness::Harness<T,S>::complete (4 samples, 1.19%)tokio::runtime::task::raw::schedule (4 samples, 1.19%)tokio::runtime::context::with_scheduler (4 samples, 1.19%)tokio::runtime::scheduler::multi_thread::worker::<impl tokio::runtime::scheduler::multi_thread::handle::Handle>::push_remote_task (4 samples, 1.19%)std::sys::sync::mutex::futex::Mutex::lock_contended (3 samples, 0.90%)all (335 samples, 100%)tokio-runtime-w (329 samples, 98.21%)tokio-runtime-wstd::sys::pal::unix::thread::Thread::new::thread_start (316 samples, 94.33%)std::sys::pal::unix::thread::Thread::new::thread_startcore::ops::function::FnOnce::call_once{{vtable.shim}} (316 samples, 94.33%)core::ops::function::FnOnce::call_once{{vtable.shim}}std::sys::backtrace::__rust_begin_short_backtrace (316 samples, 94.33%)std::sys::backtrace::__rust_begin_short_backtracetokio::runtime::task::raw::poll (299 samples, 89.25%)tokio::runtime::task::raw::polltokio::runtime::task::raw::shutdown (1 samples, 0.30%)tokio::runtime::task::core::Core<T,S>::set_stage (1 samples, 0.30%)core::ptr::drop_in_place<tokio::runtime::task::core::Stage<core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future+Output = ()+core::marker::Send>>>> (1 samples, 0.30%)core::ptr::drop_in_place<futures_util::fns::MapOkFn<hyper_util::client::legacy::client::Client<hyper_rustls::connector::HttpsConnector<hyper_util::client::legacy::connect::http::HttpConnector>,http_body_util::empty::Empty<bytes::bytes::Bytes>>::connect_to::{{closure}}::{{closure}}>> (1 samples, 0.30%)core::ptr::drop_in_place<hyper_util::client::legacy::pool::Connecting<hyper_util::client::legacy::client::PoolClient<http_body_util::empty::Empty<bytes::bytes::Bytes>>,(http::uri::scheme::Scheme,http::uri::authority::Authority)>> (1 samples, 0.30%)bytes::bytes::shared_drop (1 samples, 0.30%) \ No newline at end of file diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/http.rs b/src/http.rs index d4d66ac..8657ace 100644 --- a/src/http.rs +++ b/src/http.rs @@ -68,7 +68,7 @@ pub async fn serve_http_connection( B::Data: Send, B::Error: Into> + Send + Sync, IO: hyper::rt::Read + hyper::rt::Write + Unpin + Send + 'static, - S: Service, Response=Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: Into> + Send, E: HttpServerConnExec + Send + Sync + 'static, @@ -83,38 +83,57 @@ pub async fn serve_http_connection( let sleep = sleep_or_pending(max_connection_age); tokio::pin!(sleep); - // TODO(This builder should be pre-configured outside of the server) - // unfortunately this object is very poorly designed and there is - // no way exposed to pre-configure it. - // - // There must be some way to approach here. - let builder = builder.clone(); + // TODO(It's absolutely terrible that we have to clone the builder here) + // and configure it rather than passing it in. + // this is due to an API flaw in the hyper_util crate. + // this builder doesn't have a way to convert back to a builder + // once you start building. + // Configure the builder let mut builder = builder.clone(); builder // HTTP/1 settings .http1() + // Enable half-close for better connection handling .half_close(true) + // Enable keep-alive to reduce overhead for multiple requests .keep_alive(true) - .max_buf_size(64 * 1024) + // Increase max buffer size to 256KB for better performance with larger payloads + .max_buf_size(256 * 1024) + // Enable immediate flushing of pipelined responses .pipeline_flush(true) + // Preserve original header case for compatibility .preserve_header_case(true) + // Disable automatic title casing of headers to reduce processing overhead .title_case_headers(false) // HTTP/2 settings .http2() - .initial_stream_window_size(Some(1024 * 1024)) - .initial_connection_window_size(Some(2 * 1024 * 1024)) + // Increase initial stream window size to 2MB for better throughput + .initial_stream_window_size(Some(2 * 1024 * 1024)) + // Increase initial connection window size to 4MB for improved performance + .initial_connection_window_size(Some(4 * 1024 * 1024)) + // Enable adaptive window for dynamic flow control .adaptive_window(true) - .max_frame_size(Some(16 * 1024)) - .max_concurrent_streams(Some(1000)) - .max_send_buf_size(1024 * 1024) + // Increase max frame size to 32KB for larger data chunks + .max_frame_size(Some(32 * 1024)) + // Allow up to 2000 concurrent streams for better parallelism + .max_concurrent_streams(Some(2000)) + // Increase max send buffer size to 2MB for improved write performance + .max_send_buf_size(2 * 1024 * 1024) + // Enable CONNECT protocol support for proxying and tunneling .enable_connect_protocol() - .max_header_list_size(16 * 1024) - .keep_alive_interval(Some(Duration::from_secs(20))) - .keep_alive_timeout(Duration::from_secs(20)); + // Increase max header list size to 32KB to handle larger headers + .max_header_list_size(32 * 1024) + // Set keep-alive interval to 10 seconds for more responsive connection management + .keep_alive_interval(Some(Duration::from_secs(10))) + // Set keep-alive timeout to 30 seconds to balance connection reuse and resource conservation + .keep_alive_timeout(Duration::from_secs(30)); // Create and pin the HTTP connection - // This handles all the HTTP connection logic via hyper + // + // This handles all the HTTP connection logic via hyper. + // This is a pointer to a blocking task, effectively + // Which tells us how it's doing via the hyper_io transport. let mut conn = pin!(builder.serve_connection_with_upgrades(hyper_io, hyper_service)); // Here we wait for the http connection to terminate @@ -368,14 +387,14 @@ pub async fn serve_http_with_shutdown( signal: Option, ) -> Result<(), super::Error> where - F: Future + Send + 'static, - I: Stream> + Send + 'static, + F: Future + Send + 'static, + I: Stream> + Send + 'static, IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, IE: Into + Send + 'static, - S: Service, Response=Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: Into> + Send, - ResBody: Body + Send + Sync + 'static, + ResBody: Body + Send + Sync + 'static, ResBody::Error: Into + Send + Sync, E: HttpServerConnExec + Send + Sync + 'static, { @@ -748,7 +767,7 @@ mod tests { } } }) - .await; + .await; match shutdown_result { Ok(Ok(())) => println!("Server shut down successfully"),