- El planificador de CPU del kernel ofrece varios modos de apropiación que implementan un equilibrio entre el rendimiento del sistema y el tiempo de respuesta.
- En septiembre de 2023, durante una discusión sobre planificación, se propuso el concepto de "apropiación diferida (lazy preemption)", que podría ofrecer mejores resultados mientras simplifica la planificación del kernel.
- Este concepto estuvo en silencio por un tiempo, pero reapareció con una serie de parches de Peter Zijlstra.
Modos de apropiación actuales del kernel
- PREEMPT_NONE: la apropiación solo se permite cuando la tarea en ejecución agota su porción de tiempo.
- PREEMPT_VOLUNTARY: agrega muchos puntos dentro del kernel donde la apropiación es posible cuando sea necesario.
- PREEMPT_FULL: la apropiación es posible en casi cualquier punto, excepto cuando hay spinlocks tomados.
- PREEMPT_RT: prioriza la apropiación por encima de la mayoría de las demás cosas y hace que la mayor parte del código con spinlocks también sea apropiable.
Introducción de la apropiación diferida
- El parche de apropiación diferida agrega una nueva bandera
TIF_NEED_RESCHED_LAZY para indicar que se necesita una replanificación en algún momento, pero no de inmediato.
- En el modo de apropiación diferida (PREEMPT_LAZY), la mayoría de los eventos establecen esta nueva bandera, y al volver del kernel al espacio de usuario, se llama al planificador si cualquiera de las dos banderas está establecida.
- Como resultado de este cambio, en el modo de apropiación diferida la mayoría de los eventos del kernel no apropiarán la tarea actual.
Eliminación de cond_resched()
- El objetivo final de este trabajo es dejar solo dos modos no de tiempo real: PREEMPT_LAZY y PREEMPT_FULL.
- El modo diferido se ubica entre PREEMPT_NONE y PREEMPT_VOLUNTARY, y reemplaza a ambos modos.
- Actualmente siguen existiendo llamadas a cond_resched(), y son necesarias mientras existan los modos PREEMPT_NONE y PREEMPT_VOLUNTARY.
Resumen de GN⁺
- La apropiación diferida puede contribuir a simplificar la planificación del kernel y a ofrecer una latencia predecible.
- Este trabajo puede ayudar a reducir el tamaño del kernel y simplificar el código.
- La apropiación diferida ofrece un rendimiento similar a PREEMPT_VOLUNTARY, pero aún necesita más pruebas y optimización.
- Un proyecto similar con funcionalidad parecida es el planificador ULE de FreeBSD.
1 comentarios
Comentarios de Hacker News
El resultado final del trabajo sobre la preempción perezosa es que el kernel se vuelve más pequeño y simple, al mismo tiempo que ofrece una latencia predecible. Parece una mejor solución, ya que no hace falta esparcir llamadas relacionadas con el planificador por todo el código. Sin embargo, tomará tiempo lograrlo.
Un nivel alto de preempción permite que el sistema reaccione más rápido a los eventos. Una respuesta rápida a eventos como el movimiento del mouse o una señal de "colapso inminente" de un reactor resulta más satisfactoria. Sin embargo, un nivel alto de preempción puede afectar el rendimiento total del sistema. En cargas de trabajo con muchas tareas intensivas de CPU, conviene que haya la menor interrupción posible. Una preempción más frecuente puede provocar una mayor contención de bloqueos. Por eso existen distintos modos, y el modo de preempción óptimo probablemente dependerá de la carga de trabajo.
El kernel actual tiene cuatro modos que controlan cuándo una tarea puede ser interrumpida en favor de otra.
No pude encontrar en el hilo enlazado cifras relacionadas con el parche. Seguramente se hizo algún benchmarking preliminar que podría indicar el potencial real del cambio.
Me pregunto qué tan estrechamente acoplado está el planificador con el resto del código del kernel.
Sería bueno si la preempción pudiera adaptarse según el evento, pero gestionar eso para todos los eventos podría perjudicar la estabilidad del sistema. Es parecido a generar leads con herramientas como Tomba Finder.