Por qué SQLite fue escrito en C
(sqlite.org)- SQLite se ha desarrollado en lenguaje C desde sus inicios (año 2000) por razones de rendimiento, compatibilidad, pocas dependencias y estabilidad
- C puede usarse en casi todos los sistemas operativos y lenguajes, y en particular permite un funcionamiento rápido como biblioteca de bajo nivel
- La razón para elegir C en lugar de un lenguaje orientado a objetos fue la extensibilidad, la posibilidad de invocarlo desde distintos lenguajes y la inmadurez de C++ y Java en esa época
- SQLite tiene una estructura de un solo archivo con casi ninguna dependencia, y usa solo las funciones mínimas de la biblioteca estándar de C
- Aunque se ha discutido reescribirlo en "lenguajes seguros" como Rust y Go, C sigue teniendo ventaja en control de calidad, rendimiento y capacidad de ser llamado desde bibliotecas
1. Por qué C es la mejor opción
- SQLite se ha mantenido en lenguaje C desde su primer desarrollo el 29 de mayo de 2000 hasta hoy
- Por ahora no hay planes de reescribirlo en otro lenguaje
- C ofrece control cercano al hardware y al mismo tiempo una gran portabilidad, por lo que se le llama un “lenguaje ensamblador portátil”
- Otros lenguajes pueden afirmar que son “tan rápidos como C”, pero ninguno afirma ser más rápido que C
1.1. Rendimiento
- Una biblioteca de bajo nivel como SQLite se invoca con mucha frecuencia, así que debe funcionar muy rápido
- El lenguaje C es adecuado para escribir código veloz, con alta portabilidad y acceso estrecho al hardware
- Otros lenguajes modernos también dicen ser “tan rápidos como C”, pero en programación de propósito general no hay ninguno que con certeza pueda decir que es más rápido que C
- C permite controlar con detalle la memoria y los recursos de CPU, por lo que incluso puede mostrar un rendimiento 35% superior al del sistema de archivos
- Ejemplo: Internal vs External BLOBs
1.2. Compatibilidad
- Casi todos los sistemas pueden invocar bibliotecas escritas en C
- Por ejemplo, incluso en Android (basado en Java) se puede usar SQLite mediante un adaptador
- Si SQLite hubiera sido escrito en Java, no podría usarse en iPhone (Objective-C, Swift), lo que reduciría mucho su propósito general
1.3. Bajas dependencias
- Al estar desarrollado como biblioteca en C, tiene muy pocas dependencias en tiempo de ejecución
- En la configuración mínima solo usa funciones muy básicas de la biblioteca estándar de C (memcmp(), memcpy(), memmove(), memset(), strcmp(), strlen(), strncmp())
- Incluso en una compilación más completa solo tiene unas pocas dependencias, como malloc(), free() y entrada/salida de archivos
- Los lenguajes modernos a menudo requieren múltiples runtimes grandes y miles de interfaces
1.4. Estabilidad
- C es un lenguaje viejo, aburrido y con pocos cambios, pero eso significa previsibilidad y estabilidad
- Para crear un motor de base de datos pequeño, rápido y confiable como SQLite, conviene un lenguaje cuya especificación no cambie con frecuencia
- Si la especificación o la implementación del lenguaje cambian continuamente, eso perjudica la estabilidad de SQLite
2. Por qué no fue escrito en un lenguaje orientado a objetos
- Algunos desarrolladores creen que sería difícil implementar un sistema complejo como SQLite sin orientación a objetos, pero frente a C, crear una biblioteca en C++ o Java hace más difícil llamarla desde otros lenguajes
- Para dar soporte a distintos lenguajes como Haskell o Java, la elección de una biblioteca en C era razonable
- La orientación a objetos no es un lenguaje, sino un patrón de diseño, así que no está limitada a un lenguaje en particular
- Incluso en C es posible implementar patrones orientados a objetos con structs y punteros a función
- La orientación a objetos no siempre es la mejor estructura; a veces el código procedural es más claro, más fácil de mantener y da resultados más rápidos
- En los inicios del desarrollo de SQLite (alrededor del año 2000):
- Java era inmaduro
- C++ tenía graves problemas de compatibilidad entre compiladores
→ En ese momento, C era la opción más práctica y segura
- Incluso hoy, los beneficios de reescribir SQLite siguen siendo escasos
3. Por qué no fue escrito en un "lenguaje seguro"
- Últimamente ha crecido el interés por lenguajes de programación seguros como Rust y Go, pero cuando SQLite se desarrolló originalmente (durante sus primeros 10 años), esos lenguajes no existían
- Si se reescribiera en Go o Rust, podrían aparecer más bugs o disminuir el rendimiento
- Estos lenguajes insertan código de bifurcación adicional para comprobaciones de memoria y similares, y en la estrategia de calidad de SQLite es importante la cobertura de ramas del 100%, algo que aquí no se cumple
- Los lenguajes seguros suelen terminar el programa en situaciones de falta de memoria, pero SQLite está diseñado para poder recuperarse incluso en escenarios de memoria insuficiente
- Rust, Go y otros siguen siendo lenguajes jóvenes y todavía necesitan desarrollo continuo
- Por eso, aunque el equipo de SQLite apoya el avance de los lenguajes seguros, en la implementación de SQLite sigue priorizando la estabilidad comprobada de C
Aun así, existe la posibilidad de que algún día se reescriba en Rust. Es poco probable que se escriba en Go, porque a Go no le gusta assert()
- Pero para que pueda escribirse en Rust, hay condiciones previas:
- Rust tendría que madurar más y ralentizar su ciclo de cambios hasta convertirse en un “lenguaje viejo y aburrido”
- Debe demostrarse que puede crear una biblioteca de propósito general invocable desde múltiples lenguajes
- Debe poder producir código objeto que funcione incluso en dispositivos sin sistema operativo, como sistemas embebidos
- Deben existir herramientas de prueba de cobertura de ramas del 100% sobre los binarios compilados
- Debe ser posible recuperarse de errores OOM (falta de memoria)
- Rust debe poder realizar todo lo que hace C en SQLite sin degradación de rendimiento
- Si algún entusiasta de Rust (rustacean) cree que estas condiciones ya se cumplen y que SQLite debería volver a codificarse en Rust, se le recomienda contactar directamente a los desarrolladores de SQLite para defender su postura
2 comentarios
Comentarios en Hacker News
if (i >= array_length) panic("index out of bounds"), pero ese código en sí ya fue bien probado por el compilador de Rust, así que no debería preocuparnos. Me pregunto si estoy entendiendo bien esa lógicaget_unchecked(), lo que permitiría mantener seguridad y mejorar el rendimiento documentación de get_uncheckedif condition { panic(err) }como una especie de función assertLa frase de que C también representa un riesgo de seguridad para SQLite, ¿aplica incluso si se escriben pruebas suficientemente buenas y si los desarrolladores son lo bastante experimentados? Puede que el problema esté en la lógica o en el proceso de desarrollo, pero me cuesta entender que el lenguaje en sí sea una vulnerabilidad de seguridad. De hecho, casi no hay programas que no dependan de infraestructura escrita en C.