Uma introdução à programação assíncrona em Rust

Os modelos tradicionais de programação síncrona geralmente levam a gargalos de desempenho. Isso ocorre porque o programa espera que as operações lentas sejam concluídas antes de passar para a próxima tarefa. Isso geralmente resulta em uso insatisfatório de recursos e uma experiência de usuário lenta.

A programação assíncrona permite escrever código sem bloqueio que utiliza os recursos do sistema de forma eficaz. Aproveitando a programação assíncrona, você pode criar aplicativos que executam várias tarefas. A programação assíncrona é útil para lidar com várias solicitações de rede ou processar grandes quantidades de dados sem bloquear o fluxo de execução.

Programação assíncrona em Rust

O modelo de programação assíncrona do Rust permite que você escreva um código Rust eficiente que é executado simultaneamente sem bloquear o fluxo de execução. A programação assíncrona é benéfica ao lidar com operações de E/S, solicitações de rede e tarefas que envolvem a espera de recursos externos.

Você pode implementar programação assíncrona em seus aplicativos Rust de várias maneiras. Isso inclui recursos de linguagem, bibliotecas e o tempo de execução do Tokio.

Além disso, o modelo de propriedade do Rust e as primitivas de simultaneidade, como canais e bloqueios, permitem uma programação simultânea segura e eficiente. Você pode aproveitar esses recursos com programação assíncrona para criar sistemas simultâneos que escalam bem e utilizam vários núcleos de CPU.

Conceitos de programação assíncrona do Rust

Futuros fornecem uma base para programação assíncrona em Rust. Um futuro representa uma computação assíncrona que não foi completamente executada.

  13 plataformas de marketing por e-mail econômicas para blogueiros

Futuros são preguiçosos (eles só são executados quando em votação). Quando você chama um método future poll(), ele verifica se o futuro foi concluído ou se precisa de trabalho adicional. Se o futuro não estiver pronto, ele retorna Poll::Pending, indicando que a tarefa deve ser agendada para execução posterior. Se o futuro estiver pronto, ele retornará Poll::Ready com o valor resultante.

A cadeia de ferramentas padrão do Rust inclui primitivas de E/S assíncronas, uma versão assíncrona de E/S de arquivo, rede e temporizadores. Essas primitivas permitem que você execute operações de E/S de forma assíncrona. Isso ajuda a evitar o bloqueio da execução de um programa enquanto aguarda a conclusão das tarefas de E/S.

A sintaxe async/await permite que você escreva um código assíncrono semelhante ao código síncrono. Isso torna seu código intuitivo e fácil de manter.

A abordagem de Rust para programação assíncrona enfatiza a segurança e o desempenho. As regras de propriedade e empréstimo garantem a segurança da memória e evitam problemas comuns de simultaneidade. A sintaxe Async/await e os futuros fornecem uma maneira intuitiva de expressar fluxos de trabalho assíncronos. Você pode usar um tempo de execução de terceiros para gerenciar tarefas para uma execução eficiente.

Você pode combinar esses recursos de linguagem, bibliotecas e tempo de execução para escrever código de alto desempenho. Ele fornece uma estrutura poderosa e ergonômica para a construção de sistemas assíncronos. Isso torna o Rust uma escolha popular para projetos que exigem tratamento eficiente de tarefas vinculadas a E/S e alta simultaneidade.

Rust versão 1.39 e versões posteriores não oferecem suporte a operações assíncronas na biblioteca padrão do Rust. Você precisará de uma caixa de terceiros para usar a sintaxe async/await para lidar com operações assíncronas no Rust. Você pode usar pacotes de terceiros como Tokio ou async-std para trabalhar com a sintaxe async/await.

  Apple atinge valor de mercado de US$ 3 trilhões e adquire startup de fintech

Programação assíncrona com Tokio

Tokio é um tempo de execução assíncrono robusto para Rust. Ele fornece funcionalidade para criar aplicativos escaláveis ​​e de alto desempenho. Você pode aproveitar o poder da programação assíncrona com o Tokio. Ele também fornece recursos para extensibilidade.

No núcleo do Tokio está seu modelo de execução e agendamento de tarefas assíncronas. Tokio permite que você escreva código assíncrono com a sintaxe async/await. Isso permite a utilização eficiente de recursos do sistema e a execução simultânea de tarefas. O loop de eventos do Tokio gerencia eficientemente o agendamento de tarefas. Isso garante a utilização ideal dos núcleos da CPU e minimiza a sobrecarga de troca de contexto.

Os combinadores de Tokio facilitam a coordenação e composição de tarefas. Tokio fornece poderosas ferramentas de coordenação e composição de tarefas. Você pode esperar que várias tarefas sejam concluídas com junção, selecionar a primeira tarefa concluída com selecionar e competir entre si com corrida.

Adicione a tokio crate à seção de dependências do seu arquivo Cargo.toml.

 [dependencies]
tokio = { version = "1.9", features = ["full"] }

Veja como você pode usar a sintaxe async/await em seus programas Rust com Tokio:

 use tokio::time::sleep;
use std::time::Duration;

async fn hello_world() {
    println!("Hello, ");
    sleep(Duration::from_secs(1)).await;
    println!("World!");
}

#[tokio::main]
async fn main() {
    hello_world().await;
}

A função hello_world é assíncrona, então ela pode usar a palavra-chave await para pausar sua execução até que um futuro seja resolvido. A função hello_world imprime “Hello,” no console. A chamada de função Duration::from_secs(1) suspende a execução da função por um segundo. A palavra-chave await aguarda a conclusão do futuro de suspensão. Finalmente, a função hello_world imprime “World!” para o console.

A função principal é uma função assíncrona com o #[tokio::main] atributo. Ele designa a função principal como ponto de entrada para o Tokio runtime. O hello_world().await executa a função hello_world de forma assíncrona.

  Como baixar filmes no Netflix para visualização offline

Atrasando tarefas com Tokio

Uma tarefa predominante na programação assíncrona é usar atrasos ou agendar tarefas para serem executadas em um intervalo de tempo especificado. O tokio runtime fornece um mecanismo para usar temporizadores assíncronos e atrasos através do módulo tokio::time.

Veja como você pode atrasar uma operação com o Tokio runtime:

 use std::time::Duration;
use tokio::time::sleep;

async fn delayed_operation() {
    println!("Performing delayed operation...");
    sleep(Duration::from_secs(2)).await;
    println!("Delayed operation completed.");
}

#[tokio::main]
async fn main() {
    println!("Starting...");
    delayed_operation().await;
    println!("Finished.");
}

A função delay_operation introduz um atraso de dois segundos com o método sleep. A função atraso_operação é assíncrona, portanto, pode usar await para pausar sua execução até que o atraso seja concluído.

Tratamento de erros em programas assíncronos

O tratamento de erros no código Rust assíncrono envolve o uso do tipo Result e o tratamento de erros Rust com o ? operador.

 use tokio::fs::File;
use tokio::io;
use tokio::io::{AsyncReadExt};

async fn read_file_contents() -> io::Result<String> {
    let mut file = File::open("file.txt").await?;
    let mut contents = String::new();
    file.read_to_string(&mut contents).await?;
    Ok(contents)
}

async fn process_file() -> io::Result<()> {
    let contents = read_file_contents().await?;
    
    Ok(())
}

#[tokio::main]
async fn main() {
    match process_file().await {
        Ok(()) => println!("File processed successfully."),
        Err(err) => eprintln!("Error processing file: {}", err),
    }
}

A função read_file_contents retorna um io::Result que representa a possibilidade de um erro de E/S. Usando o ? operador após cada operação assíncrona, o Tokio runtime irá propagar erros na pilha de chamadas.

A função principal lida com o resultado com uma instrução de correspondência que imprime um texto com base no resultado da operação.

Reqwest usa programação assíncrona para operações HTTP

Muitas caixas populares, incluindo Reqwest, usam o Tokio para fornecer operações HTTP assíncronas.

Você pode usar Tokio com Reqwest para fazer várias solicitações HTTP sem bloquear outras tarefas. Tokio pode ajudá-lo a lidar com milhares de conexões simultâneas e gerenciar recursos com eficiência.