I wish to spin up X threads which will fire X requests to the specified server within the code. Currently, my application is waiting for each thread and X requests to finish before spinning up the next one.
How can I go about doing this async?
extern crate hyper;
extern crate time;
use hyper::header::Connection;
use hyper::Client;
use std::sync::{Arc, Mutex};
use std::thread;
use time::*;
struct Request {
elapsed_time: f64,
}
impl Request {
fn new(elapsed_time: f64) -> Request {
Request {
elapsed_time: elapsed_time,
}
}
}
fn main() {
let requests = Arc::new(Mutex::new(Vec::new()));
for _x in 0..100 {
println!("Spinning up thread...");
let mut client = Client::new();
let thread_items = requests.clone();
let handle = thread::spawn(move || {
for _x in 0..100 {
println!("Firing the request");
let start = time::precise_time_s();
let _res = client
.get("http://jacob.uk.com")
.header(Connection::close())
.send()
.unwrap();
let end = time::precise_time_s();
thread_items
.lock()
.unwrap()
.push((Request::new(end - start)));
}
});
handle.join().unwrap();
}
}
Program output:
Spinning up thread...
Firing request
Firing request
Firing request
Firing request
Spinning up thread...
Firing request
Firing request
Firing request
Firing request
Spinning up thread...
Firing request
Firing request
Firing request
Firing request
The threads provided by the Rust standard library are "OS threads", that is, they use the facilities of your operating system. Therefore, a Rust program has no limit imposed by Rust itself, but rather, this limit would result from whatever your OS lets you do.
The Rust standard library uses a 1:1 model of thread implementation, whereby a program uses one operating system thread per one language thread. There are crates that implement other models of threading that make different tradeoffs to the 1:1 model.
Spawning a new physical thread will mean a transition into Kernel mode and setting up a bunch of mernel structures, so the overhead will be higher.
Rust, in fact, has a history with green threads. A green threads runtime used to be the default paradigm for Rust code.
Your culprit is this line:
handle.join().unwrap();
You execute a thread in the loop, and then right after starting the thread you join
it into the main thread.
What you could do, is to create a Vec
and put all the handles in the vec. Then, in another loop, you join
all the handles.
Another possibility is to simply not join the threads, and let them exit naturally, but then you won't know when all of them are done. Which, as @delnan notes, might allow the main thread to exit before the spawned threads exit. This causes all the spawned threads to be killed instead of letting them run to termination.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With