1 points par GN⁺ 2024-09-02 | 1 commentaires | Partager sur WhatsApp

Optimisation de la taille du binaire de la bibliothèque {fmt}

  • Présentation de la bibliothèque {fmt}

    • {fmt} est une bibliothèque de formatage réputée pour la petite taille de ses binaires
    • Par rapport à IOStreams, Boost Format, tinyformat, etc., la taille du code par appel de fonction est bien plus faible
    • Elle minimise la surcharge des templates grâce à l'effacement de type (type erasure)
  • Formatage via l'effacement de type

    • La fonction format délègue le travail à la fonction vformat
    • L'itérateur de sortie et les autres types de sortie sont eux aussi effacés via une API de buffer spécialement conçue
    • L'utilisation minimale des templates réduit la taille du binaire et le temps de compilation
  • Exemple de code

    #include <fmt/base.h>
    int main() { fmt::print("The answer is {}.", 42); }
    
    • Le code ci-dessus se compile en un binaire bien plus petit que du code basé sur IOStreams
    • Même comparé à printf, la taille reste similaire tout en offrant la sûreté de type à l'exécution
  • Optimisation de la taille du binaire

    • En 2020, un travail a été mené pour ramener la taille de la bibliothèque sous les 100 kB
    • La taille du binaire de la version récente (11.0.2) est de 75 kB
    • En désactivant la prise en charge des locales, la taille peut être réduite à 71 kB
  • Analyse avec l'outil Bloaty

    • Le formatage des nombres, en particulier des nombres à virgule flottante, occupe une part importante
    • Si la prise en charge des flottants n'est pas nécessaire, elle peut être désactivée
  • Optimisation du formatage par type

    • En définissant la macro FMT_BUILTIN_TYPES à 0, seul le type int est traité de manière spéciale, et les autres types passent par l'API d'extension
    • Cette méthode permet de réduire la taille du binaire à 31 kB
  • Suppression des artefacts liés aux locales

    • En utilisant la macro FMT_USE_LOCALE pour supprimer les artefacts liés aux locales, la taille peut être réduite à 27 kB
  • Compromis entre vitesse et taille

    • En utilisant la macro FMT_OPTIMIZE_SIZE pour optimiser la taille, le binaire peut être ramené à 23 kB
  • Suppression de la dépendance à la bibliothèque standard C++

    • En désactivant les exceptions et en utilisant l'option -nodefaultlibs, la dépendance au runtime C++ est supprimée
    • L'introduction d'un allocateur personnalisé utilisant malloc et free permet de réduire la taille du binaire à 14 kB
  • Vérification du résultat

    • La commande ldd permet de confirmer que la dépendance au runtime C++ a bien été supprimée

Résumé de GN⁺

  • La bibliothèque {fmt} est une bibliothèque de formatage offrant une petite taille de binaire et la sûreté de type à l'exécution
  • L'effacement de type et la configuration de macros permettent de réduire fortement la taille du binaire
  • La suppression de la dépendance à la bibliothèque standard C++ permet une utilisation efficace même sur des systèmes embarqués
  • Parmi les bibliothèques offrant des fonctions similaires, on trouve IOStreams, Boost Format et tinyformat

1 commentaires

 
GN⁺ 2024-09-02
Avis Hacker News
  • {fmt} est fondamentalement indépendant de la locale
  • Le formatage des nombres à virgule flottante nécessite beaucoup de code
    • Le projet Dragonbox vaut la peine d’être lu pour son code optimisé
  • L’allocateur par défaut de C++ n’utilise pas malloc et free
    • On se demande pourquoi l’allocateur par défaut de libc++ n’appelle pas malloc et free de libc
  • Il existe un projet qui permet d’obtenir printf(Hello, World!\n") avec un exécutable de 1008 octets
    • La comparaison directe est difficile, mais cela reste une référence utile
  • Sur un système où un programme C avec une fonction main vide fait 6 kB, {fmt} ajoute moins de 10 kB au binaire
    • C’est un test intéressant
  • On s’attendait à ce qu’une petite bibliothèque de formatage n’ait besoin que d’environ 50 octets pour afficher des chaînes et des entiers
    • Les chaînes tiennent en environ 4 instructions
    • Les entiers tiennent en environ 20 instructions
    • Les nombres à virgule flottante ne sont pas utilisés dans beaucoup de programmes, donc ils ne devraient être compilés qu’en cas de besoin
    • Quand l’espace code d’un microcontrôleur est de 2 kilo-octets, on n’y inclut pas une bibliothèque de formatage de chaînes de 14 kilo-octets
  • Ce type d’optimisation hors des sentiers battus est très agréable
  • Il a fallu un moment pour comprendre que "14k" signifiait "14 kB"
  • fmt pose toujours problème
    • Le même problème se produit aussi en .NET
    • Si l’on manipule beaucoup le formatage/parsing des nombres, l’éditeur de liens finit par inclure beaucoup de code lié aux flottants et aux BigInt, ce qui augmente la taille du binaire