1

The following Java method is meant to print the number i by nLoopsPerSecond times per second for seconds seconds:

public void test(int nLoopsPerSecond, int seconds) {
    double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
    long startTime = System.currentTimeMillis();
    long currentTime;
    int i = 0;
    while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
        System.out.println(i++);
        while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
    }
}

With the following call:

test(1000,1);

I expect this method to do the System.out.println(i++); 1,000 times, but I only got 63.

When I try to see how many seconds it actually use per loop with this code

public void test(int nLoopsPerSecond, int seconds) {
    double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
    long startTime = System.currentTimeMillis();
    long currentTime;
    int i = 0;
    while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
        while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
        System.out.println(System.currentTimeMillis() - currentTime);
    }
}

I expect it to print 1 milliseconds each loop, but it prints 15 or 16 milliseconds.

Please suggest what is wrong in my code.

asinkxcoswt
  • 2,252
  • 5
  • 29
  • 57
  • I suggest you put exact code that you are trying to execute. This will not compile. For example - what is `seccond`? Also- why do you have while loop inside while loop? – V_Singh Jun 21 '15 at 16:28
  • 4
    `System.out.println` will likely not be able to output to the console 1000 times per second. Rather much less. – Jite Jun 21 '15 at 16:29
  • As an alternative to using `printlln()` in the loop(s) you could fill a datastructure with the values you wish to print then display them after the loop all at once. Try an `ArrayList` constructed to already be sized at 1000 or try an old school int array sized at 1000. – candied_orange Jun 21 '15 at 16:34
  • @jite I don't think so, because when I remove the inner `while`, it prints up to 90,000++ – asinkxcoswt Jun 21 '15 at 16:41
  • 3
    For your purposes it looks like `System.nanoTime()` would be more useful since you are not measuring time since the epoch. http://stackoverflow.com/a/351571/1493294 – candied_orange Jun 21 '15 at 16:43
  • Is your goal here to measure how long it takes certain code to execute or are you trying to fire an event every thousandth of a second? – candied_orange Jun 21 '15 at 16:52
  • changing to `System.nanoTime()` solves the problem, thank you all :D – asinkxcoswt Jun 21 '15 at 16:54
  • @CandiedOrange I am attempting the latter, I am going to do a load test my web service. – asinkxcoswt Jun 21 '15 at 16:55

4 Answers4

7

Are you running on Windows, perhaps? System.currentTimeMillis() consults the underlying operating system clock, which is only 60Hz on many versions of Windows.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • [From the API docs](http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis()): "Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds." – that other guy Jun 21 '15 at 16:49
  • I changed from `System.currentTimeMillis()` to `System.nanoTime()` and it solves. And for the reason, I think you are correct. and yes I am running on Windows (I try both Windows Xp, and Windows 8.1) – asinkxcoswt Jun 21 '15 at 17:08
1

Try System.nanoTime() since you are not measuring time since the epoch. System.currentTimeMillis vs System.nanoTime

Community
  • 1
  • 1
candied_orange
  • 7,036
  • 2
  • 28
  • 62
0

That's probably because the processing takes up some time. The processor does not solely dedicate its time to the execution of your program, it performs several other functions in the background. So you might get different results based on the processor load.

0

Your output console is not fast enough. You do not mention how you run your test and where the output goes. The speed of the terminal and buffers (not) used will limit how fast can the program output data. If running unbuffered, your program will always have to wait, until the new line is printed on screen. If the console waits for screen redraw and screen is redrawn at 60Hz, you've got your 16ms/line and about 60 lines per second.

Running your code without inner loop inside IntelliJ Idea, I get about 140.000 lines per second (and Idea warns me, that it is not displaying every line, as my output is too fast).

With the inner loop, I get about 800-900 lines. That happens because the process may be scheduled out of cpu, or blocked because of something else, like swapping. (If I simplify a lot, usually desktop OSes schedule in 1ms granularity.)

Fox
  • 2,348
  • 19
  • 19
  • I am running on Windows XP with CPU Intell i5, but when I remove the inner while loop, it prints 90,000++, so I believe it is not because of the delay from printing to console, anyways thanks :D – asinkxcoswt Jun 21 '15 at 17:04