Même les programmes Haskell de petite taille se transforment en exécutables gigantesques.
J'ai écrit un petit programme, qui a été compilé (avec GHC) en binaire avec une taille de 7 Mo!
Qu'est-ce qui peut provoquer la compilation d'un petit programme Haskell en un énorme binaire?
Que puis-je faire, le cas échéant, pour réduire cela?
strip
sur le binaire pour supprimer la table de symboles.strip test
. Cette commande supprime certaines informations de débogage du programme et le réduit.data M3 = M3 !V3 !V3 !V3
etdata V3 = V3 !Float !Float !Float
. Compilez avecghc -O2 -funbox-strict-fields
.Réponses:
Voyons ce qui se passe, essayez
Vous voyez dans la
ldd
sortie que GHC a produit un exécutable lié dynamiquement, mais seules les bibliothèques C sont liées dynamiquement ! Toutes les bibliothèques Haskell sont copiées in extenso.A part: puisqu'il s'agit d'une application gourmande en graphiques, je compilerais certainement avec
ghc -O2
Vous pouvez faire deux choses.
Symboles de dépouillement
Une solution simple: dépouiller le binaire:
Supprimer supprime les symboles du fichier objet. Ils ne sont généralement nécessaires que pour le débogage.
Bibliothèques Haskell liées dynamiquement
Plus récemment, GHC a pris en charge la liaison dynamique des bibliothèques C et Haskell . La plupart des distributions distribuent désormais une version de GHC conçue pour prendre en charge la liaison dynamique des bibliothèques Haskell. Les bibliothèques Haskell partagées peuvent être partagées entre de nombreux programmes Haskell, sans les copier dans l'exécutable à chaque fois.
Au moment de l'écriture, Linux et Windows sont pris en charge.
Pour permettre aux bibliothèques Haskell d'être liées dynamiquement, vous devez les compiler avec
-dynamic
, comme ceci:De plus, toutes les bibliothèques que vous souhaitez partager doivent être créées avec
--enabled-shared
:Et vous vous retrouverez avec un exécutable beaucoup plus petit, qui a à la fois les dépendances C et Haskell résolues dynamiquement.
Et voilà!
que vous pouvez décaper pour rendre encore plus petit:
Un exécutable très simple, construit à partir de nombreux éléments C et Haskell liés dynamiquement:
Un dernier point: même sur les systèmes avec des liaisons statiques uniquement, vous pouvez utiliser -split-objs , pour obtenir un fichier .o par fonction de niveau supérieur, ce qui peut encore réduire la taille des bibliothèques liées statiquement. Il faut que GHC soit construit avec -split-objs, ce que certains systèmes oublient de faire.
la source
cabal install
supprime pas le binaire installé par défaut?enable-shared
été envisagé. launchpad.net/ubuntu/+source/pandoc/+bugsHaskell utilise la liaison statique par défaut. C'est-à-dire que toutes les liaisons à OpenGL sont copiées dans votre programme. Comme ils sont assez gros, votre programme est inutilement gonflé. Vous pouvez contourner ce problème en utilisant la liaison dynamique, bien qu'elle ne soit pas activée par défaut.
la source
--enabled-shared
" donc si votre plateforme Haskell est livrée avec des bibliothèques construites sans que--enabled shared
vous ayez à recompiler les bibliothèques de base, ce qui peut être assez pénible.