Pull to refresh

Как ускорить программу на Go

Reading time 2 min
Views 17K
Увы, я не веду свой бложик, а результат недавнего «открытия» обнародовать в виде заметки считаю необходимым. Полагаю, найдутся люди, которым это весьма пригодится.

Go — язык, компилируемый в нативный код, а посему, очевидно, должен быть быстрым. Однако, к сожалению, на данный момент это далеко не всегда соответствует действительности.
В моём же случае, Go проиграл PHP (ну, на самом деле модулю PHP на C, однако результат всё равно удручающий). Если кратко, то при вычислении Whirlpool-хеша Go проигрывал в 3,5-7.5 раз!

Во множестве источников описывается одна и та же причина — «слабый» стандартный компилятор Go (тот, что вызывается через go build). Это полностью верно. Дело в том, что компилятор довольно «молодой» и пока не имеет багажа оптимизаций, какой, например, имеет GCC.
Решение есть — существует вариант компилятора Go — gccgo.
Сборка программы через gccgo с оптимизациями производится так:
go build -compiler gccgo -gccgoflags "-march=native -O3" main.go
В данном случае будет выполнена сборка со всеми доступными оптимизациями и инструкциями на текущем оборудовании.
В целом, достаточно использовать только опцию -O2.

Результаты тестирования для моего случая:
Скрытый текст
# Standart compiler
➜ go build ./dedup.go
➜ time ./dedup > /dev/null

real 0m4.612s
user 0m4.588s
sys 0m0.020s

# gccgo compiler without optimizations
➜ go build -compiler gccgo ./dedup.go
➜ time ./dedup > /dev/null

real 0m2.110s
user 0m2.084s
sys 0m0.024s

# PHP realization
➜ time php hash.php > /dev/null

real 0m0.634s
user 0m0.608s
sys 0m0.024s

# gccgo with optimizations
➜ go build -a -gccgoflags "-march=native -O3" -compiler gccgo ./dedup.go
➜ time ./dedup > /dev/null

real 0m0.534s
user 0m0.512s
sys 0m0.020s


Итого время выполнения программы, собранной gccgo с оптимизациями, оказалось в 4.2-9.2 раза быстрее билда без оптимизаций.
Сводная «табличка»:
Вариант Относительное время
gccgo optimized 85%
PHP 100%
gc v1.2.1 210%
gccgo 350%
gc v1 750%

На этом, в общем-то, всё, спасибо за внимание.

UPD1: Компилятор в go 1.2.1 даёт значительно лучшие результаты (добавлен в таблицу):
Скрытый текст
➜ time ./dedup > /dev/null

real 0m1.550s
user 0m1.528s
sys 0m0.020s

Также, обратите внимание, что есть некоторое различие в итоговой сборке при использовании разных компиляторов для разных платформ или различных линковщиков. Информация здесь: blog.golang.org/gccgo-in-gcc-471
Вкратце, всё будет хорошо, если использовать gccgo >=4.7.1 в паре с линковщиком gold на x86 (32/64 bit). Проблемы же, пожалуй, не сильно страшные, зато появляется больше целевых платформ. Подробности в посте по ссылке выше.
Tags:
Hubs:
+5
Comments 25
Comments Comments 25

Articles