7 puntos por GN⁺ 2026-01-07 | 8 comentarios | Compartir por WhatsApp
  • SQLite es desde 2000 un motor de base de datos ligero implementado en lenguaje C, y no tiene planes de reescribirse en otro lenguaje
  • C se considera el lenguaje más adecuado para SQLite en términos de rendimiento, compatibilidad, mínimas dependencias y estabilidad
  • Los lenguajes orientados a objetos (C++, Java, etc.) tienen grandes limitaciones para llamadas entre lenguajes, y un enfoque procedural puede ser más simple y rápido
  • Los “lenguajes seguros” como Rust o Go todavía no han madurado lo suficiente y no se ajustan a la estrategia de calidad de SQLite (por ejemplo, pruebas del 100% de ramas y recuperación ante OOM)
  • La posibilidad de portar SQLite a Rust sigue abierta en el futuro, pero solo si se cumplen varias condiciones relacionadas con madurez, compatibilidad, rendimiento y soporte de herramientas

1. Por qué C es la mejor opción

  • SQLite fue implementado desde el principio en lenguaje C estándar el 29 de mayo de 2000, y hasta hoy no hay planes de cambiar a otro lenguaje
  • Se presentan como razones por las que C es adecuado para SQLite el rendimiento, la compatibilidad, las bajas dependencias y la estabilidad

1.1 Rendimiento

  • SQLite es una biblioteca de bajo nivel usada intensivamente, por lo que la velocidad es indispensable
    • Como ejemplo, su rendimiento se demuestra en los documentos “Internal Versus External BLOBs” y “35% Faster Than The Filesystem”
  • A C se le llama un “lenguaje ensamblador portable”, ya que ofrece control cercano al hardware y al mismo tiempo mantiene la portabilidad entre plataformas
  • Aunque otros lenguajes afirman ser “tan rápidos como C”, ninguno afirma ser más rápido que C

1.2 Compatibilidad

  • Casi todos los sistemas ofrecen capacidad para llamar bibliotecas escritas en C
  • Por ejemplo, Android puede llamar a SQLite desde aplicaciones Java mediante un adaptador
  • Si SQLite hubiera sido escrito en Java, no podría usarse en apps de iPhone basadas en Objective-C o Swift

1.3 Bajas dependencias

  • Las bibliotecas escritas en C tienen muy pocas dependencias de runtime
  • En una configuración mínima, SQLite solo necesita las siguientes funciones de la biblioteca estándar de C
    • memcmp(), memcpy(), memmove(), memset(), strcmp(), strlen(), strncmp()
  • Incluso en una compilación completa, solo usa malloc(), free() y entrada/salida de archivos
  • En cambio, los lenguajes modernos requieren runtimes de varios MB y miles de interfaces

1.4 Estabilidad

  • C es un lenguaje antiguo y con pocos cambios, que ofrece un comportamiento claro y predecible
  • Al desarrollar un motor de base de datos pequeño, rápido y confiable como SQLite, es importante que la especificación del lenguaje no cambie con frecuencia

2. Por qué no está escrito en un lenguaje orientado a objetos

  • Algunos desarrolladores creen que un sistema complejo solo puede implementarse con un lenguaje orientado a objetos, pero SQLite demuestra lo contrario

  • Una biblioteca escrita en C++ o Java normalmente solo puede usarse desde aplicaciones escritas en ese mismo lenguaje

    • En cambio, una biblioteca en C puede llamarse desde casi cualquier lenguaje
  • La orientación a objetos es un patrón de diseño, no el lenguaje en sí, y una estructura orientada a objetos también puede implementarse en C

  • La orientación a objetos no siempre es lo mejor, y en algunos casos el código procedural puede ser más simple y ventajoso en mantenimiento y rendimiento

  • En los inicios de SQLite (principios de los 2000), Java todavía era inmaduro y C++ tenía graves problemas de compatibilidad entre compiladores

    • En ese momento, C era claramente una mejor elección, y hoy sigue habiendo muy pocos beneficios en reescribirlo

3. Por qué no está escrito en un “lenguaje seguro”

  • En años recientes han llamado la atención los “lenguajes seguros” como Rust y Go, pero SQLite sigue manteniéndose en C
  1. Durante los primeros 10 años de SQLite no existían lenguajes seguros
    • Se podría reescribir en Go o Rust, pero existe el riesgo de introducir nuevos errores y perder rendimiento
  2. Los lenguajes seguros insertan ramas (branches) adicionales, como verificaciones de límites de arreglos
    • En código correcto, esas ramas no se ejecutan, por lo que no es posible hacer pruebas del 100% de ramas
  3. La mayoría de los lenguajes seguros detienen el programa cuando falta memoria (OOM)
    • SQLite está diseñado para recuperarse normalmente incluso ante OOM, y ese comportamiento entra en conflicto con eso
  4. Todos los lenguajes seguros existentes son nuevos y cambian rápidamente
    • SQLite prefiere lenguajes antiguos y estables

4. Posibilidad de portar SQLite a Rust

  • Existe la posibilidad de reescribir SQLite en Rust, pero portarlo a Go es casi imposible
    • Motivo: a Go no le gusta assert()
  • Condiciones previas para portar SQLite a Rust
    1. Que Rust madure más y reduzca su ritmo de cambio hasta convertirse en un “lenguaje antiguo y estable”
    2. Que Rust pueda generar bibliotecas de propósito general invocables desde todos los lenguajes
    3. Que pueda generar código objeto que funcione incluso en dispositivos embebidos sin sistema operativo
    4. Que cuente con un ecosistema de herramientas que soporte pruebas con cobertura del 100% de ramas
    5. Que ofrezca un mecanismo de recuperación ante OOM
    6. Que demuestre una implementación a nivel de C sin pérdida de rendimiento
  • Los desarrolladores que crean que Rust cumple estas condiciones pueden contactar directamente al equipo de SQLite para discutirlo

5. Conclusión

  • SQLite es un motor de base de datos pequeño, rápido y confiable, y las características del lenguaje C encajan con ese objetivo
  • Cambiar a un lenguaje orientado a objetos o a uno seguro no ofrece beneficios reales en compatibilidad, rendimiento ni control de calidad
  • La simplicidad y estabilidad de C respaldan el mantenimiento a largo plazo y la confiabilidad de SQLite

8 comentarios

 
ndrgrd 2026-01-10

Total, es un proyecto que ni siquiera acepta PRs, así que... usan lo que ellos quieren usar.

 
skrevolve 2026-01-09

Si la situación es compacta, no hay un lenguaje que reemplace a C, C++ y Rust. Simplemente no hay muchos desarrolladores que se identifiquen con eso de desarrollar preocupándose por overflow a nivel de bits o por posibles hacks en structs o maps.

 
[Este comentario fue ocultado.]
 
aqqnucs 2026-01-08

El título es demasiado sensacionalista. Si ven el artículo original, trata sobre por qué C es el más adecuado para el desarrollo de SQLite. Ojalá todos se calmen un poco.

 
aqqnucs 2026-01-08

¿No, pero incluso el texto en sí fue escrito hace 7 años? Parece que le fueron agregando cosas después y que se actualizó parcialmente en 2025... 🤦

 
wahihi 2026-01-08

Lo importante es poder hacer ese tipo de juicio de usar un lenguaje adecuado según cada situación de desarrollo; poner un título así, como si un lenguaje en particular siempre fuera bueno, es un nivel de pensamiento de alguien que apenas terminó la secundaria...

 
m00nny 2026-01-08

Creo que la mayor ventaja de C es que toca directamente la esencia de que “una computadora es una secuencia de bits”. Tiene el atractivo de que, gracias a la filosofía simple de C y al agresivo reinterpret casting, el usuario casi siempre puede saber a qué código máquina se va a traducir. No es que por ser C se pueda llamar desde todos los lenguajes; lo que se puede invocar es el ABI, y en C simplemente es posible predecir —o se debe poder predecir— qué secuencia de bits entra y sale. También creo que, cuando siempre discutimos sobre la viabilidad de implementación, es importante distinguir si algo es imposible en una máquina de Turing o si es imposible en el lenguaje o framework que estamos usando ahora mismo.

 
GN⁺ 2026-01-07
Comentarios de Hacker News
  • No creo que haya que justificar por qué no todos los proyectos o programadores usan Rust o Zig.
    En Hacker News y en otras plataformas hay una tendencia a empujar demasiado esos lenguajes.
    Si con C ya se están logrando buenos resultados y los usuarios están satisfechos, no hay razón para que desde afuera se ande opinando de más.

    • Es natural que los lenguajes nuevos reciban atención.
      Es normal que a la gente interesada en el avance tecnológico le atraiga explorar el potencial de los nuevos lenguajes.
      Aun así, aunque desde afuera exista la libertad de opinar, los proyectos no tienen la obligación de escuchar.
    • Si se mira la filosofía de diseño de Rust y los recientes casos de bugs de Rust en el kernel de Linux, Rust no es una solución perfecta.
      Rust reduce la exposición a bugs, pero ese mismo tipo de bugs sigue existiendo.
      Los desarrolladores de C tienden a reaccionar con más sensibilidad ante las condiciones de carrera, y en Rust existe el riesgo de confiarse demasiado en las anotaciones de “seguridad”.
      Además, en Rust las correcciones no siempre son simples, así que la carga de refactorización puede ser mayor.
      Al final, Rust es un lenguaje interesante, pero no es una solución universal, y no debería imponerse.
    • Últimamente incluso está creciendo el escepticismo hacia la POO.
      Lenguajes como Rust o Zig tienen la intención de alejarse de los patrones tradicionales de programación orientada a objetos.
      La POO en algún momento fue atractiva como un marco conceptual que ofrecía una especie de “iluminación”, pero en la práctica muchas veces aumenta la complejidad y perjudica la modularidad.
    • Si Rust fuera mejor en todos los aspectos y realmente redujera bugs, no sería raro que la gente lo alabara.
      Igual que es natural usar un taladro eléctrico en vez de uno manual, si existe una herramienta mejor, lo normal es usarla.
    • Recientemente el gobierno de Estados Unidos recomendó dejar de usar lenguajes que no son memory-safe (como C).
      Pero también hace falta que evolucionen lo suficiente las herramientas y la capacitación para poder escribir C seguro.
  • Soy un Rustacean bastante serio, pero no creo que sea razonable reescribir todos los proyectos en Rust.
    Si se migra a Rust un proyecto en C que ya está bien probado, a corto plazo incluso puede haber más bugs.
    Aun así, algunos están intentando reescribir partes en Rust; por ejemplo, está Limbo: un proyecto que reescribe SQLite por completo en Rust.

    • Limbo es interesante, pero tiene una limitación importante: no permite acceso multiproceso.
      Una de las grandes ventajas de SQLite es que varios procesos pueden acceder a él al mismo tiempo; si eso desaparece, su campo de uso se reduce bastante.
    • Los desarrolladores de Rust no necesitan esperar la aprobación de SQLite.
      Pueden crear su propia versión y probar por cuenta propia si tiene éxito o no.
    • Personalmente, me parece más razonable crear una nueva base de datos embebida en Rust que portar SQLite.
    • Voy a seguir observando cómo evoluciona Limbo.
  • Tuve experiencia migrando RediSearch a Rust.
    Eso fue porque últimamente había muchas vulnerabilidades CVE.
    Si SQLite no tiene ese tipo de problemas, entonces hay menos motivos para moverlo a Rust.
    Creo que harán falta décadas para entender de verdad las fortalezas y limitaciones de Rust.
    En particular, la utilidad de Rust en las aplicaciones GUI todavía no está clara.

    • La estabilidad y ese carácter “aburrido” de C son el resultado de décadas de prueba y error.
      Para que Rust alcance un nivel similar de confianza, quizá tenga que llegar alrededor de 2040.
    • Para sistemas como SQLite, lenguajes como Ada/SPARK podrían ser más adecuados.
  • Como mencionó Linus, Rust necesita un mecanismo de recuperación ante OOM (Out of Memory).
    Se puede ver más sobre esto en el enlace a la discusión en LKML.

    • Pero las características del propio lenguaje Rust están orientadas por defecto a la asignación en stack, así que no llaman directamente a malloc.
      En código embebido o de kernel, incluso se puede desactivar por completo la funcionalidad de asignación.
      Es decir, Rust ya ofrece control total sobre la memoria.
    • (Como nota al margen) también se compartió código para mejorar el CSS de esa página.
    • La observación de Linus es válida, pero también hace falta ordenar los problemas de su propio bando.
  • La afirmación de que “no existe un lenguaje de propósito general más rápido que C” es una comparación parcial que ignora el tiempo del desarrollador.
    En vez de tardar 5 horas en hacer con C un programa que corre en 4 segundos, puede ser más realista hacer en otro lenguaje uno que corre en 5 segundos pero está listo en 5 minutos.

    • Pero en software como SQLite, donde el tiempo de CPU del usuario domina ampliamente, la eficiencia de C importa mucho más.
      Cuantos más usuarios haya, más valor acumulado tienen incluso pequeñas diferencias de velocidad.
    • Al final, si se prioriza el tiempo del usuario, la optimización de rendimiento en C sigue teniendo mucho sentido.
  • A Rust todavía le falta bastante para convertirse en un lenguaje “aburrido y estable”.
    Mientras que C es administrado por un comité conservador que cuida con rigor la compatibilidad, Rust prioriza la innovación por encima de la compatibilidad para resolver problemas.

    • En Rust, el lenguaje en sí a veces rompe compatibilidad, pero el ecosistema de herramientas es estable.
      Código de versiones viejas puede seguir compilándose con compiladores nuevos.
    • Rust opta por manejar automáticamente el código viejo con compiladores viejos para reducir la carga del legado.
      Me parece un enfoque mejor que el de C++, que sigue cargando con funcionalidades del pasado.
    • El conservadurismo de C no es algo “extraño”, sino un símbolo de estabilidad.
    • C fue diseñado originalmente por una sola persona con ideas fuertes, por eso tenía una dirección clara.
      En cambio, lenguajes diseñados por comité, como C++ o Common Lisp, aumentaron su complejidad.
      Rust también es grande, así que conviene usarlo con cautela en sistemas embebidos o sistemas críticos.
    • Aun así, parece posible que Rust eventualmente entre en una etapa de estabilidad.
  • Coincido con la actitud de “si algo funciona bien, no hay que romperlo porque sí”.
    La historia de la evolución de los lenguajes parece una repetición constante del proceso de resolver problemas para luego crear nueva complejidad.

    • Mozilla creó Rust por los problemas de C++, pero Rust no es simplemente un reemplazo de C++.
      C es un caso representativo de la filosofía de “Worse is Better”, y tuvo éxito durante décadas gracias a su simplicidad.
      Rust, en cambio, apunta al “Right Thing™”.
      Hoy, como en la mayoría de los entornos la carga de implementar todo manualmente ha disminuido, ahora puede ser una mejor opción.
      Pero no hace falta mover a la fuerza proyectos que ya tuvieron éxito.
      Si es un proyecto nuevo, es muy probable que Rust sea una mejor elección.
  • La simplicidad y estabilidad de C son ventajas subestimadas.
    Me parece mejor pulir la biblioteca estándar o el ecosistema que seguir cambiando el lenguaje en sí.

    • Aun así, C sigue teniendo bastante UB (comportamiento indefinido), así que hay que tener cuidado.
      No solo importa la simplicidad, también es importante la garantía de comportamiento determinista.
    • Prefiero lenguajes simples, elegantes y estables como Clojure.
    • Incluso cuando C agrega funciones nuevas, casi siempre son mejoras prácticas y poco controvertidas.
      Por ejemplo, me gustan características como designated initializer, compound literal, alignas y memset_explicit.
  • Personalmente, sigo pensando que C sigue siendo lo mejor.
    Rust tiene muchas buenas ideas, pero también es un lenguaje con desventajas muy claras.
    Todavía hay un ambiente en el que es difícil discutir con frialdad los problemas de Rust.

    • Si se señalaran de forma concreta cuáles son las desventajas de Rust, la discusión sería más productiva.
      Por ejemplo, podrían mencionarse cosas como la curva de aprendizaje o la complejidad del empaquetado.
    • La afirmación de que “Rust es un lenguaje terrible” necesita fundamentos concretos.
  • Ya no es cierto eso de que “todos los sistemas pueden llamar bibliotecas en C”.
    Rust y Zig también cumplen con ese requisito.
    Aun así, la biblioteca estándar de Rust muchas veces hace panic en vez de recuperarse ante OOM, y además la documentación es insuficiente.

    • En Rust y Zig hay que usar explícitamente extern "C" o export para tener compatibilidad con la ABI de C.
      De lo contrario, la ABI no está definida y puede ser incluso más inestable que C++.
      En especial, este problema puede hacerse mayor en distribuciones Linux que distribuyen crates de Rust.