From f00714abaa75104378e94312ac95cbcc41379a04 Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Sun, 15 Jan 2023 06:48:04 +0100 Subject: [PATCH] added rust sources to blazingly-fast.md --- blazingly-fast.md | 144 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/blazingly-fast.md b/blazingly-fast.md index 8e78b52..d81b74c 100644 --- a/blazingly-fast.md +++ b/blazingly-fast.md @@ -127,6 +127,150 @@ if __name__ == "__main__": print("Server stopped.") ``` +## rust code + +[main.rs](wrk/rust/hello/src/main.rs) + +```rust +use hello::ThreadPool; +use std::io::prelude::*; +use std::net::TcpListener; +use std::net::TcpStream; + +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(); +} +``` + +[lib.rs](wrk/rust/hello/src/lib.rs) + +```rust +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), + } + } +} +``` + ## wrk output wrk version: `wrk 4.1.0 [epoll] Copyright (C) 2012 Will Glozer`