2015-02-04 2 views
2
import java.util.ArrayList; 
import java.util.List; 


public class HowFastMulticoreProgramming { 

    public static void main(String[] args) { 

     //Produce Date 
     List<String> data=new ArrayList<String>(); 
     for(int i=0;i<10000;i++){ 
      data.add(""+i); 
     } 


     /*Style Java 1.4*/ 
     long beforeStartJDK14=System.currentTimeMillis(); 
     for (int i = 0; i < data.size(); i++) { 
      System.out.println(data.get(i)); 
     } 
     long afterPrintJDK14=System.currentTimeMillis(); 

     /*Style Java 1.5*/ 
     long beforeStartJDK15=System.currentTimeMillis(); 
     for (String s : data) { 
      System.out.println(s); 
     } 
     long afterPrintJDK15=System.currentTimeMillis(); 

     long beforeStartJDK18=System.currentTimeMillis(); 
     data.parallelStream().forEach(string-> System.out.println(string)); 
     long afterPrintJDK18=System.currentTimeMillis(); 

     System.out.println("Milis Need JDK 1.4 : "+(afterPrintJDK14-beforeStartJDK14)); 
     System.out.println("Milis Need JDK 1.5 : "+(afterPrintJDK15-beforeStartJDK15)); 
     System.out.println("Milis Need JDK 1.8 : "+(afterPrintJDK18-beforeStartJDK18)); 

    } 
} 

나는 목록을 인쇄하기 위해 3 가지 스타일 (JDK 버전 기준)이 있습니다. 그러나 모든 스타일은 완료 할 시간이 필요합니다. 사실 람다와 함께 스타일 jdk 8 .. 어떤 스타일과 큰 neeeded. 어째서?간단한 인쇄 목록으로 Java 8 속도 테스트

이것은이 코드를 실행 한 결과입니다. 939

나는 누군가가이 질문에 대답 할 수 있기를 바랍니다 : 76 시간 Milis JDK 1.8이 필요 : 85 시간 Milis JDK 1.5이 필요 : 시간 Milis는 JDK 1.4이 필요합니다.

+0

Java 8 버전은 병렬로 수행되므로 스레드 생성으로 인해 성능이 저하 될 수 있습니다. parrallel 작업없이 다른 버전을 만듭니다. – meskobalazs

+4

http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – reto

+1

가능한 복제본 [Java 8의 스트림 : 왜 병렬 스트림의 속도가 더 느립니까?]를 읽어보십시오. (http://stackoverflow.com/questions/23170832/java-8s-streams-why-parallel-stream-is-slower) –

답변

4

이 비교는 완전히 의미가 없습니다.

첫 번째 두 가지 변형은 완전히 I/O 시간에 의해 좌우됩니다. 출력되는 것은 무엇이든간에 모든 루프가 일반적으로됩니다. 당신이 반복하는 방식은 아마 잡음에 영향을 미칩니다. I/O가 느립니다.

그러나 세 번째 변형에서 수행하는 것과 같이 느리지는 않습니다. 세 번째 변종에서는 parallelStream()을 사용합니다. 이는 Java8의 조인/포크 기능을 호출합니다. 여러 스레드를 생성하고 있습니다 (CPU 코어를 보유한 것만 큼). 이러한 스레드를 통해 목록 요소를 작성하는 작업을 배포하고 있습니다. 그러면 이 동일한 스레드에 쓰여지고 은 작업을 직렬화합니다. 즉, 스레드를 만들고 배포하는 모든 작업을 수행 한 후에는 여전히 하나의 작업 만 수행하고있는 것입니다. 이제는 대규모 동기화 오버 헤드가 발생합니다.

재미있는 비교를하려면 데이터를 다른 데이터로 변환해야하며 작업 관리 오버 헤드가 발생하지 않도록 각 항목에 간단한 작업 (동기화는 아님)을 수행해야합니다. 계산 시간을 절약하십시오.

그동안 parallelStream() 대신 stream()을 사용해보세요. 그러면 다른 두 변종의 대략 시간까지 시간이 걸릴 것입니다. 그렇다고해서 더 이상 의미있는 것은 아닙니다.

1

면책 조항 : 마이크로 벤치 마크 및 마이크로 벤치 마크 are hard to do을 수행하고 있습니다. 내 약간 변경된 코드는 그 자체만으로도 충분한 문제가 있다고 확신합니다.

parallelStream()은 약간의 시작 시간이 필요하며, 오버 헤드가 많으므로 Thread이 가져오고 있습니다.

또 다른 문제는 각 항목에 대해 System.out.println()을 수행하고 있다는 것입니다. 즉, IO이기 때문에 반복 외에도 많은 것을 측정하고 있습니다. 이는 여러 스레드에서 하나의 스트림 (System.out)에 액세스 할 때 특히 문제가됩니다.

인쇄 문을 지우면 JVM이 루프를 건너 뛰기 때문에 모든 요소를 ​​합계에 추가하는 것입니다. 꽤 빠르지 않으면 최적화되지 않을 것입니다.

100,000,000의 목록 크기 다음 예제를 실행

, 나는 이러한 결과를 얻을 수 (만드는 데 약 1 분 소요) :

Milis Need JDK 1.4 : 190 
Milis Need JDK 1.5 : 681 
Milis Need JDK 1.8 : 198 

내 코드 : 그

@Test 
public void testIterationSpeed() { 
    List<Integer> data = new ArrayList<>(); 
    for (int i = 0; i < 100000000; i++) { 
     data.add(i); 
    } 

    /*Style Java 1.4*/ 
    long dummySum = 0; 
    long beforeStartJDK14 = System.currentTimeMillis(); 

    for (int i = 0; i < data.size(); i++) { 
     dummySum += data.get(i); 
    } 
    long afterPrintJDK14 = System.currentTimeMillis(); 

    /*Style Java 1.5*/ 
    dummySum = 0; 
    long beforeStartJDK15 = System.currentTimeMillis(); 

    for (Integer i : data) { 
     dummySum += i; 
    } 
    long afterPrintJDK15 = System.currentTimeMillis(); 

    /* Java 1.8 */ 
    long beforeStartJDK18 = System.currentTimeMillis(); 
    data.parallelStream().mapToLong(i -> i).sum(); 
    long afterPrintJDK18 = System.currentTimeMillis(); 

    System.out.println("Milis Need JDK 1.4 : " + (afterPrintJDK14 - beforeStartJDK14)); 
    System.out.println("Milis Need JDK 1.5 : " + (afterPrintJDK15 - beforeStartJDK15)); 
    System.out.println("Milis Need JDK 1.8 : " + (afterPrintJDK18 - beforeStartJDK18)); 

} 

참고 경우 목록 크기를 줄이면 parallelStream의 오버 헤드가 너무 많아집니다.이 사실을 Amdahl's Law라고도합니다. 합계를 만드는 과정은 다른 루프와 다릅니다. 따라서 좋은 벤치 마크는 아닙니다.

흥미로운 점은 각각의 경우가이 경우보다 느리다는 것입니다.