Otimização 0.1
Achei bem interessante que nesse tempo que fiquei sem escrever, o blog teve uma quantidade de acessos maior que em tempos de atividade. De qualquer forma, um post de vez em quando não faz mal a ninguém :).
Tem um site de tirinhas chamado Vida de Programador que posta situações corriqueiras (as vezes) de forma engraçada.
Na tirinha de hoje, ele mostrava o código de um programador iniciante:
bool isValid; ... switch(isValid) { case true: ... case false: ... }
Claro que não faz sentido tanta verborragia pra algo tão simples como uma variável booleana. No entanto, as pessoas se esquecem que os compiladores atuais são muito bons e não vão deixar seu código lento só porque você preferiu que ele fosse “mais legível”.
Uma excelente ferramenta online chamada GCC Explorer mostra a saída assembly do seu compilador preferido com diversos níveis de otimização.
Independente do nível de otimização, o código gerado para o trecho acima será extamente o mesmo que para “if...else
” ou o operador ternário “? :
“.
int testFunction(bool x) { switch (x) { case true: return 10; break; case false: return 12; } } int testFunction2(bool x) { return x? 10 : 12; }
E o Assembly gerado (com -O2) será:
testFunction(bool): cmpb $1, %dil sbbl %eax, %eax andl $2, %eax addl $10, %eax ret testFunction2(bool): cmpb $1, %dil sbbl %eax, %eax andl $2, %eax addl $10, %eax ret
Se você olhar, não há nenhum jump no assembly gerado. Ele compara a variável com o número 1, subtrai o registro de retorno dele mesmo com borrow, faz um AND com o 2 e depois soma 10. Você não ia pensar que retornar 12 ou 10 significa colocar 2 ou 0 numa variável e depois somar 10, mas o compilador sabe que lógica AND e OR para números inteiros é muito mais rápida que jumps e faz tudo sem que você se preocupe. Esse código seria semelhante a:
int testFunction3(bool x) { return 10 + (2 & -(1-x)); }
Mas o GCC consegue diminuir ainda mais o assembly!
testFunction3(bool): leal 3(%rdi), %eax andl $2, %eax addl $10, %eax ret
Só que ninguém vai querer ler um código tão feio assim que apenas poupa 1 nanossegundo.
Sem dar razão à pessoa que fez um switch para um bool, se o código não é o gargalo do seu programa, não há motivo para mudar. Como escreveu Donald Knuth: otimização prematura é a raiz de todo o mal.