-2

Given the complete source code below, please explain why every execution of this program in Eclipse results in time in do1() greater than time in do2() by 2~3 milliseconds.

Does the JVM need to "warm up"?

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

public class Question {
    public static void main(String[] args) {
        do1();
        do2();
    }

    public static void do1() {
        O obj = new O();
        Thread t = new Thread(() -> IntStream.range(0, 100000)
                    .forEach(e -> obj.incrementN()));

        long start = System.currentTimeMillis();

        t.start();

        try {
            t.join();
        } catch (InterruptedException e1) {

        }

        float time = (System.currentTimeMillis()-start)/1000F;

        System.out.println(time);
        System.out.println(obj);
        System.out.println();
    }

    public static void do2() {
        O obj = new O();
        Thread t = new Thread(() -> IntStream.range(0, 100000)
                    .forEach(e -> obj.incrementN()));

        long start = System.currentTimeMillis();

        t.start();

        try {
            t.join();
        } catch (InterruptedException e1) {

        }

        float time = (System.currentTimeMillis()-start)/1000F;

        System.out.println(time);
        System.out.println(obj);
    }
}

class O {
    private AtomicInteger n = new AtomicInteger(0);

    public void incrementN() {
        n.getAndIncrement();
    }

    @Override
    public String toString() {
        return ""+n.get();
    }
}

Sample output:

0.003
100000

0.001
100000
blackr1234
  • 1,420
  • 12
  • 23
  • 1
    It would be more accurate if you did this let's say a thousand times, and then took the average results.. This might just be randomness. – RaminS Mar 03 '16 at 20:13
  • 2
    And yes, the JVM needs to warm-up, since the heavily used code is compiled to native code via the JIT system. – Xvolks Mar 03 '16 at 20:15
  • its just a one time result, an average could give more accurate results. It can be loading time of class O which is done once in do1(), then not taking time in do2(). – Gurpreet Singh Mar 03 '16 at 20:16
  • I have run this program many times and the ``time`` variable in ``do2()`` is always less than the ``time`` variable in ``do1()``. If ``do1()`` and ``do2()`` are placed within a loop under ``main()`` then yes, all results are about 1 ms, except for the first one or two which give 2~4 ms. @Gurpreet Singh Time calculation starts after ``new O()``, not sure if this matters. – blackr1234 Mar 03 '16 at 20:29
  • 1
    http://stackoverflow.com/questions/4345999/avoid-jvm-warmup – Jean-François Savard Mar 03 '16 at 20:44
  • I would ignore the first 2 - 10 seconds to ensure the application has warmed up. – Peter Lawrey Mar 04 '16 at 16:22

1 Answers1

0

This is really a too short timespan to really determine what causes do1() to execute longer than do2().

Some factors could be:

  • Garbage collector kicking in (Your o and t Objects for example are created, the pointer to their memory location (on the stack) is destroyed when the method do1() is left, but the memory itself is freed by the garbage collector)

  • Eclipse doing some analysing stuff somewhere in between (measuring variables, time or something)

  • As you suggested, the JVM could also do some warmup stuff.

  • Unlucky CPU scheduling. It could be that do1() gets some more CPU time than do2(), for whatever reason

you could do some stuff before you call do1() (or sleep), then call do1(), then wait again and call do2() and measure again. Or you could increase the amount of time do1() and do2() consume.

Also, your do1() and do2() methods are (except for the name and the println in do1()) exactly the same, so what happens when you just call do1() 2 times?

blackr1234
  • 1,420
  • 12
  • 23