2015-02-18 3 views
33

Я выполнил программу Hello World Go, которая сгенерировала собственный исполняемый файл на моей Linux-машине. Но я был удивлен, увидев размер простой программы Hello World Go, это было 1,9 МБ!Причина огромного размера скомпилированного исполняемого файла Go

Почему это так, что исполняемый файл такой простой программы в Go настолько огромен?

+7

Огромный? Я думаю, вы не делаете много Java тогда! –

+4

Ну, им из C/C++ фона! –

+0

Я просто попробовал этот scala-родной мир приветствия: http://www.scala-native.org/en/latest/user/sbt.html#minimal-sbt-project Потребовалось довольно много времени, чтобы скомпилировать, загрузить много и двоичный файл - 3,9 МБ. – bli

ответ

37

Это точный вопрос появляется в официальном FAQ: Why is my trivial program such a large binary?

Цитирование ответ:

линкеры в цепи дс инструмента (5l, 6l и 8l) делать статические ссылки. Таким образом, двоичные файлы Go включают в себя время выполнения Go вместе с информацией типа времени выполнения, необходимой для поддержки проверок динамического типа, отражения и даже трассировки стека паники.

Простая программа «привет, мир», скомпилированная и связанная статически с использованием gcc на Linux, составляет около 750 КБ, включая реализацию printf. Эквивалентная программа Go с использованием fmt.Printf составляет около 1,9 МБ, но включает более мощную поддержку и информацию о времени выполнения.

Таким образом, собственный исполняемый файл вашего Hello World составляет 1,9 МБ, поскольку он содержит среду выполнения, которая обеспечивает сбор мусора, отражение и многие другие функции (которые ваша программа может не использовать, но она есть). И реализация пакета fmt, который вы использовали для печати текста "Hello World" (плюс его зависимости).

Теперь попробуйте следующее: добавьте еще одну строку fmt.Println("Hello World! Again") в свою программу и скомпилируйте ее снова. Результат не будет 2x 1,9 МБ, но все равно всего 1,9 МБ! Да, потому что все используемые библиотеки (fmt и его зависимости) и среда выполнения уже добавлены в исполняемый файл (и поэтому для печати второго текста, который вы только что добавили, будет добавлено только несколько байт).

7

Обратите внимание, что проблема двоичного размера отслеживается issue 6853 в golang/go project.

Например, commit a26c01a (для Go 1.4) вырезать привет мир от 70kb:

, потому что мы не пишем эти имена в таблице символов.

Учитывая компилятор, ассемблер, компоновщик, и выполнения для 1.5 будет полностью в Go, вы можете ожидать дальнейшей оптимизации.

+0

Я не вижу, к чему он относится. Им нужно использовать общие библиотеки. Несколько невероятно, что они уже не в этот день и в возрасте. – EJP

+0

@EJP: Зачем им нужно использовать общие библиотеки? – Flimzy

+4

@EJP, часть простоты Go не использует разделяемые библиотеки. На самом деле Go вообще не имеет никаких зависимостей, он использует простые системные вызовы. Просто разверните один бинарный файл, и он просто работает. Это значительно усугубило бы язык и его экосистему, если бы это было иначе. – creker

4

Рассмотрим следующую программу:

package main 

import "fmt" 

func main() { 
    fmt.Println("Hello World!") 
} 

Если я построю это на моей машине Linux AMD64 (Go 1.9), как это:

$ go build 
$ ls -la helloworld 
-rwxr-xr-x 1 janf group 2029206 Sep 11 16:58 helloworld 

Я получаю аа двоичный файл, что составляет около 2 Мб в размер.

Причина этого (что объясняется в других ответах) заключается в том, что мы используем пакет «fmt», который довольно велик, но двоичный файл также не был удален, а это означает, что таблица символов все еще существует ,Если мы вместо того, чтобы указать компилятору, чтобы лишить двоичный, он станет намного меньше:

$ go build -ldflags "-s -w" 
$ ls -la helloworld 
-rwxr-xr-x 1 janf group 1323616 Sep 11 17:01 helloworld 

Однако, если переписать программу, чтобы использовать встроенную функцию печати, а fmt.Println, как это:

package main 

func main() { 
    print("Hello World!\n") 
} 

А затем компилировать его:

$ go build -ldflags "-s -w" 
$ ls -la helloworld 
-rwxr-xr-x 1 janf group 714176 Sep 11 17:06 helloworld 

Мы в конечном итоге с еще меньшим двоичном. Это настолько мало, что мы можем получить его, не прибегая к трюкам, таким как UPX-упаковка, поэтому накладные расходы Go-runtime составляют примерно 700 Kb.

Смежные вопросы