Postępowałem zgodnie z programem hello world Go, który generował natywny plik wykonywalny na moim komputerze z systemem Linux. Ale byłem zaskoczony, widząc rozmiar prostego programu Hello world Go, to było 1,9 MB!
Dlaczego plik wykonywalny tak prostego programu w Go jest tak ogromny?
go
executable
Karthic Rao
źródło
źródło
dotnet publish -r win-x64 -p:publishsinglefile=true -p:publishreadytorun=true -p:publishtrimmed=true
generacją pliku binarnego o ~ 26MB!Odpowiedzi:
Dokładne pytanie pojawia się w oficjalnym FAQ: Dlaczego mój trywialny program ma tak duży plik binarny?
Cytując odpowiedź:
Tak więc natywny plik wykonywalny twojego Hello World ma 1,9 MB, ponieważ zawiera środowisko uruchomieniowe, które zapewnia zbieranie śmieci, odbicie i wiele innych funkcji (których twój program może tak naprawdę nie używać, ale jest). I implementacja
fmt
pakietu, którego użyłeś do wydrukowania"Hello World"
tekstu (plus jego zależności).Teraz spróbuj wykonać następujące czynności: dodaj kolejną
fmt.Println("Hello World! Again")
linię do swojego programu i skompiluj go ponownie. Rezultatem nie będzie 2x 1,9 MB, ale tylko 1,9 MB! Tak, ponieważ wszystkie używane biblioteki (fmt
i ich zależności) i środowisko uruchomieniowe są już dodane do pliku wykonywalnego (a więc zostanie dodanych jeszcze tylko kilka bajtów, aby wydrukować drugi tekst, który właśnie dodałeś).źródło
Rozważ następujący program:
package main import "fmt" func main() { fmt.Println("Hello World!") }
Jeśli zbuduję to na mojej maszynie Linux AMD64 (Go 1.9), na przykład:
$ go build $ ls -la helloworld -rwxr-xr-x 1 janf group 2029206 Sep 11 16:58 helloworld
Otrzymuję plik binarny o rozmiarze około 2 Mb.
Powodem tego (co zostało wyjaśnione w innych odpowiedziach) jest to, że używamy pakietu „fmt”, który jest dość duży, ale plik binarny również nie został usunięty, co oznacza, że tablica symboli nadal istnieje. Jeśli zamiast tego poinstruujemy kompilator, aby usunął plik binarny, stanie się on znacznie mniejszy:
$ go build -ldflags "-s -w" $ ls -la helloworld -rwxr-xr-x 1 janf group 1323616 Sep 11 17:01 helloworld
Jeśli jednak przepiszemy program, aby używał wbudowanej funkcji print, zamiast fmt.Println, na przykład:
package main func main() { print("Hello World!\n") }
A następnie skompiluj to:
$ go build -ldflags "-s -w" $ ls -la helloworld -rwxr-xr-x 1 janf group 714176 Sep 11 17:06 helloworld
Otrzymujemy jeszcze mniejszy plik binarny. Jest to tak małe, jak możemy to uzyskać bez uciekania się do sztuczek, takich jak pakowanie UPX, więc narzut czasu wykonywania Go wynosi około 700 Kb.
źródło
Zauważ, że problem z rozmiarem binarnym jest śledzony według numeru 6853 w projekcie golang / go .
Na przykład, commit a26c01a (dla Go 1.4) cut hello world o 70kB :
Biorąc pod uwagę, że kompilator, asembler, konsolidator i środowisko wykonawcze w wersji 1.5 będą w całości w Go, możesz spodziewać się dalszej optymalizacji.
Aktualizacja 2016 Go 1.7: to zostało zoptymalizowane: zobacz „ Mniejsze pliki binarne Go 1.7 ”.
Ale tego dnia (kwiecień 2019) najwięcej miejsca zajmuje
runtime.pclntab
.Zobacz „ Dlaczego moje pliki wykonywalne Go są tak duże? Wizualizacja rozmiaru plików wykonywalnych Go przy użyciu D3 ” autorstwa Raphael 'kena' Poss .
źródło