1 puntos por GN⁺ 2024-09-02 | 1 comentarios | Compartir por WhatsApp

Optimización del tamaño binario de la biblioteca {fmt}

  • Introducción a la biblioteca {fmt}

    • {fmt} es una biblioteca de formateo conocida por su pequeño tamaño binario
    • En comparación con IOStreams, Boost Format, tinyformat y otras, el tamaño de código por llamada de función es mucho menor
    • Minimiza la sobrecarga de plantillas mediante borrado de tipos (type erasure)
  • Formateo mediante borrado de tipos

    • La función format delega el trabajo a la función vformat
    • El iterador de salida y otros tipos de salida también se borran en cuanto a tipo mediante una API de búfer diseñada especialmente
    • Al minimizar el uso de plantillas, se reducen el tamaño binario y el tiempo de compilación
  • Código de ejemplo

    #include <fmt/base.h>
    int main() { fmt::print("The answer is {}.", 42); }
    
    • El código anterior se compila con un tamaño mucho menor que el código con IOStreams
    • Incluso en comparación con printf, el tamaño es similar y ofrece seguridad de tipos en tiempo de ejecución
  • Optimización del tamaño binario

    • En 2020 se realizó un trabajo para reducir el tamaño de la biblioteca a menos de 100 kB
    • El tamaño binario de la versión más reciente (11.0.2) es de 75 kB
    • Si se desactiva el soporte de locale, el tamaño puede reducirse a 71 kB
  • Análisis con la herramienta Bloaty

    • El formateo de números, especialmente el de números de punto flotante, ocupa una gran parte
    • Si no se necesita soporte para punto flotante, puede desactivarse
  • Optimización del formateo por tipo

    • Configurando la macro FMT_BUILTIN_TYPES en 0, solo el tipo int se maneja de forma especial y el resto de los tipos se procesan mediante la API de extensión
    • Con este método, el tamaño binario puede reducirse a 31 kB
  • Eliminación de artefactos de locale

    • Usando la macro FMT_USE_LOCALE para eliminar artefactos de locale, el tamaño puede reducirse a 27 kB
  • Compensación entre velocidad y tamaño

    • Al optimizar el tamaño con la macro FMT_OPTIMIZE_SIZE, el binario puede reducirse a 23 kB
  • Eliminación de la dependencia de la biblioteca estándar de C++

    • Se desactivan las excepciones y se usa la opción -nodefaultlibs para eliminar la dependencia del runtime de C++
    • Introduciendo un asignador personalizado que usa malloc y free, el tamaño binario puede reducirse a 14 kB
  • Verificación del resultado

    • Se confirma con el comando ldd que se eliminó la dependencia del runtime de C++

Resumen de GN⁺

  • La biblioteca {fmt} es una biblioteca de formateo que ofrece un tamaño binario pequeño y seguridad de tipos en tiempo de ejecución
  • Mediante borrado de tipos y configuración de macros, es posible reducir significativamente el tamaño binario
  • Al eliminar la dependencia de la biblioteca estándar de C++, puede usarse de forma eficiente incluso en sistemas embebidos
  • Algunas bibliotecas con funciones similares son IOStreams, Boost Format y tinyformat

1 comentarios

 
GN⁺ 2024-09-02
Opiniones en Hacker News
  • {fmt} es independiente de la configuración regional por defecto
  • El formateo de punto flotante requiere mucho código
    • Vale la pena revisar el proyecto Dragonbox por su código optimizado
  • El asignador predeterminado de C++ no usa malloc ni free
    • Se preguntan por qué el asignador predeterminado de libc++ no llama a malloc y free de libc
  • Hay un proyecto que hace posible printf(Hello, World!\n") con un ejecutable de 1008 bytes
    • Es difícil compararlo directamente, pero sirve como referencia
  • En un sistema donde un programa en C con una función main vacía ocupa 6 kB, {fmt} agrega menos de 10 kB al binario
    • Es una prueba interesante
  • Se esperaba que una biblioteca pequeña de formateo necesitara unos 50 bytes para imprimir cadenas y enteros
    • Las cadenas consisten en unas 4 instrucciones
    • Los enteros consisten en unas 20 instrucciones
    • Como el punto flotante no se usa en muchos programas, debería compilarse solo cuando haga falta
    • Si el espacio de código de un microcontrolador es de 2 kilobytes, no incluirías una biblioteca de formateo de cadenas de 14 kilobytes
  • Este tipo de optimizaciones fuera de lo habitual son muy disfrutables
  • Tomó un tiempo darse cuenta de que "14k" significaba "14 kB"
  • fmt siempre causa problemas
    • En .NET pasa lo mismo
    • Si trabajas mucho con formateo/análisis de números, el linker termina incluyendo mucho código relacionado con punto flotante y BigInt, y el tamaño del binario crece