Análise do custo de um comando

6 respostas
Calvin

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

6 Respostas

T

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…

Roger75

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”.

Pedrosa

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

T

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.

T

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.

Calvin

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

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

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…

Criado 21 de maio de 2007
Ultima resposta 22 de mai. de 2007
Respostas 6
Participantes 5