Thuta Learning
ရှာဖွေရန်
Rust
AdvancedProgrammingbeginner

Async Rust Basics

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Async Rust Basics concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • နမူနာ Rust code ကို ကိုယ်တိုင် run ပြီး output စစ်နိုင်ရန်
  • Tutorial Platform project နှင့် production scenario တွင် မှန်ကန်စွာအသုံးချနိုင်ရန်

နားလည်ထားရမယ့် အချက်

Lesson 18 ရဲ့ `std::thread` ဟာ OS thread တစ်ခုစီအတွက် memory/context-switch cost ရှိလို့ concurrent task ထောင်ချီ (ဥပမာ network request ထောင်ချီ) handle ချင်ရင် expensive ဖြစ်နိုင်ပါတယ်—async/await ကတော့ ဒီ scale ပြဿနာအတွက် lightweight solution တစ်ခုပါ။ `async fn` ကို ခေါ်တာနဲ့ code ချက်ချင်း run တာ မဟုတ်ဘဲ `Future` value တစ်ခု ချက်ချင်းပြန်ပေးတာသာ ဖြစ်ပါတယ်—Future ဟာ lazy ဖြစ်ပြီး `.await` (သို့) runtime က poll လုပ်မှသာ actual work စတင်ပါတယ်—ဒါက Lesson 16 ရဲ့ iterator ရဲ့ lazy evaluation နှင့် တူတဲ့ pattern တစ်ခုပါ။ JavaScript/Go လို language တွေမှာ async runtime (event loop, goroutine scheduler) က language ကိုယ်တိုင် built-in ပါလာပေမယ့် Rust ကတော့ deliberately runtime ကို language core ထဲ ထည့်မထားပါဘူး—Rust ကို embedded system အထိ အသုံးချနိုင်ဖို့ (runtime overhead လုံးဝမလိုချင်တဲ့ context) library level မှာသာ runtime ကို ရွေးချယ်စေချင်လို့ပါ—ဒါကြောင့် `tokio` (အသုံးအများဆုံး) လို external crate ကို depend ပေါ်ထားပြီးမှသာ async code ကို actually execute နိုင်ပါတယ်။ `.await` ကတော့ Future ကို complete ဖြစ်အောင် wait ပေးတဲ့ point တစ်ခုဖြစ်ပြီး OS thread ကို block မလုပ်ဘဲ (thread ဟာ တခြား task ဆီ ပြန်လှည့်ပြီး အလုပ်လုပ်နိုင်) runtime scheduler ဆီ control ကို ပြန်ပေးလိုက်တာဖြစ်ပါတယ်—ဒါကြောင့် I/O-bound task (network call, file read) ရာနှင့်ချီကို OS thread အနည်းငယ်တည်းနဲ့ efficiently handle နိုင်ပါတယ်—CPU-bound work အတွက်တော့ Lesson 18 ရဲ့ thread က ပိုသင့်တော်ပါတယ်။

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Lesson 22 ရဲ့ Axum API project ကို preview လုပ်ကြည့်ရင် HTTP handler function တစ်ခုစီကို `async fn get_lesson(...)` အဖြစ် ရေးရမှာဖြစ်ပါတယ်—request ရာနှင့်ချီကို တစ်ပြိုင်နက် handle ချင်ရင် (database query စောင့်နေတဲ့ time ကို OS thread ကို block မလုပ်ဘဲ) async ကို လိုအပ်ပါတယ်။ Lesson content file များစွာကို disk ကနေ concurrently ဖတ်ချင်ရင် `tokio::fs::read_to_string(path).await` ကို `Vec` of futures အဖြစ် ဆောက်ပြီး `futures::future::join_all(...)` ဖြင့် တစ်ပြိုင်နက် await လုပ်နိုင်ပါတယ်—Lesson 18 ရဲ့ thread-per-file approach ထက် lightweight ဖြစ်ပါတယ်။ `#[tokio::main]` attribute ကို `main` function ပေါ်တွင် ထားရင် tokio runtime ကို auto-setup လုပ်ပေးပါတယ်—ဒီ setup မရှိရင် `async fn` ကို ဘယ်လိုမှ execute လို့ ရမှာမဟုတ်ပါ။

အတူတူ စမ်းရေးကြည့်မယ်

rust
use tokio::time::{sleep, Duration};

async fn fetch_lesson_stat(id: u32) -> String {
    sleep(Duration::from_millis(10)).await;
    format!("lesson-{id} ready")
}

#[tokio::main]
async fn main() {
    let a = fetch_lesson_stat(1);
    let b = fetch_lesson_stat(2);
    let (result_a, result_b) = tokio::join!(a, b);
    println!("{result_a}");
    println!("{result_b}");
}
You should see
"lesson-1 ready" နှင့် "lesson-2 ready" ကို concurrently (sequential 20ms အစား ~10ms အတွင်း) print ထုတ်နိုင်မည်။

၅ မိနစ် စမ်းကြည့်

`async fn double(n: u32) -> u32` ရေးပါ (small `sleep` ပါစေ)—`tokio::join!` ဖြင့် ဒီ function ကို input value သုံးခုနှင့် concurrently ခေါ်ပြီး result သုံးခုကို print ထုတ်ပါ—`#[tokio::main]` setup လိုအပ်ကြောင်း သတိပြုပါ။

သတိလေးတစ်ချက်

`#[tokio::main]` (သို့ runtime setup အခြားနည်း) မထားဘဲ `async fn main()` ကို run ကြိုးစားခြင်း—compile error "async main function is not supported" ရနိုင်ပါတယ်—Rust language core မှာ runtime built-in မရှိလို့ဖြစ်ပါတယ်။

Async task များစွာကို `.await` တစ်ခုချင်းစီ sequential ခေါ်ခြင်း (`a.await; b.await;`)—concurrent ဖြစ်စေချင်ရင် `tokio::join!` သို့ `join_all` ကို သုံးရမယ်—sequential await ကတော့ concurrency ဘာမှ မရှိတော့ပါ။

Tokio Tutorial — Getting StartedRust

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • `#[tokio::main]` (သို့ runtime setup အခြားနည်း) မထားဘဲ `async fn main()` ကို run ကြိုးစားခြင်း—compile error "async main function is not supported" ရနိုင်ပါတယ်—Rust language core မှာ runtime built-in မရှိလို့ဖြစ်ပါတယ်။
  • Async task များစွာကို `.await` တစ်ခုချင်းစီ sequential ခေါ်ခြင်း (`a.await; b.await;`)—concurrent ဖြစ်စေချင်ရင် `tokio::join!` သို့ `join_all` ကို သုံးရမယ်—sequential await ကတော့ concurrency ဘာမှ မရှိတော့ပါ။
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

`async fn double(n: u32) -> u32` ရေးပါ (small `sleep` ပါစေ)—`tokio::join!` ဖြင့် ဒီ function ကို input value သုံးခုနှင့် concurrently ခေါ်ပြီး result သုံးခုကို print ထုတ်ပါ—`#[tokio::main]` setup လိုအပ်ကြောင်း သတိပြုပါ။

You'll know it worked when: "lesson-1 ready" နှင့် "lesson-2 ready" ကို concurrently (sequential 20ms အစား ~10ms အတွင်း) print ထုတ်နိုင်မည်။

Async Rust Basics | Thuta Learning