Skip to content

Instantly share code, notes, and snippets.

@esemeniuc
Created January 7, 2023 17:37
Show Gist options
  • Save esemeniuc/a209cb601b9997e6b3696bab5374acdd to your computer and use it in GitHub Desktop.
Save esemeniuc/a209cb601b9997e6b3696bab5374acdd to your computer and use it in GitHub Desktop.
Clone vs Channel+Insert invidiual items
/* results on 24 threads, Linux, Ryzen 5900X, 64GB RAM, rust 1.66 release mode
pubkey generation cost 13.703447ms
filling up 8 channels cost 1.299627336s
insert on thread_5 cost 204.928433ms
insert on thread_2 cost 202.868308ms
insert on thread_4 cost 219.480851ms
insert on thread_0 cost 213.074428ms
insert on thread_6 cost 213.296481ms
insert on thread_3 cost 234.825416ms
insert on thread_1 cost 218.522672ms
insert on thread_7 cost 247.670391ms
clone on thread_5 cost 77.638615ms
clone on thread_2 cost 89.146065ms
clone on thread_4 cost 95.712925ms
clone on thread_0 cost 100.161594ms
clone on thread_6 cost 102.523029ms
clone on thread_3 cost 106.814534ms
clone on thread_1 cost 106.549584ms
clone on thread_7 cost 96.811982ms
multithread cost 833.088291ms
crossbeam-channel = "0.5.6"
dashmap = "5.4.0"
*/
use std::collections::HashMap;
use std::thread;
use std::time::Instant;
use std::{net::SocketAddr, str::FromStr};
use crossbeam_channel::unbounded;
use rand::Rng;
use solana_sdk::pubkey::Pubkey;
fn main() {
let LIMIT = 1_000_000;
let channels = (0..8)
.map(|i| unbounded::<(Pubkey, SocketAddr)>())
.collect::<Vec<_>>();
let start = Instant::now();
let pubkeys = (0..LIMIT).map(|i| Pubkey::new_unique()).collect::<Vec<_>>();
println!("pubkey generation cost {:?}", start.elapsed());
//fill up all channels
let mut rng = rand::thread_rng();
let start = Instant::now();
(0..8).for_each(|channel_idx| {
(0..LIMIT).for_each(|i| {
channels[channel_idx]
.0
.send((
pubkeys[rng.gen_range(0..LIMIT)],
SocketAddr::from_str("0.0.0.0:0").unwrap(),
))
.unwrap()
});
});
println!("filling up 8 channels cost {:?}", start.elapsed());
let start = Instant::now();
let handles = (0..8)
.map(|i| {
let (_, receiver) = channels[i].clone();
thread::spawn(move || {
let mut d = HashMap::new();
//preload map with some data
(0..LIMIT).for_each(|_| {
d.insert(
Pubkey::new_unique(),
SocketAddr::from_str("0.0.0.0:0").unwrap(),
);
});
//actually unload the channel and time the insertions
let start = Instant::now();
receiver.try_iter().for_each(|x| {
d.insert(x.0, x.1);
});
println!("insert on thread_{i} cost {:?}", start.elapsed());
let start = Instant::now();
let c = d.clone();
println!("clone on thread_{i} cost {:?}", start.elapsed());
})
})
.collect::<Vec<_>>();
handles.into_iter().for_each(|handle| {
handle.join();
});
println!("multithread cost {:?}", start.elapsed());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment