1 pontos por GN⁺ 2023-10-08 | 1 comentários | Compartilhar no WhatsApp
  • Este artigo discute, na comunidade Rust, a controvérsia sobre o uso de executores multithread, que são runtimes assíncronos que realizam work-stealing para distribuir tarefas de forma equilibrada.
  • Alguns usuários de Rust defendem uma arquitetura alternativa chamada "thread-per-core", que promete melhor desempenho e implementação mais simples.
  • O termo "thread-per-core" é enganoso. Todo executor multithread é thread-per-core, criando uma thread do sistema operacional por núcleo e agendando tarefas sobre essas threads.
  • Thread-per-core combina três ideias: tratar a concorrência no espaço do usuário, tornar o I/O assíncrono para evitar bloqueio de threads e particionar os dados entre os núcleos de CPU para eliminar custos de sincronização e a movimentação de dados entre caches de CPU.
  • A controvérsia gira principalmente em torno do terceiro ponto, e usar Rust assíncrono permite atender aos dois primeiros requisitos.
  • Na arquitetura thread-per-core, é possível fazer duas otimizações: roubar trabalho entre threads e compartilhar o mínimo possível de estado.
  • O work-stealing melhora a latência de cauda ao garantir que todas as threads estejam sempre ocupadas, mas é difícil de implementar e pode causar custos de sincronização e falhas de cache.
  • O modelo share-nothing melhora a latência de cauda ao manter os dados em caches mais rápidas associadas a um único núcleo de CPU, mas pode ser difícil de implementar em aplicações complexas que precisam alterar estado em várias partições.
  • O artigo sugere que, em sistemas com estado compartilhado, o work-stealing pode melhorar a utilização da CPU sob carga.

1 comentários

 
GN⁺ 2023-10-08
Comentários no Hacker News
  • O cerne da discussão não são os executors com roubo de trabalho thread-per-core, e sim se async/await é uma boa abstração em Rust.
  • Thread-per-core foi inventado para resolver a escalabilidade e a eficiência da computação em servidores comuns com muitos núcleos, e acabou se mostrando excelente para cargas de trabalho I/O-bound de alta vazão.
  • A arquitetura thread-per-core veio para ficar por causa de sua escalabilidade e eficiência, mas a maioria dos engenheiros de software tem intuição limitada sobre como é um design thread-per-core moderno e idiomático.
  • Algumas aplicações são mais adequadas a sistemas single-threaded, e Rust permite essa flexibilidade.
  • Há críticas à programação async em Rust, incluindo a exigência de Send + Sync + 'static, que alguns consideram incômoda.
  • O bound Send é um requisito que permite mover tarefas entre threads do executor, e parece ser uma falha do sistema async de Rust.
  • Não existe uma abordagem única que alcance o melhor desempenho para todos os programas, e o uso de async é considerado uma otimização prematura para muitos programas em Rust.
  • Como trocas de contexto no kernel são caras, prefere-se o design thread-per-core, mas o escalonamento com troca de contexto em espaço do usuário também pode ser problemático.
  • Roubo de trabalho é uma forma de resolver a latência de cauda, mas causa cache misses e restrições adicionais para o desenvolvedor, como Send, Sync e 'static.