STL footprint

J’occupe mes soirées à faire joujou avec msvc++ 6.0, et ce qui m’amuse pour l’instant, c’est l’optimisation de la taille de l’exécutable résultant. Mais là où on peut trouver sur internet des tonnes d’explications sur comment faire le plus petit possible, en balançant par la fenêtre tout sauf le strict minimum, je recherche plutôt le meilleur compromis entre taille et fonctionnalités.

C’est pourquoi j’observe soigneusement l’évolution de la taille de mon exécutable en fonction des appels à la STL que j’y introduis. Et oui, on peut faire des executables de 20 ko avec des string, des lists et plein de templates (après un coup d’upx tout de même). Par contre, une simple ligne peut tout faire basculer, surtout au niveau des streams, y’a la patate de dépendances là-dedans.

Après cette longue introduction, voici mon idée et mes questions :

J’envisage de formaliser un peu mes expérimentations, et de consigner les résultats de mes observations sous la forme : parties de la STL utilisées vs. taille de l’executable.

Mes questions :

  1. Pensez-vous que ça puisse intéresser quelqu’un d’autre que moi ?
  2. Pensez-vous que ça aie déjà été fait ? (c’est bête de le refaire si ça a été bien fait)

Je ne sais pas si ca a ete deja fait, mais moi je trouverais ca interessant

Ca va intéresser 2 ou 3 geeks oui, dont moi

Et ça a déjà été fait, mais je pense que ça n’a jamais été formalisé (autrement dit : c’est du bouche à oreilles et autres). Je continue à faire mon raytracer pour cette satanée intro 64ko qui sortira un jour (d’ailleurs j’ai repompé un exemple de buggy avec ODE et j’ai mis le rendu en raytrace, c’est super fun on fera p’tet une release d’ici peu), et j’ai fais ces tests de taille / fonctionnalité.

Les streams pompent des ressources à mort : ça c’est pas nouveau, parce qu’il ne s’agit pas juste de templates, y’a du code derrière dépendant de l’OS. Donc à proscrire si tu recherches la taille.

Ensuite les templates… très bien les templates style string, vector & co, seulement il ne faut pas oublier que chaque nouveau type rajoute son implémentation du code du template utilisé, donc ça peut monter vite.

Au final, on a arreté d’utiliser les std::vector par exemple. On a remplacé ça par notre propre template (T3DArray qu’on l’a appelée). Pourquoi ? eh bien tout simplement parce que ça nous faisait gagner plusieurs kilos de code. Parce que les STL n’ont jamais été pensées pour gagner de la taille…

Bref, c’est un vaste sujet moult intéressant

[quote]Ensuite les templates… très bien les templates style string, vector & co, seulement il ne faut pas oublier que chaque nouveau type rajoute son implémentation du code du template utilisé, donc ça peut monter vite.

Au final, on a arreté d’utiliser les std::vector par exemple. On a remplacé ça par notre propre template (T3DArray qu’on l’a appelée). Pourquoi ? eh bien tout simplement parce que ça nous faisait gagner plusieurs kilos de code. Parce que les STL n’ont jamais été pensées pour gagner de la taille…

Aïe, voilà un point très intéressant... et très problématique aussi. Faudrait que je voie l'impact en fonction du nombre de types différents qui utilisent ces templates... Et pourquoi ne pas faire un genre de wrapper pour chaque type de template (list, vector, deque, etc.) qui utiliserait de façon interne les templates STL, mais toujours de la même manière (par exemple stocker tout sous forme de char[]) ? Ouais, la belle idée de goret que voilà.

Ou alors on peut aussi réécrire une STL spéciale, la plus petite possible, avec uniquement les méthodes indispensables… Arg, on en reparle dans dix ans

On n’est pas encore désespérés au point d’aller jusqu’à avoir un wrapper de truc genre les vectors nous

Par contre, on a réécrit les templates qu’on utilise (principalement vector, le reste ne nous intéresse qu’assez peu dans notre cas particulier). Ecrire un petit template pour faire un “vector-like” est assez simple, par contre si tu as des besoins plus exotiques… ça se complique grandement

Cela dit, pour les instance par type, si tu te debrouilles pour que chaque instance soit dans un fichier object different (un pointobj quoi , et que tu ne te sers que de certaine fonctions : le dead-code stripping devrait te debarasser des appels inutiles !

Vas-y Drealmer, fonce ! Y a longtemps que je voulais faire ce genre de tests, mais j’ai jamais eu le temps .

Personnellement, j’utilise également mes propres templates (Vector, List et Map pour l’essentiel), pas trop pour l’économie de ko, mais plutôt pour être en parfaite adéquation avec mon gestionnaire de mémoire et traquer plus facilement les fuites de mémoire.

[quote]Cela dit, pour les instance par type, si tu te debrouilles pour que chaque instance soit dans un fichier object different (un pointobj quoi , et que tu ne te sers que de certaine fonctions : le dead-code stripping devrait te debarasser des appels inutiles ![/quote]Uh ? C’est pas sensé le faire à l’intérieur même de chaque obj ? Y’a l’équivalent en msvc++ du “strip” de GCC ou bien c’est fait automatiquement ?

Tuo : vous avez récrit les opérateurs new et delete pour les mapper vers les fonctions mémoire de l’api windows ? Ca vaut vraiment la peine ce genre de choses ? Ca marche bien ? La STL supporte ce genre de traitement ?

c0unt0 : meme en faisant ça (tu penses bien qu’on le fait), ça reste plus intéressant de refaire ses propres templates.

Drealmer : oui, on a refait new et delete, et aussi malloc et free et realloc et… On a refait une CRT minimale pour nous, donc à terme on se passera totalement de la CRT de Visual (pour le moment on la garde pour de sombres histoires de fread, au final on n’en aura plus ) La STL supporte parfaitement ce système, ce qui est logique

[quote]Uh ? C’est pas sensé le faire à l’intérieur même de chaque obj ? Y’a l’équivalent en msvc++ du “strip” de GCC ou bien c’est fait automatiquement ?

Le stripping est toujours plus efficace si tu peux te debarasser de tout un obj d'un coup.

[quote]c0unt0 : meme en faisant ça (tu penses bien qu’on le fait), ça reste plus intéressant de refaire ses propres templates.

tout a fait d'accords : c'est ce que j'ai toujours fait/vu faire... ou alors utiliser une implementation propre des STL... mais c'est rare [img]style_emoticons/<#EMO_DIR#>/smile.gif[/img]