El Ecosistema Startup > Blog > Actualidad Startup > SBCL Fibers: hilos cooperativos ligeros en Lisp

SBCL Fibers: hilos cooperativos ligeros en Lisp

¿Qué son las SBCL Fibers y por qué importan para el backend moderno?

La programación concurrente es uno de los grandes retos de cualquier arquitectura de backend que necesite escalar. Los hilos del sistema operativo (OS threads) han sido la solución dominante durante décadas, pero traen consigo un costo real: alto consumo de memoria, cambios de contexto lentos y un techo duro cuando se habla de cientos de miles de conexiones simultáneas. SBCL Fibers propone una respuesta concreta a este problema dentro del ecosistema de Common Lisp: hilos cooperativos ligeros en espacio de usuario (user-space green threads) que permiten escalar a millones de tareas concurrentes con una fracción del costo.

Este artículo analiza cómo funcionan, qué API exponen, cómo se integran con el recolector de basura de SBCL (Steel Bank Common Lisp) y qué implica para founders y equipos de ingeniería que construyen backends de alto rendimiento.

El problema que resuelven: los límites del modelo tradicional de hilos

Un servidor web basado en OS threads típicamente soporta del orden de ~100.000 conexiones concurrentes antes de enfrentar agotamiento de memoria (cada hilo ocupa alrededor de 8 MB de stack) y degradación severa por cambios de contexto (~1–5 µs cada uno). Para workloads I/O-bound —como servidores HTTP, APIs o brokers de mensajes— esto es un cuello de botella estructural.

👥 ¿Quieres ir más allá de la noticia?

En nuestra comunidad discutimos las tendencias, compartimos oportunidades y nos ayudamos entre emprendedores. Sin humo, solo acción.

👥 Unirme a la comunidad

Las SBCL Fibers atacan exactamente este punto: son entidades de concurrencia que viven en espacio de usuario, se multiplexan sobre un número pequeño de OS threads y ceden el control de forma cooperativa (no preemptiva). El resultado es que un solo servidor puede mantener 10 millones o más de fibers activas simultáneamente con cambios de contexto de aproximadamente ~100 ns.

Arquitectura interna: cómo están construidas las SBCL Fibers

Gestión de stacks

Cada fiber recibe un stack propio, inicialmente de 16 KB, que puede crecer o reducirse dinámicamente. Se asigna mediante mmap (Linux/macOS) o VirtualAlloc (Windows) con semántica copy-on-write, lo que reduce drásticamente el consumo de memoria en estado de reposo. Crear 1 millón de fibers tarda aproximadamente 0,5 segundos con este esquema.

Integración con el Garbage Collector

Uno de los aspectos más delicados al implementar green threads en un lenguaje con GC es garantizar que el recolector pueda rastrear correctamente todos los objetos vivos. SBCL Fibers resuelve esto mediante alien stack scanning: cada fiber registra sus raíces de stack con el GC, de modo que durante una recolección solo se escanean los stacks activos. Con 1 millón de fibers, las pausas de GC se mantienen por debajo de 1 ms, algo inviable con OS threads convencionales.

Scheduler y work stealing

El scheduler implementa un modelo M:N (muchas fibers sobre pocos OS threads). Cada OS thread mantiene una cola local de fibers ejecutables; existe además una cola global compartida. Cuando un thread termina su trabajo local, roba tareas de los threads vecinos usando acceso lock-free (contadores atómicos). Las fibers ceden control explícitamente mediante fiber-yield.

Multiplexación de I/O

Para el I/O no bloqueante, SBCL Fibers se integra con libuv (a través de la librería luv). Cuando una fiber espera datos de red o disco, cede al runloop, que mantiene un uv_poll activo. En cuanto el descriptor está listo, el runloop reagenda la fiber sin bloquear ningún OS thread. Este es el patrón que hace viable servir miles de conexiones HTTP desde un solo proceso Lisp.

API principal: cómo usar SBCL Fibers en la práctica

La API está diseñada para ser directa y componible. Las funciones y macros centrales son:

  • (make-fiber :name "nombre" :function #'mi-funcion) — Crea y agenda una fiber.
  • (current-fiber) — Devuelve la fiber actualmente en ejecución.
  • (fiber-yield) — Cede el control al scheduler voluntariamente.
  • (fiber-interrupt fiber thunk) — Programa la ejecución de thunk sobre otra fiber.
  • (spawn (&rest forms) &rest args) — Macro de conveniencia para crear fibers rápidamente.
  • (with-fibers (&body body)) — Inicializa el scheduler y ejecuta el cuerpo.

Para comunicación entre fibers, se usan channels:

  • (make-channel :buffered-p t :size 64) — Canal con buffer.
  • (send chan value) / (receive chan) — Envío y recepción (bloqueantes para la fiber, no para el OS thread).
  • (receive-with-timeout chan timeout) — Recepción con timeout no bloqueante.

Integración con Hunchentoot: servidor HTTP en Common Lisp

Hunchentoot es el servidor HTTP más usado en el ecosistema Lisp. La integración con SBCL Fibers sigue un patrón simple: cada request HTTP lanza una fiber dedicada, eliminando el overhead de crear un OS thread por conexión.

Los benchmarks reportados son significativos: con Hunchentoot sobre SBCL Fibers en un servidor de 16 cores, se alcanzan 1,2 millones de requests por segundo con 16.000 conexiones concurrentes. En el mismo hardware con OS threads nativos, el techo ronda los 200.000 req/s antes de la degradación.

Comparativa con otros modelos de concurrencia

Para dimensionar bien la propuesta, aquí un resumen de cómo se compara SBCL Fibers con alternativas relevantes:

  • OS Threads (SBCL nativo): Preemptivos, sencillos de razonar, pero ~8 MB/thread y cambios de contexto lentos. Viables hasta ~100K concurrencia.
  • lparallel (CL): Work-stealing sobre un pool fijo de OS threads. Ideal para CPU-bound; no escala en I/O intensivo.
  • Go Goroutines: Modelo M:N similar, integrado en el runtime del lenguaje. Las fibers SBCL ofrecen el mismo patrón pero dentro del ecosistema Lisp, con toda la expresividad del lenguaje.
  • Erlang Processes: Actor model con aislamiento fuerte. Mayor overhead por mensaje; fibers son más de bajo nivel y flexibles.
  • Async/Await (Python, JS): Concurrencia cooperativa basada en coroutines. Fibers logran lo mismo sin transformar el código en máquinas de estados explícitas.

Consideraciones prácticas para equipos de ingeniería

Antes de adoptar SBCL Fibers en producción, hay puntos clave a evaluar:

  • Cooperative scheduling: Las fibers no son preemptivas. Si una fiber ejecuta un loop de cómputo intensivo sin ceder, bloquea al OS thread anfitrión. Para workloads CPU-bound, lo recomendado es combinar fibers con lparallel.
  • Debugging: Los debuggers convencionales de SBCL tienen soporte limitado para inspeccionar stacks de fibers. Se recomienda usar fiber-step para debugging granular.
  • Windows: El soporte en Windows es experimental en la versión actual.
  • Integración con librerías bloqueantes: Si una librería hace syscalls bloqueantes directamente, anula la ventaja de las fibers. Es necesario usar wrappers no bloqueantes o delegar a un thread pool separado.

Rendimiento en cifras

Para tener una referencia concreta de lo que ofrece este modelo:

  • Cambio de contexto: ~100 ns (vs. ~1–5 µs de OS threads).
  • Concurrencia máxima: 10M+ fibers en un proceso.
  • Arranque de 1M fibers: ~0,5 segundos.
  • Pausa de GC con 1M fibers activas: menos de 1 ms.
  • Throughput HTTP (16 cores): 1,2M req/s con 16K conexiones concurrentes.

¿Cuándo tiene sentido adoptar SBCL Fibers?

Este modelo brilla en escenarios donde el cuello de botella es la concurrencia I/O-bound a escala: servidores web con miles de conexiones simultáneas, proxies, gateways de API, brokers de eventos o cualquier sistema que maneje muchos clientes con poco cómputo por request. Si tu stack ya es Lisp o considerás SBCL para tu backend, las fibers son la herramienta de concurrencia más eficiente disponible hoy en ese ecosistema.

Conclusión

SBCL Fibers representa una implementación madura y bien pensada de concurrencia cooperativa para Common Lisp, con una arquitectura que resuelve los tres grandes problemas de los OS threads: consumo de memoria, velocidad de cambio de contexto y escalabilidad en workloads I/O-bound. La integración cuidadosa con el GC de SBCL, el scheduler con work stealing y el modelo de I/O no bloqueante via libuv la posicionan como una alternativa seria a Go Goroutines o Erlang para quienes trabajan en el ecosistema Lisp.

Para founders y equipos técnicos que buscan exprimir el rendimiento de su infraestructura backend sin abandonar la expresividad de Common Lisp, esta propuesta merece atención seria. Las cifras de benchmark son contundentes y el diseño está alineado con las mejores prácticas del área.

Descubre cómo otros founders implementan estas soluciones de concurrencia y backend en su stack tecnológico. Únete gratis a la comunidad de Ecosistema Startup.

Ver soluciones de founders

Fuentes

  1. https://atgreen.github.io/repl-yell/posts/sbcl-fibers/ (fuente original)
  2. https://www.sbcl.org (fuente adicional)
  3. https://simonsafar.com/2020/sbcl/ (fuente adicional)
  4. https://lisp-lang.org/wiki/article/implementations (fuente adicional)
  5. https://news.ycombinator.com/item?id=21104834 (fuente adicional)
¿te gustó o sirvió lo que leíste?, Por favor, comparte.

Daily Shot: Tu ventaja táctica

Lo que pasó en las últimas 24 horas, resumido para que tú no tengas que filtrarlo.

Suscríbete para recibir cada mañana la curaduría definitiva del ecosistema startup e inversionista. Sin ruido ni rodeos, solo la información estratégica que necesitas para avanzar:

  • Venture Capital & Inversiones: Rondas, fondos y movimientos de capital.
  • IA & Tecnología: Tendencias, Web3 y herramientas de automatización.
  • Modelos de Negocio: Actualidad en SaaS, Fintech y Cripto.
  • Propósito: Erradicar el estancamiento informativo dándote claridad desde tu primer café.

📡 El Daily Shot Startupero

Noticias del ecosistema startup en 2 minutos. Gratis, cada día hábil.


Share to...