Loading rust_08_misc...
fn give_me_a_tuple(param: u32) -> (String, f64) { let text = format!("param was {}", param); let real = 1.0 / (param as f64); (text, real) }
fn main() { let (t1, r1) = give_me_a_tuple(5); println!("t1={:?}, r1={}", t1, r1); let tuple2 = give_me_a_tuple(10); println!("tuple2={:?}", tuple2); let (ref_t2, ref_r2) = &tuple2; // take references on members println!("ref_t2={:?}, ref_r2={}", ref_t2, ref_r2); let (t2, r2) = tuple2; // consume (move) values of members println!("t2={:?}, r2={}", t2, r2); } /* t1="param was 5", r1=0.2 tuple2=("param was 10", 0.1) ref_t2="param was 10", ref_r2=0.1 t2="param was 10", r2=0.1 */
#[derive(Debug, Clone)] struct Thing { text: String, real: f64, }
fn give_me_a_struct(param: u32) -> Thing { Thing { text: format!("param was {}", param), real: 1.0 / param as f64, } }
fn main() { let Thing { text: t1, real: r1 } = give_me_a_struct(5); println!("t1={:?}, r1={}", t1, r1); let struct2 = give_me_a_struct(10); println!("struct2={:?}", struct2); let Thing { text: ref_t2, real: ref_r2 } = &struct2; // take references on members println!("ref_t2={:?}, ref_r2={}", ref_t2, ref_r2); let Thing { text: t2, real: r2 } = struct2; // consume (move) values of members println!("t2={:?}, r2={}", t2, r2); let Thing { text, real } = give_me_a_struct(20); println!("text={:?}, real={}", text, real); } /* t1="param was 5", r1=0.2 struct2=Thing { text: "param was 10", real: 0.1 } ref_t2="param was 10", ref_r2=0.1 t2="param was 10", r2=0.1 text="param was 20", real=0.05 */
&cl) sur le réel mémorisé dans cette variante✍
&cl) sur les membres length et size mémorisés dans cette variante.
if let Clothing::Trousers { length: l, size: s } = &cl { println!("~~> a pair of trousers, length {}, size {}", l, s); } else { println!("Sorry, I'm only interested in trousers..."); }
rustup doc --book“18. Patterns and Matching”
rustup doc --book“6. Enums and Pattern Matching”
rustup doc --reference“9. Patterns”
rustup doc --std 'match',
rustup doc --std 'let',
rustup doc --std 'if'
cargo build --release
cargo run --release
[profile.release] panic = "abort" codegen-units = 1 lto = true strip = "symbols" # reduce size, but incompatible with perf/flamegraph # debug = true # required for perf/flamegraph
[build] rustflags = ["-C", "target-cpu=native"]
fn generate_sin( samples: &mut [f32], dt: f32, freq: f32, ) { for (i, s) in samples.iter_mut().enumerate() { let t = i as f32 * dt; *s += (2.0 * std::f32::consts::PI * t * freq).sin(); } }
fn main() { let start = std::time::Instant::now(); let dt = 1.0 / 44100.0; let mut samples = vec![0.0; 50_000_000]; for f in 1..=5 { let freq = f as f32 * 100.0; generate_sin(&mut samples, dt, freq); } let duration = start.elapsed(); println!("duration: {:?}", duration); }
cargo install flamegraph
sudo apt update sudo apt install linux-tools-generic linux-tools-`uname -r`
sudo dnf install perf
sudo pacman -S perf
echo 'kernel.perf_event_paranoid = 0' | sudo sh -c 'tee -a /etc/sysctl.conf | sysctl -q -f -'
cargo flamegraph
/// Approximates sine of 2π·x with paraboloids fn unit_sine(x: f32) -> f32 { let x = x - x.floor(); let mut y = x - 0.5; y *= 16.0 * (y.abs() - 0.5); // y += 0.225 * y * (y.abs() - 1.0); // increase precision y }
// *s += (2.0 * std::f32::consts::PI * t * freq).sin(); *s += unit_sine(t * freq);
fn thread_task( title: String, delay_ms: u64, ) { for i in 0..10 { std::thread::sleep(std::time::Duration::from_millis(delay_ms)); println!("{} counting {}", title, i); } println!("leaving {}", title); }
fn main() -> Result<(), Box<dyn std::error::Error>> { // spawn a thread computing something in parallel let thread_title = String::from("thread task"); let thread_delay_ms = 100; let consumer_thread = std::thread::spawn(move || { thread_task(thread_title, thread_delay_ms); });
// compute something in the main thread for i in 0..5 { std::thread::sleep(std::time::Duration::from_millis(200)); println!("main program counting {}", i); }
// wait for the thread to terminate if let Err(e) = consumer_thread.join() { Err(format!("{:?}", e))?; }
println!("leaving main program"); Ok(()) } /* thread task counting 0 main program counting 0 thread task counting 1 thread task counting 2 main program counting 1 thread task counting 3 thread task counting 4 main program counting 2 thread task counting 5 thread task counting 6 main program counting 3 thread task counting 7 thread task counting 8 main program counting 4 thread task counting 9 leaving thread task leaving main program */
fn consumer_task( channel_receiver: std::sync::mpsc::Receiver<String> ) -> Result<(), Box<dyn std::error::Error>> { let start_time = std::time::SystemTime::now(); while let Ok(msg) = channel_receiver.recv() { // consume each incoming data let elapsed = start_time.elapsed()?; println!("consumer task received {:?} after {:?}", msg, elapsed); } println!("no more messages for consumer task"); Ok(()) }
fn main() -> Result<(), Box<dyn std::error::Error>> { // prepare a channel in order to provide the thread with some data let (channel_sender, channel_receiver) = std::sync::mpsc::channel();
// spawn a thread consuming data from this channel let consumer_thread = std::thread::spawn(move || { if let Err(e) = consumer_task(channel_receiver) { eprintln!("ERROR: {:?}", e); } });
// send data to the thread whenever we want channel_sender.send(String::from("first message"))?; for i in 0..5 { std::thread::sleep(std::time::Duration::from_millis(500)); let msg = format!("counting {}", i); channel_sender.send(msg)?; } channel_sender.send(String::from("last message"))?;
// close the channel drop(channel_sender);
// wait for the thread to terminate if let Err(e) = consumer_thread.join() { Err(format!("{:?}", e))?; }
Ok(()) } /* consumer task received "first message" after 784ns consumer task received "counting 0" after 500.130009ms consumer task received "counting 1" after 1.000132368s consumer task received "counting 2" after 1.500230532s consumer task received "counting 3" after 2.00035814s consumer task received "counting 4" after 2.500384809s consumer task received "last message" after 2.500390231s no more messages for consumer task */
use std::sync::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, };
#[derive(Debug, Default)] struct SharedState { next_n: AtomicUsize, elements: Mutex<Vec<(char, usize)>>, }
fn fibonacci(n: usize) -> usize { if n < 2 { n } else { fibonacci(n - 2) + fibonacci(n - 1) } }
fn compute_task( letter: char, limit: usize, state: &SharedState, ) -> Result<(), Box<dyn std::error::Error>> { loop { // atomic increment let n = state.next_n.fetch_add(1, Ordering::Relaxed);
// compute let fib_n = fibonacci(n); if fib_n > limit { break; }
// exclusively access the shared storage let mut elements = state.elements.lock().unwrap(); if elements.len() <= n { elements.resize(1 + n, (letter, 0)); } elements[n] = (letter, fib_n); } Ok(()) }
fn main() -> Result<(), Box<dyn std::error::Error>> { // prepare a shared state let state = Arc::new(SharedState::default()); let limit = 100_000_000;
// start many threads working with the shared state let mut threads = Vec::new(); for letter in "ABCD".chars() { threads.push(std::thread::spawn({ // clone the reference, not the state! let state = Arc::clone(&state); move || { if let Err(e) = compute_task(letter, limit, state.as_ref()) { eprintln!("ERROR: {:?}", e); } } })); }
// wait for all threads to terminate for th in threads { if let Err(e) = th.join() { Err(format!("{:?}", e))?; } }
// obtain the global result println!("{:?}", state.elements.lock().unwrap());
Ok(()) } /* [('B', 0), ('B', 1), ('B', 1), ('B', 2), ('B', 3), ('B', 5), ('B', 8), ('B', 13), ('B', 21), ('B', 34), ('B', 55), ('B', 89), ('B', 144), ('B', 233), ('B', 377), ('B', 610), ('B', 987), ('B', 1597), ('B', 2584), ('B', 4181), ('B', 6765), ('B', 10946), ('D', 17711), ('A', 28657), ('C', 46368), ('B', 75025), ('D', 121393), ('A', 196418), ('C', 317811), ('B', 514229), ('D', 832040), ('A', 1346269), ('C', 2178309), ('B', 3524578), ('D', 5702887), ('A', 9227465), ('C', 14930352), ('B', 24157817), ('D', 39088169), ('A', 63245986)] */
rustup doc --book“16.1. Using Threads to Run Code Simultaneously”
rustup doc --book“16.2. Using Message Passing to Transfer Data Between Thread”
rustup doc --book“16.3. Shared-State Concurrency”
rustup doc --rust-by-example“20.2. Channels”
rustup doc --std 'std::thread::spawn'
rustup doc --std 'std::sync::mpsc'
rustup doc --std 'std::sync::Arc'
rustup doc --std 'std::sync::atomic'
rustup doc --std 'std::sync::Mutex'