Comments 3
Не очень понятно всё-таки как это работает. Они просмо пометили в компиляторе, что вот у этих двух библиотек у конкретно этих функций есть ассемблерные реализации, которые надо использовать вместо кода на го и лежат при этом эти ассемблерные инструкции не в .s файлах а где-то еще?
Вот просто есть у меня одна библиотека на го, которую используют в высоконагруженном коде и там очень важна производительность. И есть там очень много делений на константу дважды: один раз для получения результата деления и один раз для остатка. github.com/mr-tron/base58/blob/master/base58.go#L49
Давно была мысль заменить это на ассемблерную инструкцию, которая возвращает сразу и результат деления и остаток.
Ну я вот счас попробовал заменить
на
и получил сильное падение скорости.
Вот просто есть у меня одна библиотека на го, которую используют в высоконагруженном коде и там очень важна производительность. И есть там очень много делений на константу дважды: один раз для получения результата деления и один раз для остатка. github.com/mr-tron/base58/blob/master/base58.go#L49
Давно была мысль заменить это на ассемблерную инструкцию, которая возвращает сразу и результат деления и остаток.
Ну я вот счас попробовал заменить
tmp[j] = byte(carry % 58)
carry /= 58
на
carry, t = bits.Div32(0, carry, 58)
tmp[j] = byte(t)
и получил сильное падение скорости.
Стало интересно:
Цикл на go
Цикл на go
for i = zcount; i < binsz; i++ {
j = size - 1
for carry = uint32(bin[i]); j > high || carry != 0; j-- {
carry = carry + 256*uint32(tmp[j])
tmp[j] = byte(carry % 58)
carry /= 58
}
high = j
}
Как он компилируется напрямую:movzx r14d, byte ptr [r11+rsi]
shl r14d, 8
add r12d, r14d
mov r14d, 8D3DCB09h
imul r14, r12
shr r14, 25h
imul r15d, r14d, 3Ah
sub r12d, r15d
mov [rsi+r11], r12b
dec r11
mov r12, r14
Как он компилируется с использованием bits.Div32:movzx r14d, byte ptr [r11+rsi]
shl r14d, 8
add r14d, r12d
nop
mov r15d, r14d
shr r14, 1
mov r12, rax
mov rax, 8D3DCB08D3DCB08Eh
mul r14
shr rdx, 4
imul r14, rdx, 3Ah
sub r15, r14
mov [rsi+r11], r15b
dec r11
mov rax, r12
mov r12, rdx
mov rdx, [rsp+60h+var_20]
Количество вспомогательных mov инструкций стало больше, а количество умножений не уменьшилось. Но и пространства для оптимизации особо нет: 10 инструкций в нагруженном цикле.Не все intrinsic одинаково полезны.
Sign up to leave a comment.
Встраиваемые функции в Go