Affichage des articles dont le libellé est cpp. Afficher tous les articles
Affichage des articles dont le libellé est cpp. Afficher tous les articles

mardi 19 mai 2026

Un setup de vibe coding en local qui fonctionne avec 16GB de VRAM (si on est patient)

J'étais arrivé à la conclusion qu'il n'est pas possible de vibe coder avec seulement 16GB de VRAM, et que je devais donc considérer mon AMD 7800XT comme suffisante pour du conversationel, mais pas pour de l'agentique.

Le problème principal est un problème de taille. Les gros modèles ne tiennent pas en mémoire, et les petits fonctionnent mal : soit ils partent en mode poisson rouge et racontent d'importe quoi, soit ils perdent la compréhension du protocole pour communiquer avec la GUI agentique.

Sauf qu'à force d'insister, j'ai compris plusieurs choses : d'une part, ollama, lorsqu'il détecte que la VRAM est basse, configure par défaut un tout petit contexte. D'autre part, ollama est capable de décharger une partie de la VRAM en RAM, ce qui est lent, mais doit continuer de fonctionner. Et c'est seulement lorsque l'on tente de changer de modèle qu'il s'emmelle les pinceaux et peut planter en ne trouvant plus de mémoire pour y charger le modèle.

Un setup qui marche chez moi, c'est donc devstral-small-2 avec 32K de contexte, en utilisant Mistral Vibe du côté client. Alors, c'est très lent - Compter plusieurs minutes entre chaque action de la boucle agentique, et plusieurs dizaines de minutes pour arriver au bout d'une requête ou feature, surtout si on lui demande de compiler (il se trompe beaucoup). Mais ça marche !

J'ai plein d'idées, principalement orientées vers l'idée de le laisser tourner en tâche de fond pendant que je fais autre chose (comme écrire des billets de blog).

mercredi 15 avril 2026

Nouveau mini-jeu

Parce que c'est l'occasion d'intégrer les dessins de la petite, je me suis lancé dans un nouveau mini-jeu. Et j'ai bataillé beaucoup trop longtemps avec Godot avant de finalement repasser à mon bon vieux sfml. Pour un jeu complexe, avec beaucoup d'animations ou même en 3D, il n'y a pas photo. Mais pour un bête truc qui affiche 3 images, revenir aux fondamentaux, c'est plutôt plaisant.

mardi 30 septembre 2025

Divisions entières rapides

Je me suis attaqué à un morceau plutôt amusant : en effet, j'ai eu besoin d'écrire ma propre queue circulaire à accès concurrent, avec un producteur et un consommateur - Typiquement le genre de problème que l'on désire résoudre avec un algo "lock-free". Ce n'est pas très compliqué : un atomic pour l'écriture, un atomic pour la lecture, et basta. Là où ça devient intéressant, c'est dans les différentes optimisations sur lesquelles on peut travailler.

Tout d'abord, bien penser à séparer ses atomiques, afin d'éviter le "false sharing", c'est à dire le transfer entre les caches CPUs de données qui sont indépendantes, mais proches. On utilise pour cela alignas(std::hardware_destructive_interference_size) devant nos attributs afin de bien les séparer.

Ensuite, on se rend compte que l'on a besoin à chaque lecture ou à chaque écriture de vérifier si l'on a atteint la fin du tampon circulaire pour repartir à zéro. Cela peut se faire soit avec un test, soit avec un modulo. Les deux sont plutôt chers... Heureusement, si l'on est pas trop regardant sur la taille exacte de son tampon, on peut l'arrondir à la puissance de 2 suivante, ce qui simplifie énormément les calculs : en effet, le modulo n'est alors qu'un masque...

Voici la partie intéressante du code, qui utilise std::bit_ceil pour trouver la prochaine puissance de 2, calcule le masque, et effectue l'incrément et la division modulaire

class Buffer
{
public:
    Buffer(size_t length):
        _size(std::bit_ceil(length)),
        _mask(_size - 1),
        _reader(0),
        _writer(0)
    {
    }

    void nextRead()
    {
        _reader = (_reader + 1) | _mask;
    }

    const size_t _size;
    const size_t _mask;
    alignas(std::hardware_destructive_interference_size)
    std::atomic _reader;
    alignas(std::hardware_destructive_interference_size)
    std::atomic _writer;
};

Mais la plus grande optimisation que l'on peut faire est de correctement effectuer l'ordonnancement de la mémoire, en sélectionnant memory_order_relaxed, memory_order_acquire ou memory_order_release lors des appels à store et load. La différence est très impressionnante - Un facteur 10 ou 20 dans certains benchmarks ! Je vous passe la logique exacte (en très gros, on load en memory_order_acquire, on store en memory_order_release, et pour des cas indépendants comme chercher la taille du tampon, on peut utiliser memory_order_relaxed), mais en permettant la réécriture des opérations de manière plus flexible que l'accès strict par défaut, le compilo est capable d'effectuer de très bonnes micro-optimisations, et cela se voit !

vendredi 21 mars 2025

Keith, l'anti-mascotte du C++

Tout a commencé comme une grosse blague sur l'Uncyclopedia, qui explique que la mascotte du C++ est un rat obèse et malade, qui s'est tiré une balle das le pied, et qui a été dessiné par Richard Stallman. Et ce qui est encore plus drôle, c'est qu'on a commencé à y croire, au point que certains se sentent obligés de poster des mises au point, voire de demander carrément à Stallman de confirmer si oui ou non il a dessiné la fameuse mascotte (la réponse est non - Stallman a apparemment une mauvaise opinion du C++, mais ne le déteste pas).

Ceci étant dit, officielle ou pas, il me faut cette mascotte. Et ça tombe bien puisqu'elle est disponible en ligne, fabriquée à la demande par 2 Ukrainiennes qui font des peluches sur mesure. J'imagine que quelqu'un leur a envoyé l'illustration pour le faire faire, et depuis il fait partie de leur catalogue.

Quelques semaines plus tard, j'ai reçu Keith, en pleine forme après avoir traversé l'Europe. C'est du très beau travail, il est vraiment magnifique et très bien réalisé, jusqu'à son moignon de patte. Il trône maintenant fièrement au boulot, prêt à aider les développeurs.

dimanche 1 septembre 2024

Oeuf de canard - Retour à SDL

La bonne vieille bibliothèque SDL m'avait manqué. Tellement que j'avais raté que se préparait une version 3 ! Pas encore stable, j'ai préféré l'éviter pour le moment et me baser sur quelque chose de propre. Voici donc pour me remettre dans le bain un nouvel oeuf de canard pour réagir aux événements déclenchés par nos manettes. Signe des temps, je fournis maintenant une image Docker qui dérive d'une Debian Trixie et installe les dépendances nécéssaires. Normalement, il suffit de faire:

./refresh.sh # Créé l'image Docker et la démarre
./exec.sh # Execute un shell dans l'image Docker
cd /src 
./bootstrap.sh # Mise en place des Makefiles
make # Compilation
/buildb/bin/control # Test!

Petite surprise, je n'ai pas réussi à faire fonctionner le branchement à chaud des manettes : autant SDL détecte bien lorsque l'on débranche, l'inverse ne semble pas vrai. Je n'ai pas très envie de plonger dans le code de la SDL pour chercher si je l'utlise mal ou si c'est une limitation de l'implémentation Linux, donc tant pis, on fera sans.

lundi 15 juillet 2024

Conférence C++ On sea

J'ai passé un vendredi à la conférence C++ On Sea, c'était très sympa, même si la météo ce jour là était particulièrement excécrable et que je me suis fait bien saucer à l'aller (et un peu au retour).

Je parle un petit peu de la technique sur Linuxfr, mais j'ai vraiment apprécié l'ambiance, le côté geek et bon enfant, le bingo du C++ où chacun avait un petit papier avec les termes à cocher quand on les entendait lors d'une présentation. Le déjeuner était plutôt pas mal, et au retour on s'est fait des amis et on s'est retrouvé avec un bon groupe avec qui causer dans le train. À refaire, même si je sens une certaine réticence du côté de mon employeur à nous laisser trop profiter de ce genre d'événement sur le temps de travail.

mercredi 12 juin 2024

GTest est sympa

Je n'ai pas l'habitude d'encenser Google, mais quand ils font des trucs bien, il faut aussi savoir le dire. Je suis très impressionné par la bibliothèque GTest, qui est un cadriciel pour écrire des tests unitaires. C'est très bien pensé, et plein de bonnes idées : d'excellents comparateurs, une intégration démentielle avec CMake, mais surtout, la cerise sur le gâteau: un affichage console particulièrement pratique. Regardez donc ce programme:

#include <gtest/gtest.h>

TEST(Test, message)
{
  std::string s1("abc");
  std::string s2("def\nghi\njkl");

  ASSERT_EQ(s1, s2);
}

Quand on le fait tourner, on obtient:

gtest.cpp:9: Failure
Expected equality of these values:
  s1
    Which is: "abc"
  s2
    Which is: "def\nghi\njkl"
With diff:
@@ -1,1 +1,3 @@
-abc
+def
+ghi
+jkl

Regardez moi ça ! Il m'indique le nom des deux variables, leurs valeurs, et un diff ligne par ligne. Mais surtout, il m'affiche la valeur des variables non pas comme l'afficherait std::cout ou std::format, mais comme on devrait l'avoir dans le code source ! Et ça, c'est vraiment magique. Quand on a un résultat bien complexe, avec des caractères échappés, des retours chariots et tout et tout, juste pouvoir copier la sortie du test unitaire pour la coller telle quelle dans le source du test, quel confort ! La petite idée simple, mais il fallait y penser.

samedi 9 mars 2024

C++ : Chercher un fichier dans un répertoire - Partie 2

Et on continue à creuser ! Malheureusement, même avec une recherche récursive écrite en libc, cela prend encore trop de temps sur le système cible. En effet, il s'agit d'un système de fichiers un peu particulier, qui est censé monter en charge très fort mais dont les accès aux métadonnées sont individuellement plutôt lents. Et je ne peux pas échapper au besoin de devoir indexer un système de répertoires contenant environ 100 000 fichiers.

Le système de fichiers veut un accès concurrent ? On va lui en donner un. Malheureusement, ce n'est pas si simple ! En effet, il faut créer un algorithme à la fois récursif et parallèle, ce qui est un nid à problèmes. Pour l'instant, j'entrevois une solution qui consisterait à construire une liste des répertoires non visités, les visiter de manière parallèle pour aller chercher à chaque fois le prochain niveau, et continuer tant qu'on trouve. Le fait de gérer les tâches à partir du thread principal simpilife beaucoup de choses, mais empêche un très bon parallelisme.

Quelle tuile.

mercredi 21 février 2024

C++ : Chercher un fichier dans un répertoire

Petite séance d'optimisation aujourd'hui, où nous tentions d'améliorer une routine qui cherche des fichiers dans un répertoire.

En bon dev C++, nous sommes allés chercher ce bon vieux std::filesystem::path et ce non moins bon vieux std::filesystem::recursive_directory_iterator. Sauf que ça prend des plombes. Mais vraiment. Sur un système de fichiers distant (NFS) et un répertoire de 5000 fichiers pas accédé depuis quelques temps, cela peut monter à des dizaines de secondes. Mais que se passe-t-il ?

Avant de se lancer dans de complexes manipulations avec vtune ou encore gprof, pstack nous indique que l'on passe beaucoup de temps dans l'appel à stat. En effet, std::filesystem::recursive_directory_iterator nous donne un std::filesystem::directory_entry qui contient tout un tas d'infos tout à fait intéressantes, mais qui sont chères à récupérer...

Alors que peut-on faire ?

Eh bien, revenir aux bases, et à cette bonne vieille libc, qui contient l'appel readdir, lequel justement ne récupère pas d'informations sur le fichier autre que son type (ce qui est pratique pour explorer récursivement un répertoire). Et n'oublions pas non plus glob, lequel est justement conçu pour aller chercher un fichier efficacement à partir d'un motif.

Testons, alors. Et sur notre répertoire de 5000 fichiers, cela donne maintenant:

filesystem 40s
readdir 30ms
glob 3ms

Glob est donc plus de 10000 fois plus rapide qu'une recherche manuelle !

Conclusion : méfiance, donc ! Malgré ses qualités, std::filesystem::path peut coûter très cher, et revenir à des appels plus bas niveau est parfois salutaire.

samedi 16 septembre 2023

Accolades et std::optional

La nouvelle manière unifiée d'initialiser les valeurs en C++, c'est super. Bim, on met deux accolades, et on a gagné. Vraiment ?

Sur le papier, c'est bath, on peut pas se tromper:

int a = {};
std::string b = {};
std::optional<int> c = {};
MonObjectQuIlEstBeau d = {};

Sauf qu'il a danger ! C'est que lorsque l'on fait un changement de type quelque part, mettons un paramètre de fonction, et que l'on s'attend à ce que le compilo nous indique gentiment tous les endroits à changer, eh bien il est possible en fait que le compilo accepte le changement sans broncher, mais en changeant la sémantique. Et boum ! C'est ce qui m'est arrivé la semaine dernière, heureusement rapidement détecté. Voyez plutôt cet innocent programme, l'on a une fonction f qui prend un optionel, et on l'appelle en initialisant notre optionel sur vide.

#include <optional>

void f(std::optional<int> a);

int main()
{
    f({});
    return 0;
}

Un peu plus tard, l'on change la signature de f:

void f(int a);

Et boum, l'on initialise maintenant a avec la valeur 0, ce qui pourrait bien être complètement faux.

Que faire alors ? Eh bien, utilisons std::nullopt ! Ainsi, notre appel f(std::nullopt) fonctionnera correctement dans le premier cas, et causera une erreur de compilation dans le deuxième.

Conclusion : mangez du {}, mais avec les optionels, préférez std::nullopt !

dimanche 6 août 2023

Noexcept - Ce n'est pas gratuit !

Je parle régulièrement de culte du cargo dans le domaine informatique, où l'on a souvent ses petites marottes que l'on applique sans comprendre. Et j'ai un chef dont la marotte c'est d'exiger l'ajout du mot-clé "noexcept" un peu partout, avec l'espoir d'augmenter les performances.

Et c'est le cas, parfois. Par exemple, une réallocation d'un std::vector après un dépassement de capacité lors de l'ajout d'un élément sera bien plus efficace si le type de l'élément a un move constructor designé comme noexcept, car dans ce cas, l'algorithme de réallocation du vecteur peut utiliser le move. Il faut donc bien se rendre compte qu'au sein du code de std::vector, il y a une condition qui vérifie à la compilation si le type a son move constructor designé ainsi, et décide d'utiliser l'algo efficace ou non. Ce n'est donc pas une optimisation du compilateur, mais bien un choix de code au sein de la bibliothèque standard, et c'est complètement indépendant du niveau d'optimisation, de l'inlining...

Et surtout, noexcept n'est pas gratuit ! Si le compilo ne peut déterminer si effectivement la fonction marquée noexcept ne lance pas d'exception (disons, elle appelle simplement une autre fonction pas inlinée qui n'est pas déclarée noexcept), il lui faut rajouter du code pour pouvoir attraper cette exception et terminer le programme à la place. Voyons ce que dit notre ami Godbolt sur ce tout petit programme:

void f();

void g()
{
    f();
}

L'assembleur généré est celui-là, c'est à dire un bête jump et puis c'est tout !

g():
        jmp     f()

En revanche, si l'on dit maintenant que g() est noexcept:

void f();

void g() noexcept
{
    f();
}

Alors l'assembleur généré nous montre bien que l'on fait un peu plus de travail, en poussant la frame sur la pile, afin que si une exception était lancée dans f(), il soit possible de l'arrêter dans g().

g():
        subq    $8, %rsp
        call    f()
        addq    $8, %rsp
        ret

Conclusion que ne renieraient pas Plic et Ploc : réfléchir avant d'agir !

lundi 10 juillet 2023

Architecture CPU et optimisation du compilo

Et on continue de jouer avec Godbolt, en particulier la capacité de gcc d'optimiser du code numérique. Prenons par exemple une version simplifiée de la résolution d'une équation quadratique :

#include <cmath>

double calc(double a, double b, double c)
{
    double delta = b * b - 4 * a * c;
    return (-b + sqrt(delta)) / (2 * a);
}

Je vous laisserai aller voir sur Godbolt, mais en gros, ça nous fait une 30aine d'instructions assembleur.

La première grosse optimisation, c'est la combinaison de -O3 et de -ffast-math. On passe à 18 lignes (dont 12 seulement font quelque chose d'intéressant), et le compilo utilise l'instruction assembleur sqrtsd plutôt que d'appeler le sqrt de la libc. Mais l'on peut faire encore mieux ! Avec un -march=skylake, on perd 2 instructions, et la machine passe alors sur des instructions vectorisées. Plus rapide ? Moins rapide ? Je suppose que ça va dépendre ! On retrouve un code équivalent en passant chez AMD et -march=znver3.

Maintenant, le souci, c'est que je si, comme dans mon cas, je dois compiler du code qui tournera à la fois sur des machines récentes de chez Intel et AMD, eh bien je suis obligé de garder une architecture générique et de perdre l'avantage de toutes ces instructions magiques... Quand bien même elles sont peut-être en commun ?

Frustrant, donc. Mais probablement pas catastrophique, car le code que j'optimise n'est de toutes façons pas très numérique, et se vectorise probablement mal. Tant pis !

dimanche 14 mai 2023

Question C++ toute bête

Qu'est ce qui est le plus rapide ?

bool a = ...
if (a)
{
  a = false;
}

ou

bool a = ...
a = false;

En gros: est-ce que la lecture est significativement moins chère que l'écriture, et que cela vaut donc le coup de vérifier avant d'écrire la valeur ? Pour l'instant, je l'ignore. M'en vais faire tourner quelques benchmarks pour tenter d'élucider cette question...

lundi 1 mai 2023

Godbolt

Je vous ai déjà dit à quel point ce site était une tuerie ? L'idée de base est géniale : fournir une interface web permettant de tester un programme sur une grande variété de compilateurs, d'en voir l'assembleur généré, et le résultat. Avec une grande quantité de languages (C++, D, Java, Objective-C, Ocaml...) et une grande quantité de compilos (Pour le c++, nous avons pratiquement chaque version de gcc, de llvm, et du compilo de Microsoft, plus tout un tas de variations).

C'est vraiment très, très sympa pour bidouiller, tester une fonctionnalité à venir, vérifier un bug, faire de la micro-optimisation, ou juste partager une idée de code avec quelqu'un d'autre, parce qu'en plus chaque programme est enregistré via un lien unique. Très, très pratique.

jeudi 23 février 2023

C++20 - std::source_location

J'ai eu l'occasion d'expérimenter avec la structure std::source_location, qui est très bien fichue puisqu'elle s'initialise avec les informations courantes de fonction, de fichier source, et de ligne et de colonne dans le source.

Là où c'est très sympa, c'est qu'il est possible en utilisant un paramètre par défaut d'obtenir dans une fonction les informations de l'appelant ! C'est particulièrement pratique, par exemple, pour implémenter une fonction de log qui ne soit pas une immonde macro.

#include <source_location>
#include <iostream>
#include <string>

void log(std::source_location location = 
         std::source_location::current())
{
    std::cout << location.function_name() << std::endl;
}

void f()
{
    log();
}

template<typename T>
void g()
{
    log();
}

int main()
{
    f();
    g<std::string>();
    g<int>();
    return 0;
}

Et voilà le résultat :

void f()
void g() [with T = std::__cxx11::basic_string<char>]
void g() [with T = int]

Là où ça devient intéressant, c'est quand on veut le combiner avec une fonction de log variadique, de type std::format. Puisque l'on ne peut pas mettre le paramètre par défaut à la fin, car c'est ambigu, il faut ruser, et transformer le premier paramètre, typiquement la chaîne de formattage, en un objet spécial qui prend en premier paramètre la chaîne de formattage et en deuxième le paramètre std::source_location par défaut. Puis combiner tout cela avec du consteval et l'empaqueter dans un std::identity_type_t afin qu'il ne participe pas à la résolution des types variadiques, sinon ça ne marche pas !

Je posterai à l'occasion un exemple un peu plus complet. D'ici là, compilez bien.

mercredi 14 décembre 2022

Méthodes monadiques sur std::optional

Voilà que C++ se prend pour Haskell ! Maintenant, nous avons une belle interface monadique pour std::optional, les méthodes and_then, transform, or_else, qui permettent de chainer des appels sur un optionel. Je me suis demandé si le compilo pouvait optimiser entre les appels, et j'ai donc demandé au fidèle godbolt ce quí il en pensait. Le résultat est impressionnant. Voici deux fonctions qui font la même chose, l'une utilisant l'approche monadique (g++ 12.2, options -O3 -std=c++23):

#include <optional>

int f(const std::optional<int>& opt)
{
    return opt
    .transform([](auto&& val) { return val + 3;})
    .transform([](auto&& val) { return val - 11;})
    .value_or(7);
}

int g(const std::optional<int>& opt)
{
    if (opt)
    {
        return *opt + 3 - 11;
    }
    else
    {
        return 7;
    }
}

G++, sans broncher, nous sort, dans les deux cas, le même code optimisé aux petits oignons:

        cmpb    $0, 4(%rdi)
        movl    $7, %eax
        je      .L1
        movl    (%rdi), %eax
        subl    $8, %eax
.L1:
        ret

À noter que clang, encore mieux, nous débarasse carrément du saut conditionnel !

        movl    (%rdi), %ecx
        addl    $-8, %ecx
        cmpb    $0, 4(%rdi)
        movl    $7, %eax
        cmovnel %ecx, %eax
        retq

Ils sont forts, ces concepteurs de compilos. La conclusion, c'est donc que oui, le compilo peut optimiser à travers les appels monadiques. Mangez-en donc !

mercredi 7 décembre 2022

VulkanSceneGraph version 1.0

Je ne me souvenais pourtant pas de m'être abonné aux sorties de VulkanSceneGraph, mais j'avais la hype quand j'ai reçu un e-mail annonçant la version 1.0 de la nouvelle mouture du graphe de scène, mais basé sur Vulkan.

J'étais tellement enthousiaste que j'ai pondu une petite trilogie d'articles sur linuxfr.org : tout d'abord, une petite retrospective des techniques de rendu, moment nostalgie avec tous ces vieux jeux, puis un petit aperçu sur les graphes de scène, et enfin la présentation de VulkanSceneGraph.

Avec un support gltf aux petits oignons, je n'ai plus qu'à espérer un rapide développement des fonctionnalités d'animation, et je n'aurai plus d'excuses pour ne pas faire un truc avec tout ça.

samedi 6 août 2022

Grogne estivale

Je poste un petit coup de gueule sur LinuxFR. Il me tenait à coeur de batailler contre un certain manque de profondeur que l'on retrouve parfois, où pointer l'approche de grandes firmes des technologies de l'information semble suffisant pour justifier un choix technique ou méthodologique. J'en ai encore dans mon sac, en particulier sur les "12 factors app" (je ne mets pas de lien, ils ne le méritent pas), et sur la plaie que sont les gestionnaires de paquets particuliers à un language (Conda, je te regarde), par opposition aux paquets des distributions qui, je trouve, sont pour le coup une manière que je trouve particulièrement élégante et efficace de gérer ses dépendances.

Bref, profitez bien de votre été, mettez de la crème solaire, bisous !

dimanche 23 janvier 2022

C++20 - std::jthread

Coucou ! Cela faisait un petit moment que nous n'avions pas parlé de C++. Ça tombe bien, il y a plein de choses à dire. En particulier, causons aujourd'hui de std::jthread.

Ce n'est certes pas une révolution : il s'agit juste d'une version un petit peu plus évoluée que std::thread, qui embarque un indicateur qui permet de demander l'arrêt du thread, et qui a la propriété de demander cet arrêt, et de joindre le thread, dans le destructeur. Rien qui ne soit aisé à écrire soi-même, mais c'est du sucre syntaxique tout ce qu'il y a de plus agréable, et je trouve que cela s'approche plus de la philosophie RAII : là où l'ancien std::thread était vraiment un contrôle sur un thread, mais pouvait être détruit bien avant le thread, le nouveau std::jthread a plus une sémantique de possession, en s'assurant que le thread ne survivra pas à l'objet.

Subtilité supplémentaire: le foncteur passé à std::jthread peut prendre un paramètre supplémentaire de type std::stop_token qui permet de savoir si son propre thread doit s'arrêter.

Mais assez de parlotte, voyons le code:

#include <thread>
#include <iostream>

int main()
{
  std::jthread t
    ([](std::stop_token stoken)
     {
       while (!stoken.stop_requested())
       {
         std::cout << "Coucou !" << std::endl;
       }
     });

  using namespace std::literals::chrono_literals;
  std::this_thread::sleep_for(2s);

  return 0;
}

Grace à notre ami le std::jthread, pas besoin d'avoir un atomic qui traine, de bien penser à joindre à la fin du programme, et tout le toutim habituel. Le std::jthread nous prend par la main et s'assure que tout est bien nettoyé derrière. Sympa !

mercredi 21 avril 2021

Short string optimisation - Comment l'observer ?

Alors, on l'a, ou on l'a pas ? Si vous avez un compilo récent sur un système d'exploitation raisonable, la SSO, vous l'avez. Si vous avez un compilo pas si récent sur un système d'exploitation trop raisonable (Red Hat, je te regarde, la compatibilité, c'est bien, mais je veux mon SSO !), alors vous ne l'avez pas. Mais comment être sûr ? Eh bien, logiquement, si vous avez la SSO, cela veut dire que la capacité de votre chaîne est strictement supérieure à zéro, même si elle vient d'être créée vide. Alors, essayons !

#include <string>
#include <iostream>


int main()
{
  std::cout << std::string().capacity() << std::endl;
  return 0;
}

On compile, on exécute, et chez moi ça donne 15. Yeah !