exercises

Log | Files | Refs | README

main.rs (2945B)


      1 use std::sync::Arc;
      2 
      3 use actor_model::{
      4     basic_actor::{Message, RespMessage, basic_actor, resp_actor},
      5     mutex_replacement::actor_replacement,
      6 };
      7 use tokio::sync::{Mutex, mpsc::channel, oneshot};
      8 
      9 #[tokio::main]
     10 async fn main() {
     11     // 1. Basic actor without responder
     12     // let (tx, rx) = channel::<Message>(100);
     13 
     14     // let _actor_handle = tokio::spawn(basic_actor(rx));
     15 
     16     // for i in 0..10 {
     17     //     let msg = Message { value: i };
     18     //     tx.send(msg).await.unwrap();
     19     // }
     20 
     21     // 2. Basic actor with responder
     22     // if we want to send a message to our responding actor, we need to
     23     // construct a onshot channel.
     24     // let (tx, rx) = channel::<RespMessage>(100);
     25 
     26     // let _resp_actor_handle = tokio::spawn(async {
     27     //     resp_actor(rx).await;
     28     // });
     29 
     30     // for i in 0..10 {
     31     //     // We use a oneshot channel because we need the response to be
     32     //     // sent only once and then close; after that the client code
     33     //     // can go about doing other things.
     34     //     let (resp_tx, resp_rx) = oneshot::channel::<i64>();
     35 
     36     //     let msg = RespMessage {
     37     //         value: i,
     38     //         responder: resp_tx,
     39     //     };
     40 
     41     //     tx.send(msg).await.unwrap();
     42     //     println!("Response: {}", resp_rx.await.unwrap());
     43     // }
     44 
     45     // 3.1 Actor replacement using mutex: Elapsed: 602.618µs
     46     // let state = Arc::new(Mutex::new(0));
     47     // let mut handles = Vec::new();
     48 
     49     // let now = tokio::time::Instant::now();
     50 
     51     // for i in 0..100 {
     52     //     let state_ref = state.clone();
     53     //     let future = async move {
     54     //         let handle = tokio::spawn(async move { actor_replacement(state_ref, i).await });
     55 
     56     //         let _ = handle.await.unwrap();
     57     //     };
     58     //     handles.push(tokio::spawn(future));
     59     // }
     60     // for handle in handles {
     61     //     let _ = handle.await.unwrap();
     62     // }
     63     // println!("Elapsed: {:?}", now.elapsed());
     64 
     65     // 3.2 Actor approach: Elapsed: 313.017µs
     66     //
     67     // Generally, passing messages through channels can scale better than
     68     // mutexes in concurrent environments, because the senders do not
     69     // have to wait for other tasks to finish what they are doing.
     70     let (tx, rx) = channel::<RespMessage>(100);
     71     let _resp_actor_handle = tokio::spawn(async {
     72         resp_actor(rx).await;
     73     });
     74 
     75     let mut handles = Vec::new();
     76 
     77     let now = tokio::time::Instant::now();
     78     for i in 0..100 {
     79         let tx_ref = tx.clone();
     80 
     81         let future = async move {
     82             let (resp_tx, resp_rx) = oneshot::channel::<i64>();
     83             let msg = RespMessage {
     84                 value: i,
     85                 responder: resp_tx,
     86             };
     87             tx_ref.send(msg).await.unwrap();
     88             let _ = resp_rx.await.unwrap();
     89         };
     90         handles.push(tokio::spawn(future));
     91     }
     92     for handle in handles {
     93         handle.await.unwrap();
     94     }
     95     println!("Elapsed: {:?}", now.elapsed());
     96 }