Skip to content

Instantly share code, notes, and snippets.

@kamek-pf
Last active November 26, 2017 22:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kamek-pf/fd51d9d9b8417be2659bd0dc6be2a70e to your computer and use it in GitHub Desktop.
Save kamek-pf/fd51d9d9b8417be2659bd0dc6be2a70e to your computer and use it in GitHub Desktop.
Rust AWS client init benchmark
// In this test, I benchmark 3 different ways to initialize AWS clients in Rust, using the Rusoto crates
// I wanted to know what was more efficient :
// - Create a new client for every call (Boxed or not)
// - Initialize once using the lazy_static macro and a mutex
// - Initialize one using the thread_local macro
#![feature(test)]
extern crate test;
extern crate rusoto_core;
extern crate rusoto_sns;
#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;
use rusoto_core::{default_tls_client, DefaultCredentialsProvider, Region};
use rusoto_sns::{Sns, SnsClient, UnsubscribeInput};
thread_local! {
pub static SNS: Box<Sns> = init_sns();
}
lazy_static! {
pub static ref SNS_LS: Mutex<Box<Sns + Send>> = Mutex::new(init_sns());
}
fn init_sns() -> Box<Sns + Send> {
let provider = DefaultCredentialsProvider::new().unwrap();
let client = SnsClient::new(default_tls_client().unwrap(), provider, Region::UsEast1);
Box::new(client)
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[bench]
fn raw_init(b: &mut Bencher) {
let input = UnsubscribeInput {
subscription_arn: "kek".to_string()
};
b.iter(|| {
let provider = DefaultCredentialsProvider::new().unwrap();
let client = SnsClient::new(default_tls_client().unwrap(), provider, Region::UsEast1);
client.unsubscribe(&input);
})
}
#[bench]
fn raw_init_boxed(b: &mut Bencher) {
let input = UnsubscribeInput {
subscription_arn: "kek".to_string()
};
b.iter(|| {
let client = init_sns();
client.unsubscribe(&input);
})
}
#[bench]
fn thread_local(b: &mut Bencher) {
let input = UnsubscribeInput {
subscription_arn: "kek".to_string()
};
b.iter(|| {
SNS.with(|client| {
client.unsubscribe(&input);
})
});
}
#[bench]
fn lazy_static(b: &mut Bencher) {
let input = UnsubscribeInput {
subscription_arn: "kek".to_string()
};
b.iter(|| {
let client = SNS_LS.lock().unwrap();
client.unsubscribe(&input);
});
}
}
@kamek-pf
Copy link
Author

kamek-pf commented Nov 26, 2017

rustc 1.23.0-nightly (aabfed5e0 2017-11-17)

Results here (rustup nightly run cargo bench), looks like cargo runs about 300 iterations for each test :

running 4 tests
test tests::lazy_static    ... bench: 132,044,392 ns/iter (+/- 17,109,528)
test tests::raw_init       ... bench: 142,272,740 ns/iter (+/- 14,239,434)
test tests::raw_init_boxed ... bench: 135,739,178 ns/iter (+/- 21,332,773)
test tests::thread_local   ... bench: 132,222,056 ns/iter (+/- 19,232,411)
running 4 tests
test tests::lazy_static    ... bench: 135,597,728 ns/iter (+/- 14,104,085)
test tests::raw_init       ... bench: 144,043,166 ns/iter (+/- 17,936,603)
test tests::raw_init_boxed ... bench: 139,190,590 ns/iter (+/- 22,398,152)
test tests::thread_local   ... bench: 133,346,799 ns/iter (+/- 15,421,185)
running 4 tests
test tests::lazy_static    ... bench: 136,255,849 ns/iter (+/- 11,426,116)
test tests::raw_init       ... bench: 143,310,186 ns/iter (+/- 14,744,561)
test tests::raw_init_boxed ... bench: 141,918,214 ns/iter (+/- 15,608,307)
test tests::thread_local   ... bench: 133,826,961 ns/iter (+/- 19,861,269)

So thread_local and lazy_static are slightly better. I wouldn't worry too much about this, just go with what's more convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment