9

I have a function that runs a tick() for all players and objects within my game server. I do this by looping through a set every .1 seconds. I need it to be a solid .1. Lots of timing and math depends on this pause being as exact as possible to .1 seconds. To achieve this, I added this to the tick thread:

start_time = time.time()

# loops and code and stuff for tick thread in here...

time_lapsed = time.time() - start_time # get the time it took to run the above code
if 0.1 - time_lapsed > 0:
    time.sleep(0.1 - time_lapsed)
else:
    print "Server is overloaded!"
    # server lag is greater that .1, so don't sleep, and just eat it on this run. 
    # the goal is to never see this.

My question is, is this the best way to do this? If the duration of my loop is 0.01, then time_lapsed == 0.01 ... and then the sleep should only be for 0.09. I ask, because it doesn't seem to be working. I started getting the overloaded server message the other day, and the server was most definitely not overloaded. Any thoughts on a good way to "dynamically" control the sleep? Maybe there's a different way to run code every tenth of a second without sleeping?

Charles
  • 50,943
  • 13
  • 104
  • 142
jtsmith1287
  • 1,110
  • 2
  • 13
  • 24
  • I would do a `try: time.sleep(0.1 - elapsed); except: pass` just to reduce the computation time with the if-statement. But everything else looks good – inspectorG4dget Nov 08 '12 at 17:32
  • 1
    It seems pretty clear that for some reason your `loops and code and stuff for tick thread` is taking longer than 100ms. How are you sure that the server is "most definitely not overloaded"? –  Nov 08 '12 at 17:50
  • Which operating system are you using? It's important to choose the best function – enrico.bacis Nov 08 '12 at 17:52
  • @inspectorG4dget - That was actually how I originally had it, but it was not raising an exception, so I was not getting the error message printed. – jtsmith1287 Nov 08 '12 at 21:25
  • 1
    @bdares - We've done extensive stress tests on the server to see at which point it becomes overloaded. The limit is about 200-300 objects within a similar area of the game. The cause for asking this question was getting the error when only 7 things were loaded. I had a raised eyebrow moment and have since been trying to figure out why I'm getting it now. – jtsmith1287 Nov 08 '12 at 21:25

2 Answers2

3

It would be better to base your "timing and math" on the amount of time actually passed since the last tick(). Depending on "very exact" timings will be fragile at the best of times.

Update: what I mean is that your tick() method would take an argument, say "t", of the elapsed time since the last call. Then, to do movement you'd store each thing's position (say in pixels) and velocity (in "pixels/second") so the magnitude of its movement for that call to tick() becomes "velocity * t".

This has the additional benefit of decoupling your physics simulation from the frame-rate.

I see pygame mentioned below: their "pygame.time.Clock.tick()" method is meant to be used this way, as it returns the number of seconds since the last time you called it.

mike
  • 403
  • 3
  • 6
2

Other Python threads may run in between leaving your thread less time. Also time.time() is subject to system time adjustments; it can be set back.

There is a similar function Clock.tick() in pygame. Its purpose is to limit the maximum frame rate.

To avoid outside influence you could keep an independent frame/turn-based counter to measure the game time.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • Oh! So, if I'm understanding this right, I could remove time.time and time.sleep completely, and just add Clock.tick(10), and that will limit my tick thread to 10 loops a second, which is what I need. Is that right? – jtsmith1287 Nov 09 '12 at 02:11