Otimização De Código
- Definição e Propriedades de
- Tipos e Níveis de Otimização
- o Que para Otimizar
- Bons e Maus Resultados da Otimização
- Conclusão
- PVS-Studio
Conteúdo
Definição e Propriedades de
otimização de Código é qualquer método de modificação do código para melhorar a qualidade do código e eficiência. Um programa pode ser otimizado para que se torne um tamanho menor, consome menos memória, executa mais rapidamente, ou executa menos operações de entrada/saída.
os métodos básicos de otimização de requisitos devem cumprir, é que um programa otimizado deve ter a mesma saída e efeitos colaterais que sua versão não otimizada. Este requisito, no entanto, pode ser ignorado no caso de que o benefício da otimização, é estimado para ser mais importante do que as consequências prováveis de uma mudança no comportamento do programa.
tipos e níveis de otimização
otimização pode ser realizada por Otimizadores automáticos, ou programadores. Um otimizador é uma ferramenta de software especializada ou uma unidade incorporada de um compilador (o chamado compilador otimizador). Processadores modernos também podem otimizar a ordem de execução de instruções de código.
optimizações são classificadas em optimizações de alto e baixo nível. Otimizações de alto nível são geralmente realizadas pelo programador, que lida com entidades abstratas (funções, procedimentos, classes, etc.) e tem em mente a estrutura geral da tarefa para otimizar o projeto de um sistema. Otimizações realizadas ao nível de blocos estruturais elementares de código fonte – loops, ramificações, etc. – são geralmente referidas como otimizações de alto nível também, enquanto alguns autores classificam-nas em um nível separado (“médio”) (N. Wirth?). Otimizações de baixo nível são realizadas na fase em que o código fonte é compilado em um conjunto de instruções da máquina, e é nesta fase que a otimização automatizada é normalmente empregada. Programadores Assembler acreditam, no entanto, que nenhuma máquina, por mais perfeita que seja, pode fazer isso melhor do que um programador qualificado (no entanto, todo mundo concorda que um programador pobre vai fazer muito pior do que um computador).
o que otimizar
com a otimização de código manual, um enfrenta outro problema: não basta saber exatamente como a otimização deve ser feita, mas também que parte particular do programa deve ser otimizada. Devido a várias razões (lento de entrada, operações, a diferença na velocidade de trabalho de um operador humano e um computador, e assim por diante), 90% do tempo de execução de um programa é gasto para a execução de apenas 10% do código (esta declaração é bastante especulativo, com o princípio de Pareto como bastante duvidoso chão, mas A. Tanenbaum faz parecer convincente). Uma vez que a otimização leva tempo adicional além do tempo que você gastou no desenvolvimento do programa, é melhor se concentrar em otimizar este tempo crítico 10% do código, em vez de tentar otimizar todo o programa. Estes fragmentos de código são conhecidos como gargalos, e podem ser detectados por utilitários especiais – profilers – que podem medir o tempo tomado por várias partes do programa para executar.
na prática, no entanto, a otimização é geralmente feita após o estágio de programação” caótica “(incluindo métodos como” Copy-Paste”,” veremos mais tarde”,” it’s OK this way”), e portanto é uma mistura de otimização como tal, refactoring e correcções de bugfixes: simplificação de construções” queer ” como strlen(path.c_str ()), condições lógicas como (A. x != 0 & & A. X. != 0), e assim por diante. Os Profilers são de pouca ajuda com este tipo de otimização. No entanto, você pode detectar essas questões com ferramentas de análise estática, ou seja, ferramentas projetadas para procurar erros semânticos, dependendo da análise profunda do código fonte. Como você pode ver a partir do exemplo acima mencionado com a condição estranha, código ineficiente pode aparecer como resultado de erros (como um erro de impressão em nosso exemplo, onde um.x != 0 & & A. y != 0 deve ser em vez). Um analisador estático poderoso irá detectar esses fragmentos de código e chamar a sua atenção para eles, produzindo mensagens de aviso.
bons e maus resultados de otimização
na programação, quase tudo deve ser tratado do ponto de vista da racionalidade – otimização não é exceção. Há uma crença de que o código escrito por um programador de montagem inexperiente é 3-5 vezes mais lento do que o código gerado pelo compilador (Zubkov). Amplamente conhecido é uma frase de Knuth sobre otimizações iniciais de baixo nível (tais como tentativas de economizar em operadores ou variáveis): “otimização prematura é a raiz de todo o mal”.
a maioria dos programadores não se queixam de otimizações realizadas pelo otimizador, algumas das quais são convencionais e obrigatórias. Como, por exemplo, a otimização de chamadas de cauda em linguagens funcionais (chamada de cauda é um caso especial de recursão, que pode ser representado como um loop).
no entanto, deve-se entender que múltiplas otimizações complexas ao nível do Código da máquina podem causar uma grande desaceleração da compilação. O benefício que lhe permitem ganhar pode ser muito insignificante, quando comparado com as otimizações gerais de design do sistema (Wirth). Deve-se também ter em mente que as línguas modernas, com todas as suas “frescuras” sintáticas e semânticas, têm muitas nuances e sutilezas, para que um programador que não está familiarizado com elas possa ser surpreendido por um resultado de otimização.
por exemplo, tome C++ e a chamada otimização de retorno-valor, quando o compilador evita copiar um objeto temporário retornado por uma função. Como o compilador omite a cópia, este método também é chamado de “elision cópia”. Então, o seguinte código:
#include <iostream> struct C { C() {} C(const C&) { std::cout << "A copy was made.\n"; }}; C f() { return C();} int main() { std::cout << "Hello World!\n"; C obj = f();}
pode ter várias saídas:
Hello World!A copy was made.A copy was made.Hello World!A copy was made.Hello World!
por estranho que pareça, todas as três versões são válidas porque o padrão da linguagem permite omitir chamadas de um construtor de cópia em tais casos, mesmo que o construtor tenha efeitos colaterais (§12.8 copiar objetos da classe, parágrafo 15).
Conclusão
Assim, devemos sempre pensar em otimizar o código do programa utilizando utilitários especializados, sempre que possível, mas fazer isso com muito cuidado, e estar pronto para a probabilidade de inesperado truques do compilador, às vezes.
PVS-Studio
um conjunto de diagnósticos é implementado no analisador estático PVS-Studio que lhe permite encontrar algumas situações onde o código pode ser otimizado. No entanto, PVS-Studio como qualquer outro analisador estático não pode servir como uma substituição das ferramentas de perfil. Apenas os analisadores dinâmicos de programas são capazes de identificar os pontos de estrangulamento. Analisadores estáticos não sabem o que os programas de dados de entrada recebem e com que frequência uma determinada peça de código é executada. É por isso que estamos dizendo que o analisador sugere a implementação de algumas “micro-otimizações” de código, que não garantem os ganhos de desempenho.
apesar da desvantagem considerada, o analisador PVS-Studio atua como um bom complemento para as ferramentas de perfis. Além disso, ao lidar com avisos PVS-Studio, relacionados com a otimização, o código muitas vezes se torna mais simples e mais curto. This effect is considered in more detail in the article “Exploring Microoptimizations Using Tizen Code as an Example”.