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));

    }
}

I Have 3 styles to print List (based on JDK version). but every Styles need time to complete. In fact style jdk 8 with lambdas.. neeeded greater with any styles. how come?

This is what I get from running this code; Time Milis Need JDK 1.4 : 85 Time Milis Need JDK 1.5 : 76 Time Milis Need JDK 1.8 : 939

I hope somebody can answer this question.

  • The Java 8 version is done in parallel, so the thread creation could kill the performance. Make another version without parrallel operations. – meskobalazs Feb 04 '15 at 10:15
  • 4
    Please read http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – reto Feb 04 '15 at 10:20
  • 1
    possible duplicate of [Java 8's streams: why parallel stream is slower?](http://stackoverflow.com/questions/23170832/java-8s-streams-why-parallel-stream-is-slower) –  Feb 04 '15 at 10:25

2 Answers2

4

This comparison is completely meaningless.

First, the first two variants are completely dominated by I/O time. Any loop over anything whatsoever that does output will usually be. The way you iterate has an effect that is probably in the noise. I/O is slow.

But it is not quite as slow as what you're doing in the third variant. In the third variant, you use parallelStream(), which invokes the join/fork machinery of Java8. You're spawning multiple threads (probably as many as you have CPU cores). You're distributing the tasks to write the list elements over these threads. You're then writing to the same stream from each of these threads, which serializes their operation, i.e. after you went through all the work of creating the threads and distributing tasks, you're still only doing one thing at a time, plus you're now also incurring massive synchronization overhead.

If you want to do an interesting comparison, you need to transform data into some other data, and you need to do non-trivial (but not synchronized) work on each item, so that the task management overhead doesn't swamp the computation time.

In the meantime, try using stream() instead of parallelStream(). That should get the time down to roughly the time of the other two variants. That doesn't make it any more meaningful though.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
1

Disclaimer: You are doing micro benchmarks, and micro benchmarks are hard to do. I'm sure my slightly changed code below has enough problems by itself.

A parallelStream() needs some startup time, and you have the overhead multiple Threads are bringing with them.

Another problem is, that you are doing System.out.println() for each item - it's IO, so you are measuring a whole lot besides the iteration too. That's especially a problem when you are accessing one stream (System.out) from multiple threads.

If you delete your print statements, the JVM will problably just skip the loops, that's why I'm just adding every element to a sum. Should be quite fast, and it won't get optimized away.

When running the following example with a list size of 100000000 (takes about one minute to create), I get these results:

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

My code:

@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));

}

Note that if you decrease the list size, the overhead of the parallelStream will be too much - this fact is also called Amdahl's Law. And the process of creating the sum is different than in the other loops, so it's not a good benchmark.

What's interesting is that for each is slower than for in this case.

Community
  • 1
  • 1
stuXnet
  • 4,309
  • 3
  • 22
  • 31