Bloqueando o executor

A maioria dos runtimes async só permite que tarefas de I/O sejam executadas concorrentemente. Isso significa que tarefas que bloqueiam a CPU bloquearão o executor e impedirão que outras tarefas sejam executadas. Uma solução fåcil é usar métodos equivalentes async sempre que possível.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Speaker Notes

This slide should take about 10 minutes.
  • Execute o cĂłdigo e veja que os sleeps acontecem consecutivamente em vez de concorrentemente.

  • A variante "current_thread" coloca todas as tarefas em um Ășnico thread. Isso torna o efeito mais Ăłbvio, mas o bug ainda estĂĄ presente na variante multi-threaded.

  • Troque o std::thread::sleep por tokio::time::sleep e aguarde seu resultado.

  • Outra correção seria tokio::task::spawn_blocking que inicia um thread real e transforma seu handle em uma future sem bloquear o executor.

  • VocĂȘ nĂŁo deve pensar em tarefas como threads do SO. Elas nĂŁo mapeiam 1 para 1 e a maioria dos executors permitirĂĄ que muitas tarefas sejam executadas em um Ășnico thread do SO. Isso Ă© particularmente problemĂĄtico ao interagir com outras bibliotecas via FFI, onde essa biblioteca pode depender de armazenamento local de thread ou mapear para threads especĂ­ficos do SO (por exemplo, CUDA). Prefira tokio::task::spawn_blocking em tais situaçÔes.

  • Use mutexes sync com cuidado. Manter um mutex sobre um .await pode fazer com que outra tarefa bloqueie, e essa tarefa pode estar sendo executada no mesmo thread.