Análise do custo de um comando

Olá,

Vou entrar em um projeto de otimização de sistema, ou seja, basicamente vou pegar uma ronita altera-la e após a alteração a mesma deve atingir os mesmos objetivos porém de uma forma muito mais rapida.

Tenho uma boa base de analise de algoritmos, identificar se o mesmo é lg n, O(N), etc … porém quero ir mais afundo!

Quero saber a nível de custo de comando:
Por exemplo: o que custa mais para o processador, um pré ou um pós encremento?!
Outro exemplo: O que custa mais um for ou um while …

A tambem tenho uma boa base de assembler e alguns comandos consigo deduzir como o comando fica na linguagem de maquina e dai consigo tirar um achismo de qual custa mais…

Alguém possui alguma apostila sobre isso, livro para indicação, alguma fonte de conhecimento?!
Sei que a experiência seria a melhor, porém to querendo da uma adiantada, :slight_smile: )

Muito Obrigado e abraços,
Paulo

Cara, eu tenho algumas documentações impressas a respeito disso. Porém estou no trabalho, quando chegar em casa, dou uma olhada e t dou um toque… este é um assunto que me interessa bastante…

Se seu sistema usar bancos de dados como o Oracle, por exemplo, você pode fazer análise de custo das próprias queries do sistema, melhorando a performance dos comandos. É o que os DBAs chamam de “tunning”.

Cara na atual edição da Mundo Java tem uma matéria sobre Profile em aplicações Java, não sei se é exatamente isso que você precisa, mas segue o link, na matéria ensina a usar um plugin do Eclipse para esses testes.

http://www.mundojava.com.br/NovoSite/materiacapa.shtml

Os seus exemplos são terríveis :stuck_out_tongue:

No primeiro caso: tanto faz. No segundo caso: tanto faz.

É um bocado difícil, dado um código Java, determinar “só de olhar” qual é mais rápido, a menos que o algoritmo seja totalmente diferente (se um é O(n^2) e outro é O(log n) então dá para saber que para n suficientemente grande, o algoritmo O(log n) é mais rápido).

De modo geral:

  • Dependendo do processador, o “JIT” (“just-in-time compiler”) gera código diferente. Por exemplo, se ele estiver rodando em um P-IV gera código diferente de quando ele roda em um P-III ou um Athlon.
  • Código mais bobo otimiza melhor que código muito “esperto”.
  • Não saia de um loop com uma exception; saia usando uma condição.

Há muitas variáveis (como “cache hits & misses”, e outras coisas) que tornam extremamente difícil determinar a velocidade relativa de um código em relação a outro, sem rodar o código e fazer uma série de benchmarks.

Só para ter uma idéia de como não adianta usar truques de programação, eis os resultados de um benchmark:

import java.util.Arrays;

class TesteLoop {
    /**
     * Para cada iteração faço um teste
     */
    public static long teste1(final double[] array) {
        long t = System.currentTimeMillis();
        final int n = array.length;
        for (int i = 0; i &lt n; ++i) {
            array[i] = Math.PI;
        }
        return System.currentTimeMillis() - t;
    }
    /**
     * Para cada iteração não faço teste nenhum
     */
    public static long teste2(final double[] array) {
        long t = System.currentTimeMillis();
        int i = 0;
        try {
            while (true) {
                array[i++] = Math.PI;
            }
        } catch (ArrayIndexOutOfBoundsException ex) {
        }
        return System.currentTimeMillis() - t;
    }
    /**
     * Para cada iteração faço um teste, mas contra 0
     */
    public static long teste3(final double[] array) {
        long t = System.currentTimeMillis();
        for (int i = array.length - 1; i &gt= 0; --i) {
            array[i] = Math.PI;
        }
        return System.currentTimeMillis() - t;
    }
    /**
     * Para cada iteração não faço teste nenhum
     */
    public static long teste4(final double[] array) {
        long t = System.currentTimeMillis();
        int i = array.length;
        try {
            while (true) {
                array[--i] = Math.PI;
            }
        } catch (ArrayIndexOutOfBoundsException ex) {
        }
        return System.currentTimeMillis() - t;
    }
    
    // Usando o que já está pronto
    public static long teste5 (final double[] array) {
        long t = System.currentTimeMillis();
        Arrays.fill (array, Math.PI);
        return System.currentTimeMillis() - t;
    }
    
     
    public static void warmup () {
        double[] array = new double [400000];
        for (int i = 0; i &lt 1000; ++i) {
            teste1(array);
            teste2(array);
            teste3(array);
            teste4(array);
            teste5(array);
        }
    }
    
    public static void teste() {
        double[] array = new double [400000];
        long[] acc = new long[1+5]; 
        for (int i = 0; i &lt 2000; ++i) {
            acc[1] += teste1 (array);
        }
        for (int i = 0; i &lt 2000; ++i) {
            acc[2] += teste2 (array);
        }
        for (int i = 0; i &lt 2000; ++i) {
            acc[3] += teste3 (array);
        }
        for (int i = 0; i &lt 2000; ++i) {
            acc[4] += teste4 (array);
        }
        for (int i = 0; i &lt 2000; ++i) {
            acc[5] += teste5 (array);
        }
        System.out.println ("Teste 1: média = " + (acc[1] / 2000.0) + " ms");
        System.out.println ("Teste 2: média = " + (acc[2] / 2000.0) + " ms");
        System.out.println ("Teste 3: média = " + (acc[3] / 2000.0) + " ms");
        System.out.println ("Teste 4: média = " + (acc[4] / 2000.0) + " ms");
        System.out.println ("Teste 5: média = " + (acc[5] / 2000.0) + " ms");
    }

    public static void main(String[] args) {
        // Warm-up
        System.out.println ("Efetuando o warm-up");
        warmup();
        // Teste real
        System.out.println ("Efetuando o teste real");
        teste();
    }
}

Resultados:

C&gt\jdk1.6.0\bin\java -Xms128m -Xmx128m -XX:+AggressiveOpts
-server -cp . TesteLoop
Efetuando o warm-up
Efetuando o teste real
Teste 1: média = 4.1245 ms
Teste 2: média = 4.422 ms
Teste 3: média = 4.148 ms
Teste 4: média = 4.203 ms
Teste 5: média = 4.195 ms

Ou seja, sair de um loop com uma exception não é um bom negócio.

[quote=thingol]Os seus exemplos são terríveis :stuck_out_tongue:

No primeiro caso: tanto faz. No segundo caso: tanto faz.

[/quote]

HuahuHUHAUhuAHUhu! :smiley:

Foi apenas um exemplo, sabia que ia dar na mesma, coloquei para que o pessoal entende-se até aonde queria chegar…

Sei que o meu objetivo é mirabolante, porém não custa tentar…

Sobre a exception … não apenas em um loop mas em qualquer parte do código se concluir que lançar uma exception demora mais!!!

Tecnoage to esperando esse material com ansiedade!

thingol belo exemplo … é bem por ai meu raciocínio… to modificando o código e colocando um time para verificar o que eu to modificando, talvez milésimos de segundos ou nanossegundos em apenas um rotina não faça diferença, porém são muitas classes que rodam muitas vezes diariamente…

Abraços…