3

I was trying a example code with spring. And a part of code is like below;

private List<Point> points;
long timeTakeninMilis = System.currentTimeMillis();

public List<Point> getPoints() {
    return points;
}

public void setPoints(List<Point> points) {
    this.points = points;
}

public void drawJava8() {
    points.stream().forEachOrdered(
            point -> System.out.println("Point : (" + point.getX() + ", "
                    + point.getY() + ")"));
    System.out.println("Total Time Taken drawJava8(): "
            + (System.currentTimeMillis() - timeTakeninMilis)
            + " miliseconds");
}

public void draw() {
    for (Point point : points) {
        System.out.println("Point = (" + point.getX() + ", " + point.getY()
                + " )");

    }
    System.out.println("Total Time Taken draw(): "
            + (System.currentTimeMillis() - timeTakeninMilis)
            + " miliseconds");
}

The OUTPUT,

  Jun 30, 2015 11:30:53 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
  INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7daf6ecc: startup date [Tue Jun 30 11:30:53 IST 2015]; root of context hierarchy
  Jun 30, 2015 11:30:53 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
  INFO: Loading XML bean definitions from class path resource [spring.xml]
  Point = (0, 0 )
  Point = (-50, 0 )
  Point = (0, 50 )
  Total Time Taken draw(): 70 miliseconds
  Point : (0, 0)
  Point : (-50, 0)
  Point : (0, 50)
  Total Time Taken drawJava8(): 124 miliseconds
  Jun 30, 2015 11:30:54 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
  INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@7daf6ecc: startup date [Tue Jun 30 11:30:53 IST 2015]; root of context hierarchy

Why it is taking more time? Or i am doing something wrong?

I was expecting it to be faster or of similar speed... Please help me understand what is the benefit of the Lambda Expressions?

INFO: I did it in two different programs. Times are taken from those. I merged them here to make it short.

Bee
  • 12,251
  • 11
  • 46
  • 73
Rajkishan Swami
  • 3,569
  • 10
  • 48
  • 68
  • By looking your output you are calling drawJava() first and drawJava8() later. Are you resetting the variable timeTakeninMilis with the current time before calling drawJava8()? – Madhavi Balan Jun 30 '15 at 06:30
  • 3
    Writing a benchmark for java is hard; the jvm is continutally analysing your code and optimising it. Have a look at https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – beresfordt Jun 30 '15 at 06:34
  • @Madhavi Balan: I did it in two different program. Just merged them while posting so that it will be short as they are simple programs. – Rajkishan Swami Jun 30 '15 at 06:40
  • 1
    Did you try `forEach` instead of `forEachOrdered` ? But as @beresfordt said: Benchmarking is not that easily done. One step closer to a valid result would be to use much more points and to run the test many many times, so you have some statistical value. All you can say now is that this one single time, execution of the java 8 method was much slower. But this could have more reasons than the code itself. – Fildor Jun 30 '15 at 06:53
  • 1
    @beresfordt : Wow... a lot of useful information that thread have. Thank you very much. – Rajkishan Swami Jun 30 '15 at 06:53
  • @Fildor : Yes i did. Found no difference. Time is always around 122ms. Sometimes 2-3ms more or less. Actually i tried this in a medicore sized project and found stream().forEach() is actually taking 1.5-2 Seconds more. Ran the code many times. I think you are right about the benchmark stuff as i dont have much experience in java. May be some other factors are in play here. – Rajkishan Swami Jun 30 '15 at 06:56
  • @Rajkishan - Assuming it is not the case mentioned by @Madhavi Balan, this behavior could be because of `forEach` vs. `forEachOrdered` - how many CPU cores do you have and what is the size of points you are dealing with here ? – ring bearer Jun 30 '15 at 07:00
  • @ringbearer : Dual Core i3(4 threads). Its a very small and simple program with 3 points. Found no diff between the two loops ( forEach and forEachOrdered) – Rajkishan Swami Jun 30 '15 at 07:02
  • Can you rerun the test in a loop ? meaning without shutting down the application after two checks. So you need to repeat the bench marking in a loop as: `for (i=0;i<100;i++){draw(); drawJava8();}` and compare the results? – ring bearer Jun 30 '15 at 07:07
  • @ringbearer : That was interesting. Normal Loop takes 14-16 millisecs to complete 100 but streamed loop takes 9-11 millisecs to finish 100 but first iteration completes 60- 70 ms late. – Rajkishan Swami Jun 30 '15 at 07:14
  • So, @Rajkishan - never underestimate what JIT compiler can do for you, and it is not a good idea to jump to performance conclusions without repeated tests in a running JVM. So there is a slight performance benefit with `stream().forEach` – ring bearer Jun 30 '15 at 07:16
  • @ringbearer : Can you post you answers in a separate post so i can mark is solved. You helped me learn a new thing today. Thank You. A question, how you insert code block in comments? – Rajkishan Swami Jun 30 '15 at 07:19

1 Answers1

3

Adding this as an analysis per original poster's request.

We can not really predict the sophisticated analysis and transformation that the modern JIT compiler performs on running code. Hence while benchmarking items such as these, you should not conclude it just by running two method calls.

Instead, create various sample input sets (boundary cases) and check the perofmance by repeatedly calling your test cases without shutting down JVM. In this case for example :

for (int i=0;i<100;i++){draw(); drawJava8();}

Once you have the results, find out average execution and you can safely ignore first execution result as it might not have had optimizations.

So the conclusion you have drawn from your tests is not completely correct.

ring bearer
  • 20,383
  • 7
  • 59
  • 72