### Run Tokio-based Echo Server Example Source: https://github.com/xudong-huang/may/blob/master/performace.md Navigates to the `tokio` directory and starts the Tokio-based echo server example. By default, it runs with 8 threads, listening for incoming connections. ```sh $ cd tokio $ cargo run --example=echo --release ``` -------------------------------- ### Run May-based Echo Server Example Source: https://github.com/xudong-huang/may/blob/master/performace.md Navigates to the `may` directory and starts the May-based echo server example. It runs with 2 threads by default, listening on port 8000, and is configured for 8 threads via command line. ```sh $ cd may $ cargo run --example=echo --release -- -t 8 -p 8000 ``` -------------------------------- ### Compile Rust Echo Client Example Source: https://github.com/xudong-huang/may/blob/master/performace.md Compiles the echo client example from the project, creating an executable for benchmarking. This command uses `cargo build` with the `--release` flag for optimized performance. ```sh $ cargo build --example=echo_client --release ``` -------------------------------- ### Example Output for May Coroutine Stack Usage (Shell) Source: https://github.com/xudong-huang/may/blob/master/docs/tune_stack_size.md This snippet provides an example of the console output generated by the `may` library when monitoring coroutine stack usage. It shows the coroutine's name, the configured stack size, and the actual used stack size, which is reported after the coroutine completes execution. ```Shell hello may coroutine name = Some("test"), stack size = 4095, used size = 266 ``` -------------------------------- ### Rust Example: Using `coroutine_local` for Coroutine-Specific Data Source: https://github.com/xudong-huang/may/blob/master/docs/CLS_instead_of_TLS.md This Rust example demonstrates the usage of the `coroutine_local` macro to declare a coroutine-local static variable `FOO`. It shows how `FOO` maintains a unique value for each spawned coroutine within a `coroutine::scope`, ensuring that modifications within one coroutine do not affect others. It also illustrates that accessing `FOO` from the main thread context (outside a coroutine) correctly reflects its initial value, demonstrating the fallback mechanism. ```Rust fn coroutine_local_many() { use std::sync::atomic::{AtomicUsize, Ordering}; coroutine_local!(static FOO: AtomicUsize = AtomicUsize::new(0)); coroutine::scope(|scope| { for i in 0..10 { go!(scope, move || { FOO.with(|f| { assert_eq!(f.load(Ordering::Relaxed), 0); f.store(i, Ordering::Relaxed); assert_eq!(f.load(Ordering::Relaxed), i); }); }); } }); // called in thread FOO.with(|f| { assert_eq!(f.load(Ordering::Relaxed), 0); }); } ``` -------------------------------- ### Get Coroutine Stack Usage in May (Rust) Source: https://github.com/xudong-huang/may/blob/master/docs/tune_stack_size.md This snippet illustrates how to determine the exact stack usage of a coroutine. By setting the stack size to an odd number, `may` initializes the entire stack with a special pattern, allowing it to detect the 'footprint' of the stack. After the coroutine finishes, `may` prints the actual usage. ```Rust extern crate may; use std::io::{self, Read}; fn main() { go!( may::coroutine::Builder::new() .name("test".to_owned()) .stack_size(0x1000 - 1), || { println!("hello may"); } ).unwrap(); println!("Press any key to continue..."); let _ = io::stdin().read(&mut [0u8]).unwrap(); } ``` -------------------------------- ### Configure Default Coroutine Stack Size in May (Rust) Source: https://github.com/xudong-huang/may/blob/master/docs/tune_stack_size.md This snippet demonstrates how to set the default stack size for new coroutines at the initialization stage of the `may` library. The unit for stack size is 'word', and the example sets the default to 8K bytes. ```Rust may::config().set_stack_size(0x400); // this coroutine would use 8K bytes stack go!(...); ``` -------------------------------- ### Setting Custom Stack Size for a May Coroutine Source: https://github.com/xudong-huang/may/blob/master/docs/may_caveat.md This Rust code demonstrates how to specify a custom stack size for an individual coroutine using `may::coroutine::Builder`. This is crucial for preventing stack overflows, especially when dealing with recursive functions or functions that consume large stack space. The example sets the stack size to `0x2000` bytes before spawning the coroutine. ```rust Builder::new().stack_size(0x2000).spawn(...) ``` -------------------------------- ### Set Stack Size for a Single Coroutine in May (Rust) Source: https://github.com/xudong-huang/may/blob/master/docs/tune_stack_size.md This snippet shows how to explicitly specify a stack size for a single coroutine using the `may::coroutine::Builder`. This method overrides the global default stack size, allowing for fine-grained control over individual coroutine memory allocation. The example spawns a coroutine with a 16K bytes stack. ```Rust // this coroutine would use 16K bytes stack let builder = may::coroutine::Builder::new().stack_size(0x800); unsafe { builder.spawn(...) }.unwrap(); ``` -------------------------------- ### Implementing a Naive Echo Server using May Coroutines Source: https://github.com/xudong-huang/may/blob/master/README.md This Rust code demonstrates how to build a basic TCP echo server using the `may` library. It utilizes `may::net::TcpListener` to bind to an address and accept incoming connections. For each new connection, a new coroutine is spawned using the `go!` macro, which handles reading data from the stream and writing it back, showcasing `may`'s efficient asynchronous I/O capabilities. ```Rust #[macro_use] extern crate may; use may::net::TcpListener; use std::io::{Read, Write}; fn main() { let listener = TcpListener::bind("127.0.0.1:8000").unwrap(); while let Ok((mut stream, _)) = listener.accept() { go!(move || { let mut buf = vec![0; 1024 * 16]; // alloc in heap! while let Ok(n) = stream.read(&mut buf) { if n == 0 { break; } stream.write_all(&buf[0..n]).unwrap(); } }); } } ``` -------------------------------- ### Benchmark May Echo Server with Client Source: https://github.com/xudong-huang/may/blob/master/performace.md Executes the echo client against the running May server at `127.0.0.1:8000`. Similar to the Tokio benchmark, it uses 100 clients, 100-byte messages, and reports performance metrics, showing May's higher request/response rate in this specific test. ```sh $ cargo run --example=echo_client --release -- -c 100 -l 100 -t 8 -a 127.0.0.1:8000 Finished release [optimized] target(s) in 11.77s Running `target/release/examples/echo_client -c 100 -l 100 -t 8 -a '127.0.0.1:8000'` ==================Benchmarking: 127.0.0.1:8000================== 100 clients, running 100 bytes, 10 sec. Speed: 256155 request/sec, 256155 response/sec, 25015 kb/sec Requests: 2561559 Responses: 2561554 ``` -------------------------------- ### Benchmark Tokio Echo Server with Client Source: https://github.com/xudong-huang/may/blob/master/performace.md Executes the echo client against the running Tokio server at `127.0.0.1:8080`. The client simulates 100 concurrent connections, sending 100-byte messages, and reports the request/response speed and total counts over 10 seconds. ```sh $ cargo run --example=echo_client --release -- -c 100 -l 100 -t 8 -a 127.0.0.1:8080 Finished release [optimized] target(s) in 5.86s Running `target/release/examples/echo_client -c 100 -l 100 -t 8 -a '127.0.0.1:8080'` ==================Benchmarking: 127.0.0.1:8080================== 100 clients, running 100 bytes, 10 sec. Speed: 153496 request/sec, 153495 response/sec, 14989 kb/sec Requests: 1534961 Responses: 1534958 ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.