Switch

Jun. 4th, 2019 11:29 pm
elglin: (Default)
[personal profile] elglin
Реквестируется мнение умных людей.
Вот у меня есть шмат кода:
int function_1(char* arg);
// etc etc
int function_n(char* arg);

// start code snippet
unsigned char type;
char* data;
// receive type and data from somewhere
switch (type) {
    case CONST_1: {res = function_1(data); break;}
    // etc etc etc
    case CONST_N: {res = function_n(data); break}
}
//end code snippet

По факту-то этот свитч странслируется в нечто вроде (псевдоассемблер, синтаксис x86 я уже забыл)
MOV &type, EAX
#cmp1: MOV CONST_1, EBX
CMP EAX, EBX
JNZ #cmp2
CALL function_1
JMP #end
#cmp2: MOV CONST_2, EBX
CMP EAX, EBX
JNZ #cmp3
CALL function_2
JMP #end
...
#end

То есть много условного прыгания и куча шансов порвать конвейер. С другой стороны, штатная ситуация для предсказателя.
Но если сделать так (сто лет не работал с указателями на функции, могу провраться в синтаксисе):
int (*pfarray)(char*)[256];
// populate the array with pointers to correct functions
// receive type and data from somewhere
res = *(pfarray[type](data))

то результат-то будет:
MOV &type, EAX
SHL EAX, 2 // * sizeof(pfarray)
MOV pfarray, EBX
ADD EAX, EBX
CALL EBX

И конвейер, конечно, порвется с гарантией, поскольку никакой предсказатель не угадает содержимое EBX тактов за десять до вызова, но порвется он один и только один раз, плюс у нас не будет кучи MOV-CMP.

И, собственно, вопрос сведущим людям: а как быстрее-то? Мы действуем в предположении, что такты нам дороги, а килобайт памяти на указатели на функции - не очень.

(no subject)

Date: 2019-06-05 10:27 am (UTC)
beldmit: (Программизм)
From: [personal profile] beldmit
Я бы писал способом 2, потому как проще мейнтейнить. Но вообще в целом рулит профайлинг, а не теория :(
Page generated Feb. 26th, 2026 09:13 am
Powered by Dreamwidth Studios