- O escalonador de CPU do kernel oferece vários modos de preempção que implementam um compromisso entre vazão do sistema e tempo de resposta.
- Em setembro de 2023, durante discussões sobre escalonamento, foi proposto o conceito de "preempção preguiçosa (lazy preemption)", que pode simplificar o escalonamento do kernel ao mesmo tempo em que oferece resultados melhores.
- A ideia ficou em silêncio por algum tempo, mas reapareceu com uma série de patches de Peter Zijlstra.
Modos atuais de preempção no kernel
- PREEMPT_NONE: a preempção só é permitida quando a tarefa em execução esgota seu time slice.
- PREEMPT_VOLUNTARY: adiciona muitos pontos no kernel onde a preempção é possível quando necessário.
- PREEMPT_FULL: permite preempção em quase todos os pontos, exceto quando há spinlocks mantidos.
- PREEMPT_RT: prioriza a preempção acima da maioria das outras coisas, tornando preemptível também a maior parte do código com spinlocks.
Introdução da preempção preguiçosa
- O patch de preempção preguiçosa adiciona uma nova flag
TIF_NEED_RESCHED_LAZY para indicar que um reescalonamento será necessário em algum momento, e não imediatamente.
- No modo de preempção preguiçosa (PREEMPT_LAZY), a maioria dos eventos define essa nova flag, e ao retornar do kernel para o espaço do usuário, a chamada ao escalonador ocorre se qualquer uma das duas flags estiver definida.
- Como resultado dessa mudança, no modo de preempção preguiçosa a maioria dos eventos no kernel deixa de preemptar a tarefa atual.
Remoção de cond_resched()
- O objetivo final desse trabalho é deixar apenas dois modos não em tempo real: PREEMPT_LAZY e PREEMPT_FULL.
- O modo preguiçoso ocupa a posição entre PREEMPT_NONE e PREEMPT_VOLUNTARY, substituindo esses dois modos.
- Atualmente, ainda restam chamadas a
cond_resched(), e elas são necessárias enquanto os modos PREEMPT_NONE e PREEMPT_VOLUNTARY existirem.
Resumo do GN⁺
- A preempção preguiçosa pode ajudar a simplificar o escalonamento do kernel e a oferecer latências mais previsíveis.
- Esse trabalho pode ajudar a reduzir o tamanho do kernel e simplificar o código.
- A preempção preguiçosa oferece vazão semelhante à do PREEMPT_VOLUNTARY, mas ainda precisa de mais testes e otimização.
- Um outro projeto com funcionalidade semelhante é o escalonador ULE do FreeBSD.
1 comentários
Comentários no Hacker News
O resultado final do trabalho de preempção preguiçosa é que o kernel fique menor e mais simples, ao mesmo tempo em que oferece latência previsível. Isso parece ser uma solução melhor, sem a necessidade de espalhar chamadas relacionadas ao escalonador por todo o código. No entanto, levará tempo para alcançar isso.
Um nível alto de preempção permite que o sistema reaja mais rapidamente a eventos. Reações rápidas a eventos como o movimento do mouse ou um sinal de "colapso iminente" de um reator são mais satisfatórias. No entanto, um nível alto de preempção pode afetar a taxa de transferência total do sistema. Cargas de trabalho com muitas tarefas intensivas em CPU se beneficiam de sofrer o mínimo possível de interrupções. Preempções mais frequentes podem causar maior contenção de locks. É por isso que existem modos diferentes, e o modo ideal de preempção provavelmente depende da carga de trabalho.
O kernel atual tem quatro modos que controlam quando uma tarefa pode ser preemptada em favor de outra.
Não consegui encontrar números relacionados ao patch no tópico linkado. Algum benchmark preliminar deve ter sido feito para indicar o potencial real da mudança.
Fico me perguntando o quão fortemente acoplado o escalonador está ao restante do código do kernel.
Seria bom se a preempção pudesse se adaptar de acordo com o evento, mas gerenciar isso para todos os eventos pode prejudicar a estabilidade do sistema. Isso é parecido com gerar leads usando ferramentas como o Tomba Finder.