diff --git a/blazingly-fast.md b/blazingly-fast.md index 64376ac..8e78b52 100644 --- a/blazingly-fast.md +++ b/blazingly-fast.md @@ -24,7 +24,7 @@ not read files but outputting a static text just like in the other examples. **maybe someone with rust experience** can have a look at my [wrk/rust/hello](wrk/rust/hello) code and tell me why it's surprisingly slow, as I expected it to be faster than the basic GO example. I'll enable the -GitHub discussions for this matter. My suspicion is the use of muteces. +GitHub discussions for this matter. My suspicion is the use of mutexes . ![](wrk_tables.png) diff --git a/wrk/rust/hello/.gitignore b/wrk/rust/hello/.gitignore new file mode 100644 index 0000000..6985cf1 --- /dev/null +++ b/wrk/rust/hello/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/wrk/rust/hello/Cargo.toml b/wrk/rust/hello/Cargo.toml new file mode 100644 index 0000000..fb1ec2c --- /dev/null +++ b/wrk/rust/hello/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/wrk/rust/hello/hello.html b/wrk/rust/hello/hello.html new file mode 100644 index 0000000..a2b3773 --- /dev/null +++ b/wrk/rust/hello/hello.html @@ -0,0 +1 @@ +Hello from RUST! diff --git a/wrk/rust/hello/src/lib.rs b/wrk/rust/hello/src/lib.rs new file mode 100644 index 0000000..936d014 --- /dev/null +++ b/wrk/rust/hello/src/lib.rs @@ -0,0 +1,92 @@ +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; + +pub struct ThreadPool { + workers: Vec, + sender: Option>, +} + +type Job = Box; + +impl ThreadPool { + /// Create a new ThreadPool. + /// + /// The size is the number of threads in the pool. + /// + /// # Panics + /// + /// The `new` function will panic if the size is zero. + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + let (sender, receiver) = mpsc::channel(); + + let receiver = Arc::new(Mutex::new(receiver)); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + workers.push(Worker::new(id, Arc::clone(&receiver))); + } + + ThreadPool { + workers, + sender: Some(sender), + } + } + + pub fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + let job = Box::new(f); + + self.sender.as_ref().unwrap().send(job).unwrap(); + } +} + +impl Drop for ThreadPool { + fn drop(&mut self) { + drop(self.sender.take()); + + for worker in &mut self.workers { + println!("Shutting down worker {}", worker.id); + + if let Some(thread) = worker.thread.take() { + thread.join().unwrap(); + } + } + } +} + +struct Worker { + id: usize, + thread: Option>, +} + +impl Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { + let thread = thread::spawn(move || loop { + let message = receiver.lock().unwrap().recv(); + + match message { + Ok(job) => { + // println!("Worker got a job; executing."); + + job(); + } + Err(_) => { + // println!("Worker disconnected; shutting down."); + break; + } + } + }); + + Worker { + id, + thread: Some(thread), + } + } +} diff --git a/wrk/rust/hello/src/main.rs b/wrk/rust/hello/src/main.rs new file mode 100644 index 0000000..34a7474 --- /dev/null +++ b/wrk/rust/hello/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +// use std::fs; +use std::io::prelude::*; +use std::net::TcpListener; +use std::net::TcpStream; +// use std::thread; +// use std::time::Duration; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + // for stream in listener.incoming().take(2) { + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} + +fn handle_connection(mut stream: TcpStream) { + let mut buffer = [0; 1024]; + stream.read(&mut buffer).unwrap(); + + + let status_line = "HTTP/1.1 200 OK"; + + let contents = "HELLO from RUST!"; + + let response = format!( + "{}\r\nContent-Length: {}\r\n\r\n{}", + status_line, + contents.len(), + contents + ); + + stream.write_all(response.as_bytes()).unwrap(); + stream.flush().unwrap(); +}