SBCL: Hilos Ligeros Mejoran la Concurrencia

Fuentes: SBCL Fibers: Lightweight Cooperative Threads

Este documento describe una implementación de hilos cooperativos ligeros (fibers) para SBCL, una implementación de Common Lisp. El objetivo principal es proporcionar una alternativa eficiente a los hilos del sistema operativo (OS) para manejar aplicaciones concurrentes, especialmente aquellas con cargas de trabajo intensivas en I/O, como servidores web. Los hilos del OS son costosos en términos de memoria (8MB por hilo) y tiempo de cambio de contexto (transición del kernel), lo que limita su escalabilidad. La programación basada en eventos, una alternativa, complica el flujo de control y dificulta la depuración. Las fibers ofrecen un equilibrio: son hilos de espacio de usuario con sus propias pilas de control y enlaces, programados de forma cooperativa por un programador de nivel de biblioteca. Esto permite mantener un flujo de control secuencial similar a los hilos del OS, pero con una sobrecarga significativamente menor (256KB por fibra por defecto, cambio de contexto en espacio de usuario).

La implementación de SBCL Fibers se centra en la corrección bajo el recolector de basura (GC) de SBCL, que es generacional y compactante. Esto implica que el GC debe poder encontrar todos los objetos Lisp vivos, incluso aquellos en las pilas de control y enlace de las fibras suspendidas, sin corromper la memoria. Para lograr esto, se ha diseñado un sistema que preserva el estado de las fibras, incluyendo enlaces dinámicos, limpieza de unwind-protect y manejo de excepciones. La API incluye funciones para crear y ejecutar fibras, ceder el control (yield), esperar (wait), suspender condicionalmente (parking), unirse a fibras (join), y funciones para la programación multi-carrier. También se incluyen primitivas de bloqueo conscientes de las fibras (mutexes, variables de condición, semáforos) y mecanismos para el control de I/O. La arquitectura incluye hilos carrier y un programador, un estado máquina de ciclo de vida de la fibra, y un diseño de pila de control con gestión de memoria eficiente (pooling de pilas, detección de desbordamiento). Se ha prestado especial atención a la integración con el GC, incluyendo un diseño de dos listas para fibras suspendidas y contextos activos, y optimizaciones para el manejo de enlaces dinámicos. El programador utiliza una cola de deque sin bloqueo para la programación de tareas y se integra con el multiplexado de I/O a través de abstracciones de plataforma (epoll, kqueue, poll). Finalmente, se incluyen características como la detección de inactividad, la programación con plazos y el manejo de la muerte de la fibra. La implementación está en desarrollo activo y los detalles pueden cambiar.