Pull to refresh

Comments 25

I've profiled the «go build» variant of program (same run time with profiling code) and saw, that 94.1% of time program was in

github.com/jzelinskie/whirlpool.(*whirlpool).transform


Кастинг в Go медленный. Кошерный способ оптимизации с этом случае — вынос кастинга за пределы цикла.
Это вот здесь:

// Iterate over all the rounds.
for r := 1; r >56)] ^
_C1[byte(K[(i+7)%8]>>48)] ^
_C2[byte(K[(i+6)%8]>>40)] ^
_C3[byte(K[(i+5)%8]>>32)] ^
_C4[byte(K[(i+4)%8]>>24)] ^
_C5[byte(K[(i+3)%8]>>16)] ^
_C6[byte(K[(i+2)%8]>>8)] ^
_C7[byte(K[(i+1)%8])]
}

и

for i := 0; i < 8; i++ {
L[i] = _C0[byte(state[i%8]>>56)] ^
_C1[byte(state[(i+7)%8]>>48)] ^
_C2[byte(state[(i+6)%8]>>40)] ^
_C3[byte(state[(i+5)%8]>>32)] ^
_C4[byte(state[(i+4)%8]>>24)] ^
_C5[byte(state[(i+3)%8]>>16)] ^
_C6[byte(state[(i+2)%8]>>8)] ^
_C7[byte(state[(i+1)%8])] ^
K[i%8]
}
А, понятно. Тогда я согласен с комментарием mc_dir ниже. Тяжелую часть можно вынести в C, через cgo. Правда это слегка подпортит жизнь тем, кто собирает Go под Windows.
При сборке с оптимизациями особого смысла это более не имеет. Да и запарно выносить, мне кажется.
У gccgo свои заморочки, например goroutines там становятся полноценными потокоми, иными словами теряется вся прелесть Go.
пруф, пожалуйста, в студию.
Цитата из The Go Programming Language Phrasebook:

The most obvious is that gccgo uses operating system threads to implement goroutines, and will not use segmented stacks in all configurations. This means that creating a goroutine is as expensive as creating a thread in C.


FAQ также утверждает, что:

The gccgo compiler implements segmented stacks on Linux only, supported by recent modifications to the gold linker.


Я не в курсе значит ли это, что и переключение между goroutines кооперативное под gccgo или нет.
Желтовато получается.
В php hash (whirlpool) реализован на С [тыц], и компилируется со всеми необходимыми оптимизациями (в примере так полагаю эту функцию и тестируют),
когда в GO whirlpool реализован на самом GO [тыц]
Если вы уже хотите два языка сравнить, так воаля перепишите whirlpool на чистый PHP и сравните…
Видимо, скромного примечания в скобках оказалось недостаточно. Сейчас подправлю.
Заголовок статьи обещал помочь ускорить Go. Результат статьи — ускорение работы. Автор не пытался возвысить один язык над другим, более того, в итоге код на Go сработал почти со скоростью кода на Си/ПХП. Не увидел здесь желтизны.
Можно написать статью по ускорению С++. Из 2 предложений: «Я собирался с O0, стал собираться с O3! Чудо, стало быстрее!!»
Забавно, но факт — я нашёл только одно упоминание того, что человек собирает свой код через gccgo с флагами оптимизации. Причем, по теме ускорение это не гуглится.
Да, и про сравнение. С самого начала было понятно, что там шустрый Сишный модуль. Тем не менее такой огромный проигрыш не мог не расстроить меня. Т.е. сравнение в принципе проводилось ради того, чтобы выяснить, это whirlpool такой медленный или реализация/язык.
Не всем понятно где какой модуль и что использует. И похоже когда я писал коментарий название у статьи было другое. А за освещение возможности оптимизации компиляции GO спасибо.
Название статьи не трогал.
Однако, как отметили выше, у gccgo есть свои особенности и не все из них приятные. Позже обновлю статью, попробую, как советовали в группе вконтакте, собрать в версии 1.2/1.3 (судя по всему у меня 1.1 или даже старее).
Некоторые пакеты в Go ещё недостаточно оптимизированы. Например тот же regexp обещали ускорить в 1.3.
Кстати, какой версии Go использовался?
Он не признаётся наверняка:
➜ go version
go version go1
➜ go env
GOROOT="/usr/lib/go"
GOBIN=""
GOARCH=«386»
GOCHAR=«8»
GOOS=«linux»
GOEXE=""
GOHOSTARCH=«386»
GOHOSTOS=«linux»
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_386"
GOGCCFLAGS="-g -O2 -fPIC -m32 -pthread"
CGO_ENABLED=«1»
У вас версия 1. Он был заметно ускорен, ЕМНИП, к 1.1.2. Попробуйте последнюю версию 1.2.2.
Попробовал, обновление в посте. gccgo всё ещё лучше.
Этот пост — не сравнение производительности Go и PHP.
о как.
извините, видимо у меня встроенный анализатор текстов сломался.
Были проблемы с gccgo, когда использовал горутины. Решается использованием линкера gold замест ld (в binutils 2.22+ он есть). У меня gccgo собран из сырья, версия 4.10.0 20140719 (experimental). Рекомендую, т.к. более новая. Насчёт флагов я лично не мелочусь:
go build -compiler gccgo -gccgoflags "-march=native -Ofast -pipe -fomit-frame-pointer -fuse-ld=gold -Wl,--strip-all"

Но большие пакеты так собирать не приходилось. Так что будьте осторожны. Ещё хочу отметить, что в версии gccgo (Ubuntu 4.9.1-0ubuntu1) 4.9.1 стрип (-Wl,--strip-all) портит всё. Сама по себе опция -Ofast считается не рекомендуемой (gentoo вики), а вот насчёт -O3 vs. -O2 скажу прямо — используйте -O3 для узких мест не стесняясь. Мои исследования ассемблерного листинга с этими флагами показали меньший размер и эффективное использование хвостовой рекурсии с флагом -O3. Не мешало бы добавить, что простора для жёсткого «инлайнинга» в моём примере у компилятора не было (что значит, при иных раскладах размер может и увеличиться).
Помимо всего вышесказанного, если использовать в своих программах пакет syscall, то gccgo (упомянутых выше версий) выдаст ошибку — такие пакеты компилируются только golang-go (или нужно подождать патчей). Ну и разумеется не получиться использовать плюшки go 1.4 (что впрочем не сильно напрягает).
Only those users with full accounts are able to leave comments. Log in, please.