I'm getting much worst performance than what I expect when running some simple requests with the reqwest crate. I wrote a simple program just to demonstrate that:
use tokio::time::Instant;
const URL: &str = "http://localhost:3000/health";
#[tokio::main]
async fn main() {
{
let now = Instant::now();
reqwest::get(URL).await.unwrap();
println!("reqwest: {:.3?}", now.elapsed());
}
{
let now = Instant::now();
ureq::get(URL).call().unwrap();
println!("ureq: {:.3?}", now.elapsed());
}
}
When running it I get:
$ cargo run --bin perf --release
Finished release [optimized] target(s) in 0.08s
Running `target/release/perf`
reqwest: 33.126ms
ureq: 543.672µs
That's a 60x difference. I've done a bit more testing with concurrent and parallel queries (some of those experiments can be seen here) and it even gets worth when increasing the parallelism.
How do I get better query performance with reqwest?
Profiling the program execution with samply showed that reqwest is spending most of its time in
openssl::ssl::connector::SslConnector::builderon the test machine running Ubuntu 23.10.reqwestsupports many optional features that may have an impact of the performances. In that cas, using therustls-tlsfeature of the defaultnative-tlsdrastically reduce the reqwest's client creation time.In
Cargo.toml,native-tlsmay be disabled by specifyingdefault-features = falseon thereqwestdependency:With only that change, the same test program now produces much closer performance between
reqwestandureq:The results are now quite close and shouldn't be read as anything significant: no effort was done to be statistically relevant.