J'ai respecté un programme hello world Go qui a généré un exécutable natif sur ma machine Linux. Mais j'ai été surpris de voir la taille du simple programme Hello world Go, il était de 1,9 Mo!
Pourquoi l'exécutable d'un programme aussi simple dans Go est-il si énorme?
go
executable
Karthic Rao
la source
la source
dotnet publish -r win-x64 -p:publishsinglefile=true -p:publishreadytorun=true -p:publishtrimmed=true
génère un fichier binaire d'environ 26 Mo!Réponses:
Cette question exacte apparaît dans la FAQ officielle: Pourquoi mon programme trivial est-il un si gros binaire?
Citant la réponse:
Ainsi, l'exécutable natif de votre Hello World fait 1,9 Mo car il contient un runtime qui fournit le ramasse-miettes, la réflexion et de nombreuses autres fonctionnalités (que votre programme n'utilise peut-être pas vraiment, mais il est là). Et l'implémentation du
fmt
package que vous avez utilisé pour imprimer le"Hello World"
texte (plus ses dépendances).Maintenant, essayez ce qui suit: ajoutez une autre
fmt.Println("Hello World! Again")
ligne à votre programme et compilez-la à nouveau. Le résultat ne sera pas 2x 1,9 Mo, mais toujours seulement 1,9 Mo! Oui, car toutes les bibliothèques utilisées (fmt
et ses dépendances) et le runtime sont déjà ajoutés à l'exécutable (et donc juste quelques octets supplémentaires seront ajoutés pour imprimer le 2ème texte que vous venez d'ajouter).la source
Considérez le programme suivant:
package main import "fmt" func main() { fmt.Println("Hello World!") }
Si je construis ceci sur ma machine Linux AMD64 (Go 1.9), comme ceci:
$ go build $ ls -la helloworld -rwxr-xr-x 1 janf group 2029206 Sep 11 16:58 helloworld
J'obtiens un binaire d'environ 2 Mo de taille.
La raison à cela (qui a été expliquée dans d'autres réponses) est que nous utilisons le package "fmt" qui est assez volumineux, mais le binaire n'a pas non plus été supprimé et cela signifie que la table des symboles est toujours là. Si nous demandons au compilateur de supprimer le binaire, il deviendra beaucoup plus petit:
$ go build -ldflags "-s -w" $ ls -la helloworld -rwxr-xr-x 1 janf group 1323616 Sep 11 17:01 helloworld
Cependant, si nous réécrivons le programme pour utiliser la fonction intégrée print, au lieu de fmt.Println, comme ceci:
package main func main() { print("Hello World!\n") }
Et puis compilez-le:
$ go build -ldflags "-s -w" $ ls -la helloworld -rwxr-xr-x 1 janf group 714176 Sep 11 17:06 helloworld
Nous nous retrouvons avec un binaire encore plus petit. C'est aussi petit que nous pouvons l'obtenir sans recourir à des astuces comme UPX-packing, donc la surcharge du Go-runtime est d'environ 700 Ko.
la source
Notez que le problème de taille binaire est suivi par le problème 6853 dans le projet golang / go .
Par exemple, commit a26c01a (pour Go 1.4) réduit hello world de 70 ko :
Étant donné que le compilateur, l'assembleur, l'éditeur de liens et le runtime pour 1.5 seront entièrement dans Go, vous pouvez vous attendre à une optimisation supplémentaire.
Mise à jour 2016 Go 1.7: cela a été optimisé: voir " Smaller Go 1.7 binaires ".
Mais ces jours-ci (avril 2019), ce qui prend le plus de place est
runtime.pclntab
.Voir « Pourquoi mes fichiers exécutables Go sont-ils si volumineux? Visualisation de la taille des exécutables Go à l'aide de D3 » de Raphael 'kena' Poss .
la source