This discussion is archived
11 Replies Latest reply: Apr 9, 2013 12:27 PM by 1001190 RSS

A more precise alternative to Thread.sleep()

1001190 Newbie
Currently Being Moderated
So I'm designing a multi player game (server/client). I am using Thread.sleep() in a class that is used specifically for tracking the move speed of a specific character. The problem with this is sleep() only pauses for milliseconds and is very processor dependent. I've tried making a mini spinlock (for sleeping in microseconds) and was successful with this and it was very accurate. However, it doesn't clock the same on the server as the clients. (Resulting in movement on the client being slower than movement on my server--and then chops when the server updates the sync). I believe I have thought up a way (in using the spin lock way of handling it) to have the client adjust for the difference of the sleeps when it loads a character, and I think that might work well enough. But I was curious if anyone knew a better way of doing sleep() accurately and in microseconds, or some non processor depending way of sleeping?
  • 1. Re: A more precise alternative to Thread.sleep()
    EJP Guru
    Currently Being Moderated
    You might have to do something with a spin loop with Thread.sleep(0) in it, or Thread.yield(), and measure the elapsed time with System.nanoTime().

    [Another issue with Thread.sleep() is that the timer used on Windows only resolves to 15-16ms.]
  • 2. Re: A more precise alternative to Thread.sleep()
    gimbal2 Guru
    Currently Being Moderated
    Start an endless sleeping thread - as long as at least one thread is asleep (and the sleeptime is not a multiple of 10) the windows JVM puts the timer precision at 1ms, in line with other OSes which have that precision by default.
  • 3. Re: A more precise alternative to Thread.sleep()
    EJP Guru
    Currently Being Moderated
    Is that really true? Where on earth do they get these ideas from?
  • 4. Re: A more precise alternative to Thread.sleep()
    gimbal2 Guru
    Currently Being Moderated
    EJP wrote:
    Is that really true? Where on earth do they get these ideas from?
    Confusingly, we've had this discussion before and I remember that the last time you even tested it out :) But that may have been Jverd_sock_puppet now that I think about it.

    The answer is: a bug report dealing with a command line switch that is supposed to do it, but was implemented bugged so it doesn't work.

    http://bugs.sun.com/view_bug.do?bug_id=6435126

    See the work around!
  • 5. Re: A more precise alternative to Thread.sleep()
    jtahlborn Expert
    Currently Being Moderated
    EJP wrote:
    Is that really true? Where on earth do they get these ideas from?
    Unfortunately, it is.

    https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks

    TL;DR, timers on windows are a mess. even the technique gimbal2 mentioned doesn't always "work". In our product, we actually abandoned using the jdk ScheduledExecutorService on windows because it uses the nanos api which was too unreliable (we use Timer instead, which uses the "old" milliseconds api). also, running on a virtual machine can cause similar problems.
  • 6. Re: A more precise alternative to Thread.sleep()
    gimbal2 Guru
    Currently Being Moderated
    jtahlborn wrote:
    EJP wrote:
    Is that really true? Where on earth do they get these ideas from?
    Unfortunately, it is.

    https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks

    TL;DR, timers on windows are a mess. even the technique gimbal2 mentioned doesn't always "work". In our product, we actually abandoned using the jdk ScheduledExecutorService on windows because it uses the nanos api which was too unreliable (we use Timer instead, which uses the "old" milliseconds api). also, running on a virtual machine can cause similar problems.
    Hm other than a virtual machine what could make it not work I wonder? Perhaps something to do with AMD systems that were already flawed when it came to the nano timer?

    Regardless: its a piece of cr@p that you have to go to such lengths. But it all stems from the very odd and old design built into the Windows API to be honest. I mean run any kind of video software and all of a sudden your thread timings are different in your Java application because the precision is adjusted system wide.
  • 7. Re: A more precise alternative to Thread.sleep()
    EJP Guru
    Currently Being Moderated
    Well they certainly never cease to amaze.

    I found another one this week. There is this ghastly kludge in their browsers called the X-UA-Compatible: header, which can have comma- or is it semicolon-separated values of the form IE=EmulateIE7, IE=EmulateIE8, etc. MS blogs and KB articles vary about what the correct separator is, and you will search in vain for an actual specification, at least I did, several times. Anyway the idea is if you want the browser to run in a down-version way you shove this thing into the HTTP response headers and it adopts the highest emulation level it can. The fun starts now:

    1. IE7 in EmulateIE7 mode isn't the same as IE7. There are differences in display.
    2. IE8 doesn't appear to understand EmulateIE8 and so emulates IE7 in IE7 emulation mode, with the same bugs as (1).

    It got shoved into our project years ago when we didn't even have IE9 to test with, so we tried to force IE7 or 8 mode but not 9. The real killer is that of course simply removing it this week fixed every one of our known IE display anomalies.

    These are my own tentative findings. There is a much longer discussion with many more quirks discussed here.
  • 8. Re: A more precise alternative to Thread.sleep()
    1001190 Newbie
    Currently Being Moderated
    So, it would seem, the only options I currently have are my original one: the spinlock where the client will sync to the server and edit it's wait time to adjust for the difference, and this but involving a long Thread.sleep that, to what I'm understanding, forces 1 ms of precision in other thread.sleep commands?
  • 9. Re: A more precise alternative to Thread.sleep()
    gimbal2 Guru
    Currently Being Moderated
    998187 wrote:
    So, it would seem, the only options I currently have are my original one: the spinlock where the client will sync to the server and edit it's wait time to adjust for the difference, and this but involving a long Thread.sleep that, to what I'm understanding, forces 1 ms of precision in other thread.sleep commands?
    Something like that. It actually has nothing to do with Java, this 'improves' the precision that Windows sets by default, which can be 10 or 15ms depending on the computer. Its a little hack built (poorly) into the Windows version of the Oracle JVM to make threads wake up more precise. The trouble is that the precision is only increased for as long as there is at least one thread asleep. Hence the "endless" sleeping thread work around.
  • 10. Re: A more precise alternative to Thread.sleep()
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    998187 wrote:
    (Resulting in movement on the client being slower than movement on my server--and then chops when the server updates the sync).
    Pretty sure you would get the same behavior due to network lag time.
    And a precision timer wouldn't fix that.

    As a wild guess I googled for "games predictive movement" and found many results. Following describes the problems.

    http://en.wikipedia.org/wiki/Client-side_prediction
  • 11. Re: A more precise alternative to Thread.sleep()
    1001190 Newbie
    Currently Being Moderated
    Actually this is the exact reason I need a precise timer. To implement some predictive movement that is tracked at the same rate as the server. And where you say network lag time would cause the same behavior--actually no. Lag time in itself would not cause this, I thought it would on my first impression, as well. If latency is not excessively spiking one way or the other, then it will result of the client being the same delay behind the server constantly. So something starts moving 200 ms behind the server. Then it stops moving 200 ms behind the server (resulting in the same amount of movement in the same locations, just rendered 200 ms later--assuming the the timer is precise enough to keep the client clocking close enough to the server that movement isn't actually a different speed.) Whatever difference in latency will be all the chop--if you receive one update at 150ms and one at 120ms, you would receive 30 ms worth of "chop" (without me implementing an algorithm to smooth this out).

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points