Veel systeem talen hebben basis ondersteuning voor I/O operaties, maar maken vaak geen expliciet onderscheid tussen synchrone en asynchrone benaderingen. Rust is vanaf het begin ontworpen om veiligheid en prestaties te waarborgen, ook bij het werken met I/O. Daarom biedt de standaardbibliotheek van Rust (std) alleen synchrone I/O aan, terwijl populaire asynchrone ondersteuning is overgedragen aan externe bibliotheken (zoals tokio, async-std).
Het mengen van synchrone en asynchrone I/O benaderingen leidt vaak tot complicaties in de onderhoudbaarheid van de code en problemen met veiligheid en prestaties, aangezien deze benaderingen verschillende modellen voor resourcebeheer, threads en blokkeringen hebben. Bijvoorbeeld, directe lezing van een groot bestand of wachten op gegevens uit het netwerk kan de uitvoerend thread blokkeren (inclusief de hoofd-thread), wat de applicatie vertraagt.
Rust biedt een duidelijke scheiding: De Standaardbibliotheek (std::io) — alleen synchrone I/O met veilige foutafhandeling en strikte controle over resource-eigendom. Voor asynchrone oplossingen worden externe bibliotheken en asynchrone runtimes gebruikt — zij bieden hun eigen types en API's, maar met een vergelijkbare fout- en veiligheidssemantiek.
Voorbeeld van synchrone bestandslezing:
use std::fs::File; use std::io::{self, Read}; fn main() -> io::Result<()> { let mut file = File::open("foo.txt")?; let mut contents = String::new(); file.read_to_string(&mut contents)?; println!("{}", contents); Ok(()) }
Voorbeeld van asynchrone bestandslezing via tokio:
use tokio::fs::File; use tokio::io::AsyncReadExt; #[tokio::main] async fn main() -> tokio::io::Result<()> { let mut file = File::open("foo.txt").await?; let mut contents = String::new(); file.read_to_string(&mut contents).await?; println!("{}", contents); Ok(()) }
Belangrijke kenmerken:
Kan men direct types mengen (bijvoorbeeld, File uit std en File uit tokio) voor overdracht tussen synchrone en asynchrone functies?
Nee. Ze zijn niet compatibel op het niveau van de API, en standaard types implementeren geen asynchrone traits.
Blokkeert std::thread::spawn in een asynchrone functie als synchrone I/O daarin wordt aangeroepen?
Ja. Als in een asynchrone omgeving synchrone I/O wordt aangeroepen, zal de thread geblokkeerd worden, waardoor de voordelen van asynchroniciteit teniet worden gedaan.
Kan men async fn main gebruiken zonder runtime (tokio of async-std)?
Nee. Asynchrone toegangspunten moeten worden uitgevoerd door een speciale runtime, anders staat de compiler niet toe om async fn main te gebruiken.
In een multithreaded server in Rust wordt synchrone lezing uit std::io gebruikt in asynchrone request handlers. Hierdoor blokkeren de belasting de event loop, wat leidt tot verhoogde latenties, en de server kan de piekbelasting niet aan.
Voordelen:
Nadelen:
Er worden alleen asynchrone types gebruikt voor alle bestands- en netwerkoperaties binnen asynchrone code, met strikte naleving van de types en het afhandelen van fouten via Result.
Voordelen:
Nadelen: