Otimização de Executáveis com o gcc
Otimização de Executáveis com o GCC,explicações e definições.
Recentemente um amigo me perguntou sobre “como eu faço para deixar um executável mais rápido no Linux” ,isso me intrigou,não conhecia muito sobre isso então comecei-a pesquisar mais sobre a otimização de executáveis ,encontrei muitas informações é irei apresenta-la em um tutorial,para ficarem mais claras.
O GCC é o melhor compilador que existe(sem duvida nenhuma), ele é composto por ferramentas de compilação, assembler e de linkagem, sua função é produzir executáveis prontos parar “rodar” em um formato aceito pelo SO (as formas de execução é a estrutura de um binário variam de acordo com o SO), o seu modo de operação se divide em 4(quatro) etapas,em geral executadas em sequência e automaticamente pelo compilador:
- Preprocessamento:Nesta etapa ocorre a produção do código que já não possui diretivas,coisas como “#if” não podem ser entendidos diretamente pelo compilador,portanto,será traduzida para o código da maquina.
- Compilação:passo em que o compilador traduz o programa em texto para um arquivo objeto,o qual contém todas as referências de códigos e bibliotecas utilizadas.
- Assembler: Aceita os assembly mnemônicos é produz o código contendo opcodes.É comum o equívocos causados pelo compilador,como não produzir os opcodes,o estágio de assembler “limpa sujeira” causa pelo compilador.
- Linkagem: nome adaptado do inglês, linking, que transforma um arquivo objeto em executável, preenchendo todas as referências e gerando o código completo.
Agora que conhecemos um pouco mais sobre o funcionamento do GCC (recomendo o bom é velho man gcc, para mais informações), vamos ao oque interessa,as otimizações do executável.
Obs: É importante verificar a sua versão do gcc, porque muitas das flags do gcc 3.x não funcionam no gcc 2.x, então é importante saber as flags que a sua versão do gcc suporta.
Para saber a versão de GCC, digite:
$ gcc --version ou gcc -v
Para saber informação sobre o processador:
$ cat /proc/cpuinfo
Agora com as informações sobre o processador é a versão do gcc podemos dar continuidade.
O que são CFLAGS?
CFLAGS são flags do compilador C, geralmente opções do GCC (GNU Compiler Collection). CFLAGS podem ser usadas para customizar e otimizar aplicações quando você as constrói pelos fontes. (Esta é uma importante característica de algumas distribuições, como o gentoo, já que a maioria dos pacotes são instalados a partir do código-fonte nestes). CFLAGS são geralmente usadas para especificar a arquitetura de seu computador, bem como o tipo de CPU usada e qualquer outra opção especial que se queira habilitar ou desabilitar. Esta informação é importante para o GCC diz a ele exatamente como customizar as instruções de montagem que ele cria através do código-fonte da aplicação. Tecnicamente o GCC pode rodar sem nenhuma CFLAG, já que são opções extra.
Otimizações Básicas (seguras)
Existem diversas opções de otimização básicas consideradas seguras para o uso geral. A primeira delas é -O (letra, não número). Para ver exatamente quais flags de otimização são habilitadas a cada um dos níveis de otimização, bem como uma lista de outras otimizações que podem ser habilitadas, por favor leia a man page do GCC.
-O
-O liga algumas otimizações básicas que não causam grande impacto na velocidade de compilação, e vão aumentar consideravelmente a velocidade do seu sistema. Apesar que não há muita razão para usar -O ao invés de -O2.
-O2
-O2 liga todas as otimizações de -O e todas as outras otimizações que não aumentam muito o tamanho dos binários gerados ou interferem no debugging. -O2 é ainda melhor que -O, e geralmente tão seguro quanto. Este é o nível de otimização mais usado para pacotes e distribuições no mundo Linux e para o kernel Linux. Se você quer um sistema que “apenas funcione”, -O2 provavelmente é bom pra você.
-O3
-O3 liga todas as otimizações de -O2 e ainda algumas otimizações que aumentam o tamanho dos binários gerados além de tornar o debugging mais difícil ou até mesmo impossível. Usar -O3 como deu nível default de otimização pode ser uma má ideia. Nela o nível de otimização mais alto e possivelmente torna o código mais rápido mas as aplicações que se beneficiam disto são muito poucas, geralmente decoders de vídeo e imagem e coisas do tipo. Entretanto, os efeitos colaterais, como binários maiores, afetam tudo. Binários maiores ocupam mais memória, carregam mais devagar, causam mais I/O de disco, etc. Então compilar um sistema com -O3 vai ter o efeito de poucas aplicações rodando ligeiramente mais rápidas ao custo do resto do sistema rodando ligeiramente mais devagar e se tornando menos responsivo.
O Linux armazena regularmente programas e arquivos na RAM (este é a parte “cache” quando você executa free -m ), então os programas podem precisar carregar do disco rígido apenas uma vez (dependendo do programa e computador usado). Portanto este é menos um problema em sistemas com grande quantidade de RAM. Um sistema com grande quantidade de cache de CPU também ajuda já que se ajusta melhor a binários maiores, então você acaba notando maior velocidade neles. Então, se você tem um sistema topo-de-linha, você sofrerá menos de problemas associados com -O3.
-Os
-Os otimiza para tamanho. -Os habilita todas as otimizações de -O2 que geralmente não aumentam o tamanho do código e executa ainda mais otimizações desenvolvidas para reduzir o tamanho do código.
-Os é muito útil para aplicações grandes, como o Firefox,KDE,openoffice, já que vai reduzir o tempo de carregamento, uso de memória e cache, uso de disco etc. Código compilado com -Os pode ser mais rápido que com -O2 ou -O3 por causa disso. Também é recomendado para computadores velhos com pouca quantidade de RAM, espaço em disco ou cache de CPU. Mas esteja avisado que -Os não está tão bem testado quanto -O2 e pode levar a bugs de compilação.
Note que apenas uma das flags acima pode ser escolhida. Se você escolher mais de uma, só a última especificada terá efeito.
-fomit-frame-pointer
-fomit-frame-pointer diz ao gcc para omitir frame pointers, liberando um registrador adicional na CPU. Isto é principalmente útil em x86 já que a maioria das arquiteturas, como AMD64, tem isso por default em -O2 ou superior, apesar de o tamanho dos binários poder aumentar ligeiramente. Esta flag quebra o debugging em x86 e possivelmente outras arquiteturas a menos que você compile com gcc 4.x e a flag -fvar-tracking.
Glibc tem uma flag USE: glibc-omitfp. Isto faz a glibc usar -fomit-frame-pointer e algumas outras otimizações para o pacote quando for seguro. Para ler mais sobre otimizar a glibc tente este HOWTO
-march=;sua_arquitetura;
-march dis ao gcc para otimizar para uma certa arquitetura. Basicamente, você apenas precisa saber qual é a sua CPU, e o código GCC para ela. Lembre-se de que esta flag quebra compatibilidade com outras arquiteturas!
Esta flag toma a seguinte forma:
-march=pentium4
Obviamente você substituirá pentium4 pelo código correspondente.
Aqui segue uma lista incompleta de arquiteturas x86 válidas que podem ser usadas com a flag -march:
i386, i486, i586, i686, pentium, pentium-mmx, pentiumpro, pentium2, pentium3, pentium-m, pentium4, prescott, k6, k6-2, k6-3, k8, athlon, athlon-tbird, athlon-4, athlon-xp, athlon-mp, athlon64, opteron, winchip-c6, winchip2, c3.
Caso esteja usando o gcc 4.2 é mais facil e provavelmente(caso não saiba qual a flag mais aproprida) usar:
-march=native
Com isso o gcc ira auto-detectar
Cheque o gcc manual para um alista completa (em Hardware Models and Configurations).
Note: “-march” implica “-mtune” (veja a man page do gcc).
-mtune=/-mcpu=;sua_arquitetura;
-mtune, ou -mcpu em versões antigas do GCC, é similar ao -march e aceita as mesmas opções. Diferente de -march ele não quebra compatibilidde com outras arquiteturas. As opções de -march e -mtune/-mcpu podem ser misturadas para alcançar o efeito desejado. Se você não vai compartilhar seus binários com outros computadores você não precisa desta flag e deve utilizar apenas uma flag -march apropriada. As exceções são arquiteturas como PPC onde -march não está disponível. Veja o Guia de CFLAGs Seguras para mais informações.
Documentação do GCC sobre -march e -mcpu/-mtune
-pipe
A última e mais comum flag é a opção ‘-pipe’. A opção pipe diz ao GCC para não criar arquivos temporários quando compilando, e ao invés disso canalizar (pipe) dados diretamente para a próxima função, o que salva algum tempo de compilação. Esteja avisado que usar -pipe vai fazer o GCC usar mais RAM então não use se isto se você tiver pouca.
CFLAGS comuns para desenvolvedores
-Wall: Isto habilita todos os avisos sobre construções que alguns usuários consideram questionáveis, e que são fáceis de evitar (ou modificar para prevenir o aviso), mesmo em conjunção com macros.
-Wextra: Imprime avisos extras
-Werror:Transforma avisos em erros, e então o GCC irá interromper a compilação após o aviso (porque se tornou um erro).
-ggdb: Inclui toda a informação de debugging possível no binário gerado que é útil para gdb.
Segue abaixo uma tabela com as diferenças técnicas entre O1,O2,O3.
Agora sinta-se a vontade para testar as otimizações.
$./configure CFLAG="-march=athlon-xp -O3 -pipe"
$make
#make install
Fontes e Referências:
http://docs.freebsd.org/info//gcc/gcc.info.Optimize_Options.html
http://www.linuxjournal.com/article/7269
http://psydesk.blogspot.com/2007/01/cflag-otimizando-sua-compilao-no-linux.html
FLAGS para “compilação segura” com GCC 3.X
Safe Cflags
Getting Familiar with GCC Parameters













Comentários Recentes