5

I have the following code..

 public static void main(String[] args) { int i = 1234; int j = 1234; int k = 4321; long l1 = System.nanoTime(); if (i == j) { System.out.println("equal"); } System.out.println(System.nanoTime() - l1); l1 = System.nanoTime(); if (i != k) { System.out.println("equal"); } System.out.println(System.nanoTime() - l1); l1 = System.nanoTime(); if (i == k) { System.out.println("equal"); } System.out.println(System.nanoTime() - l1); l1 = System.nanoTime(); if (i != j) { System.out.println("equal"); } System.out.println(System.nanoTime() - l1); } 

Now when I run this program, the OPs are:

1. equal 190295 equal 22237 427 0 2. equal 156512 equal 18388 0 428 3. equal 155656 equal 20099 0 0 

My question : how is it that the time taken for execution is "0" ??.. If the compiler does some optimization, then why doesn't it do it always?. I think the "0" is because that statement wasnt executed by the compiler.

3
  • 2
    You need to measure doing this a few million times and take the average- just one time is virtually impossible unless you control the clock and scheduling. (And then make sure the JVM doesn't optimize the loop, micro benchmarking in java is not easy). System.nanoTime() might give you a time with nano second precision, but it does not have nano-second accuracy - what accurancy you get depends on the hardware clock you have, and then you need to account for scheduling jittering. Commented Jan 6, 2014 at 10:33
  • So.. you mean to say that the code in the last 2 if conditions is executing always?? Commented Jan 6, 2014 at 10:37
  • 2
    Imagine you have a clock that updates once every microsecond. Then you read that clock with System.nanoTime(). Now obviously you cannot measure anything precisely that takes less than 1 microsecond even if System.nanoTime() returns a timestamp that gives you nanoseconds. This becomes even harder when you run on a general purpose operating system, as the OS might suddenly decide to do something else for a little while, just inbetween the start and end of your time measurements. The accuracy of System.nanoTime depends on your platform/OS/etc. Commented Jan 6, 2014 at 10:41

2 Answers 2

4

The actual reason

The output varies and is sometimes 0, sometimes not as you already noticed. The likeliest issue is that System.nanoTime:

provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes)

So 0 does not necessarily mean 0 - it just means: less than the smallest "tick" that your clock can represent.


Can we be sure that the code hasn't been optimised by the compiler?

If you use the -XX:+PrintCompilation flag when running the program, you will get an output similar to below. If you read carefully, you will notice that main has not been compiled by the JIT yet (which makes sense since it is not really hot) - so your code can't have been optimised away.

 62 1 3 java.lang.String::hashCode (55 bytes) 62 3 3 java.lang.String::indexOf (70 bytes) 63 2 3 java.lang.String::charAt (29 bytes) 65 4 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (16 bytes) 65 5 3 java.lang.Object::<init> (1 bytes) 65 8 n 0 java.lang.System::arraycopy (native) (static) 65 6 3 java.lang.CharacterData::of (120 bytes) 66 7 3 java.lang.CharacterDataLatin1::getProperties (11 bytes) 66 9 3 java.lang.Character::toLowerCase (9 bytes) 66 10 3 java.lang.CharacterDataLatin1::toLowerCase (39 bytes) 66 11 3 java.lang.String::length (6 bytes) 66 12 3 java.lang.AbstractStringBuilder::append (29 bytes) 66 13 3 java.lang.StringBuilder::append (8 bytes) 67 14 3 java.io.WinNTFileSystem::isSlash (18 bytes) 67 15 s 3 java.lang.StringBuffer::append (13 bytes) 67 16 3 java.lang.String::<init> (62 bytes) 68 17 3 java.lang.String::equals (81 bytes) 68 18 1 java.lang.Object::<init> (1 bytes) 68 5 3 java.lang.Object::<init> (1 bytes) made not entrant 68 19 3 java.lang.String::getChars (62 bytes) 74 20 3 java.lang.Math::min (11 bytes) 74 21 3 java.io.BufferedInputStream::getBufIfOpen (21 bytes) 74 22 3 java.util.Arrays::copyOfRange (63 bytes) 75 24 3 java.io.DataInputStream::readUTF (501 bytes) 76 29 3 java.io.DataInputStream::readFully (63 bytes) 77 26 s 3 java.io.BufferedInputStream::read (113 bytes) 77 23 s 3 java.io.BufferedInputStream::read (49 bytes) 77 30 3 java.io.DataInputStream::readShort (40 bytes) 78 25 3 java.io.DataInputStream::readUTF (5 bytes) 78 27 3 java.io.BufferedInputStream::read1 (108 bytes) 78 28 3 java.io.DataInputStream::readUnsignedShort (39 bytes) 78 31 3 java.util.HashMap::hash (20 bytes) 79 32 s 3 java.io.ByteArrayInputStream::read (36 bytes) 79 33 3 java.io.DataInputStream::readByte (23 bytes) 79 34 3 sun.util.calendar.ZoneInfoFile::indexOf (32 bytes) 80 35 3 java.util.zip.CRC32::update (16 bytes) 81 36 n 0 java.util.zip.CRC32::updateBytes (native) (static) 81 37 3 sun.util.calendar.ZoneInfoFile$Checksum::update (39 bytes) 83 39 3 java.util.HashMap::putVal (300 bytes) 84 41 4 java.lang.String::equals (81 bytes) 84 38 3 java.util.HashMap::put (13 bytes) 84 42 ! 3 java.io.BufferedReader::readLine (304 bytes) 86 43 3 java.util.LinkedList::indexOf (73 bytes) 86 44 3 java.util.HashMap::getNode (148 bytes) 86 46 3 java.util.HashMap::get (23 bytes) 87 47 3 sun.misc.JarIndex::addToList (59 bytes) 87 17 3 java.lang.String::equals (81 bytes) made not entrant 87 45 3 java.util.HashMap$Node::<init> (26 bytes) 87 40 3 java.util.HashMap::newNode (13 bytes) 88 48 4 java.lang.String::charAt (29 bytes) 88 2 3 java.lang.String::charAt (29 bytes) made not entrant 92 49 3 java.lang.AbstractStringBuilder::append (50 bytes) 92 50 3 java.lang.System::getSecurityManager (4 bytes) 93 51 3 java.lang.Math::max (11 bytes) 93 52 3 java.lang.String::endsWith (17 bytes) 96 53 3 java.lang.StringBuilder::append (8 bytes) equal 189546 equal 17232 367 0 97 54 1 java.nio.Buffer::position (5 bytes) 
Sign up to request clarification or add additional context in comments.

3 Comments

So.. you mean to say that the code in the last 2 if conditions is executing always???..
@TheLostMind yes they do.
Hi.. Thanks for the answer... can you tell me how I can use "-XX:+PrintCompilation" flag in eclipse?
2

Run > run configuration > arguments > VM arguments
input as follows: -server -XX:+PrintCompilation -XX:+CITime

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.