Pergunta

Eu tenho um teste de unidade muito simples que apenas aloca muitas cordas:

public class AllocationSpeedTest extends TestCase {

    public void testAllocation() throws Exception {

        for (int i = 0; i < 1000; i++) {
            long startTime = System.currentTimeMillis();
            String a = "dummy";
            for (int j = 0; j < 1000; j++) {
                a += "allocation driven";
            }
            System.out.println(i + ": " + (System.currentTimeMillis() - startTime) + "ms " + a.length());
        }

    }

}

No meu PC Windows (Intel Core Duo, 2,2 GHz, 2 GB), isso imprime em média:

...
71: 47ms 17005
72: 47ms 17005
73: 46ms 17005
74: 47ms 17005
75: 47ms 17005
76: 47ms 17005
77: 47ms 17005
78: 47ms 17005
79: 47ms 17005
80: 62ms 17005
81: 47ms 17005
...

Sunos (5.10 Genic_138888-03 SUN4V SPARC SUNW, SPARC-Enterprise-T5120):

...
786: 227ms 17005
787: 294ms 17005
788: 300ms 17005
789: 224ms 17005
790: 260ms 17005
791: 242ms 17005
792: 263ms 17005
793: 287ms 17005
794: 219ms 17005
795: 279ms 17005
796: 278ms 17005
797: 231ms 17005
798: 291ms 17005
799: 246ms 17005
800: 327ms 17005
...

A versão JDK é 1.4.2_18 em ambas as máquinas. Os parâmetros da JVM são os mesmos e são:

–server –Xmx256m –Xms256m

Alguém pode explicar por que o Sun Super Server é mais lento?

(http://www.sun.com/servers/coolthreads/t5120/performance.xml)

Foi útil?

Solução

A CPU é de fato mais lenta no SPARC (1,2 GHz) e, conforme respondido por um dos engenheiros do Sun T2, é comum 3 vezes mais lento para aplicação de thread único que os processadores Intel modernos. No entanto, ele também afirmou que em um ambiente multithread SPARC deve ser mais rápido.

Fiz um teste multithread usando a biblioteca Groboutils e testei alocações (através de concatenações) e cálculos simples (a += j*j) para testar o processador. E eu tenho os seguintes resultados:

1 thread : Intel : Calculations test : 43ms
100 threads : Intel : Calculations test : 225ms

1 thread : Intel : Allocations test : 35ms
100 threads : Intel : Allocations test : 1754ms

1 thread : SPARC : Calculations test : 197ms
100 threads : SPARC : Calculations test : 261ms

1 thread : SPARC : Allocations test : 236ms
100 threads : SPARC : Allocations test : 1517ms

A SPARC mostra seu poder aqui superando a Intel em 100 threads.

Aqui vai o teste de cálculo multithread:

import java.util.ArrayList;
import java.util.List;

import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;
import junit.framework.TestCase;

public class TM1_CalculationSpeedTest extends TestCase {

    public void testCalculation() throws Throwable {

        List threads = new ArrayList();
        for (int i = 0; i < 100; i++) {
            threads.add(new Requester());
        }
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner((TestRunnable[]) threads.toArray(new TestRunnable[threads.size()]));
        mttr.runTestRunnables(2 * 60 * 1000);

    }

    public class Requester extends TestRunnable {

        public void runTest() throws Exception {
            long startTime = System.currentTimeMillis();
            long a = 0;
            for (int j = 0; j < 10000000; j++) {
                a += j * j;
            }
            long endTime = System.currentTimeMillis();
            System.out.println(this + ": " + (endTime - startTime) + "ms " + a);
        }

    }

}

Aqui vai o teste de alocação multithread:

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;
import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;

public class TM2_AllocationSpeedTest extends TestCase {

    public void testAllocation() throws Throwable {

        List threads = new ArrayList();
        for (int i = 0; i < 100; i++) {
            threads.add(new Requester());   
        }
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner((TestRunnable[]) threads.toArray(new TestRunnable[threads.size()]));
        mttr.runTestRunnables(2 * 60 * 1000);

    }

    public class Requester extends TestRunnable {

        public void runTest() throws Exception {
            long startTime = System.currentTimeMillis();
            String a = "dummy";
            for (int j = 0; j < 1000; j++) {
                a += "allocation driven";
            }
            long endTime = System.currentTimeMillis();
            System.out.println(this + ": " + (endTime - startTime) + "ms " + a.length());
        }

    }

}

Outras dicas

Entendo que as máquinas baseadas em Ultrasparc T2 têm como objetivo o desempenho por watt, em vez de um desempenho bruto. Você pode tentar dividir o tempo de alocação pelo consumo de energia e ver que tipo de números obtém. :)

Existe uma razão pela qual você está executando 1.4.2 em vez de 1.6?

O hardware Sunos é mais lento e a VM pode ser um pouco mais lenta também.

Eu não acho que isso esteja medindo a alocação de memória. Para começar, há muita cópia de personagem acontecendo a += "allocation driven";. Mas eu suspeito que o verdadeiro gargalo está em obter a saída de System.out.println(...) Através das camadas de rede do aplicativo no servidor Sun para sua estação de trabalho remota.

Como experimento, tente multiplicar a contagem de loops internos por 10 e 100 e veja se isso "acelera" o servidor Sun em relação à sua estação de trabalho.

Outra coisa que você pode tentar é mover o loop interno para um procedimento separado. É possível que, já que você está fazendo todo o trabalho em uma invocação de main, o compilador JIT nunca tem a chance de compilá -lo.

("Micro-benchmarks" artificiais como esse são sempre suscetíveis a efeitos como esses. Eu tendem a desconfiar deles.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top