Как уменьшить размер скомпилированного файла?
Давайте сравним c и идем:
Hello_world.c:
#include<stdio.h>
int main(){
printf("Hello world!");
}
Hello_world.go:
package main
import "fmt"
func main(){
fmt.Printf("Hello world!")
}
Скомпилируйте оба:
$gcc Hello_world.c -o Hello_c
$8g Hello_world.go -o Hello_go.8
$8l Hello_go.8 -o Hello_go
и... что это такое?
$ls -ls
... 5,4K 2010-10-05 11:09 Hello_c
... 991K 2010-10-05 11:17 Hello_go
О 1Mb Привет, мир. Ты шутишь, что ли?
Что я делаю неправильно?
(только строка Hello_go → 893K)
Ответы
Ответ 1
Проблема в том, что файл больше? Я не знаю Go, но я бы предположил, что он статически связывает некоторые библиотеки времени выполнения, что не относится к программе C. Но, вероятно, это не о чем беспокоиться, как только ваша программа станет больше.
Как описано здесь, статическая привязка времени выполнения Go является значением по умолчанию. На этой странице также описано, как настроить динамическую компоновку.
Ответ 2
Если вы используете систему на базе Unix (например, Linux или Mac OSX), вы можете попробовать удалить информацию об отладке, включенную в исполняемый файл, создав ее с помощью флага -s:
go build -ldflags "-s" prog.go
Я не знаю, как это сделать в Windows, но в Linux размеры файлов резко сокращаются.
Подробнее см. страницу GDB: http://golang.org/doc/gdb
Ответ 3
Ответ 2016 года:
1. Используйте Go 1.7
2. Скомпилировать с помощью go build -ldflags "-s -w"
➜ ls -lh hello
-rwxr-xr-x 1 oneofone oneofone 976K May 26 20:49 hello*
3. Затем используйте upx
, goupx
больше не требуется с 1.6.
➜ ls -lh hello
-rwxr-xr-x 1 oneofone oneofone 367K May 26 20:49 hello*
Ответ 4
Go двоичные файлы большие, потому что они статически связаны (за исключением привязок библиотек с использованием cgo). Попробуйте статически связать программу C, и вы увидите, что она растет до сопоставимого размера.
Если это действительно проблема для вас (которую я с трудом верю), вы можете скомпилировать ее с помощью gccgo и динамически связать.
Ответ 5
Вы должны получить goupx, он будет "исправлять" исполняемые файлы Golang ELF для работы с upx
. В некоторых случаях у меня уже около 78% размера файла ~16MB >> ~3MB
.
Коэффициент сжатия обычно составляет 25%, поэтому стоит попробовать:
$ go get github.com/pwaller/goupx
$ go build -o filename
$ goupx filename
<Р → > 2014/12/25 10:10:54 File fixed!
File size Ratio Format Name
-------------------- ------ ----------- -----------
16271132 -> 3647116 22.41% linux/ElfAMD filename
Packed 1 file.
EXTRA: флаг -s
(полоса) может сжать файл bin еще больше goupx -s filename
Ответ 6
Более компактный пример hello-world:
package main
func main() {
print("Hello world!")
}
Мы пропустили большой пакет fmt
и заметно уменьшили двоичный файл:
$ go build hello.go
$ ls -lh hello
... 259K ... hello2
$ strip hello
$ ls -lh hello
... 162K ... hello2
Не такой компактный, как C, но хотя и измеряется в K не M:) Хорошо, это не общий способ, просто показывает некоторые способы оптимизации размера: используйте полосу и попытайтесь использовать минимальные пакеты. В любом случае Go не является языком для создания миниатюрных бинарных файлов.
Ответ 7
создайте файл с именем main.go
,
попробуйте с простой мировой программой приветствия.
package main
import "fmt"
func main(){
fmt.Println("Hello World!")
}
Я использую go version 1.9.1
$ go version
go version go1.9.1 linux/amd64
Скомпилируйте стандартную команду go build
.
$ go build main.go
$ ls -lh
-rwxr-xr-x-x 1 nil nil 1.8M Oct 27 07:47 main
Скомпилируйте еще раз go build
, но с ldflags
, как было предложено выше,
$ go build -ldflags "-s -w" main.go
$ ls -lh
-rwxr-xr-x-x 1 nil nil 1.2M Oct 27 08:15 main
Размер файла уменьшается на 30%.
Теперь, используйте gccgo
,
$ go version
go version go1.8.1 gccgo (GCC) 7.2.0 linux/amd64
Построение с gccgo
,
$ go build main.go
$ ls -lh
-rwxr-xr-x 1 nil nil 34K Oct 27 12:18 main
Двоичный размер уменьшается почти на 100%.
Давайте еще раз попытаемся построить наш main.go
с помощью gccgo
, но с флагами сборки,
$ go build -gccgoflags "-s -w" main.go
-rwxr-xr-x 1 nil nil 23K Oct 27 13:02 main
Внимание:
Так как бинарные файлы gccgo
были динамически связаны.
Если у вас есть бинарный файл, который очень большой по размеру, ваш двоичный файл при компиляции с gccgo не будет уменьшен на 100%, но он будет уменьшен в размере на значительное количество.
По сравнению с gc, gccgo медленнее компилирует код, но поддерживает более мощные оптимизации, поэтому программа с привязкой к процессору, созданная gccgo, будет работать быстрее. Доступны все оптимизации, реализованные в GCC на протяжении многих лет, включая встраивание, оптимизацию циклов, векторизация, планирование команд и многое другое. Хотя он не всегда дает лучший код, в некоторых случаях программы, скомпилированные с помощью gccgo, могут работать на 30% быстрее.
Ожидается, что выпуски GCC 7 будут включать полную реализацию пользовательских библиотек Go 1.8. Как и в предыдущих версиях, среда выполнения Go 1.8 не полностью слита, но это не должно быть видимым для программ Go.
Плюсы:
- Уменьшенный размер
- Оптимизированный.
против
- Низкая
- Невозможно использовать последнюю версию
go
.
Здесь вы можете увидеть здесь и здесь.
Ответ 8
Двоичный файл содержит по умолчанию сборщик мусора, систему планирования, управляющую процедурами go и все импортируемые библиотеки.
Результат - минимальный размер около 1 Мб.
Ответ 9
От Go 1.8 вы также можете использовать новую систему плагинов, чтобы разбить ваш двоичный код на нечто, похожее на общие библиотеки. Для этой версии он работает только в Linux, но в будущем, возможно, будут поддерживаться другие платформы.
https://tip.golang.org/pkg/plugin/