Skip to main content
gamedev.net
🔒 Locked

Time-sensitive networking functionality and multithreading

Started by jacksaccountongamedev 6 replies 1.2k views
Original Post
jacksaccountongamedev
jacksaccountongamedev
Hello, I have a rather straightforward question regarding the use of a separate thread for networking in the client of the multiplayer action game I am currently programming. My apologies if this is a repeated question, but the search feature is not working correctly on my machine (page half-loads with one to three listed topics) and those results that I did manage to find were irrelevant. I have been coding a networking layer built atop HawkNL that provides such features as automatic pinging and connection management, automatic synchronization of timers between remote hosts and semi packet reliability (guaranteed to arrive but not in order). The time-sensitive features such as clock syncing work as one would expect when I run bare non-graphical test programs. The times recorded and used are accurate because the program loop (networking) runs at least once a millisecond (usually around five to six times). However, if my client runs at seventy frames per second (rendering graphics etc), then the networking loop will only execute once every fifteen milliseconds or so (single threaded). Obviously when establishing pings and syncing times this is not ok at all. Having no real experience with multithreaded applications, I ask: is multithreading the answer here? If I run the networking layer in a separate thread, record any application-specific packets received and pass them to the main game thread for processing once every rendering frame, will my network code execute as fast as it possible can over and over again (at least once a ms for best accuracy)? If so, then how can any multiplayer action games survive within a single thread? Thanks for any help, Jackson Allan
kuphryn
kuphryn
Correct. Multithreading is one solution allowing the other threads to do work.

Kuphryn
cbenoi1
cbenoi1
Another way would be to gather stats on the ping times. Given that the timestamp snapshot would be off by 15/2 ms on average and that latency varies with time, you end up with a Poisson distribution of the combined delays.

http://www.codewhore.com/howto1.html

> If so, then how can any multiplayer action games
> survive within a single thread?

You don't need millisecond accuracy for games. There is also simulation computation delays that you have to incur besides solely the network latency and rendering times. And those make up for the overall delay you have to incur.

In an FPS setting, human reaction time from visual stimuli to pressing the fire button is on the order of 80 - 100ms. The RTS genre can have delays up to 250ms without affecting gameplay; it's a more complex eye/hand coordination (aka a "mouse clicking festival"). Besides, if the visuals are made coherent in time (i.e. movement interpolation / extrapolation), players will tend to anticipate movement and behave accordingly. If you've played Counter-Strike or Battlefield1942, you've noticed it takes a minute or two to get the feel for the latency and adjust your deflection shooting accordingly.

Hope this helps.

-cb
hplus0603
hplus0603
Just because you have multiple threads doesn't mean that your code will magically run in parallel. It will only run in parallel if you have multiple CPUs, or, possibly, if you have a HyperThreaded CPU.

Thus, on a single-CPU system, even though you have multiple threads, the OS will only interrupt the currently running thread when it enters a blocking system call, or when a scheduling timer quanta expires. Even if a higher-priority thread becomes runnable, many OS-es won't actually schedule that thread until at least 10 milliseconds later!

The only way to get GOOD timing data is to build it into the device driver model. Sadly, networking has never had timing as a requiement, and thus no desktop OS I know of has timing information as part of the networking API.

Now, if you create a high-priority thread for just receiving data and putting it in a queue with a timestamp, and run it on a hyperthreaded CPU, you will often see very low latency. Except when DirectSound decides to run. Or the background intelligent transfer service. Or the USB printer poller. Or ...

Typically, these events will almost never happen on your development machine, but will happen all the time on your user's machines, because users install more cruft than typical developers ;-P
enum Bool { True, False, FileNotFound };
cbenoi1
cbenoi1
Quote:
Speak for yourself! Adrenaline, focus, being just 1 frag from the level limit, and on 50% health with only one rocket left can do wonders for reaction times...

LOL.

I'm not convinced you can train someone to react faster. Pavlovian theory might explain why people drool when fragging, though...

-cb
jacksaccountongamedev
jacksaccountongamedev
Cbenoi1: That document is actually the scheme I am already employing to account for network latency (read through it some time ago). However, the document talks of synchronization within six milliseconds – that would seem very difficult if the networking is reliant on the framerate.

Hplus: I do not have a hyper threaded CPU, nor will the standard machine I would expect this game to run on. If I placed my network code inside a separate thread, would it at least run more often that it would if I tied it to the main game loop? Currently my networking system accounts for inaccuracy due to varying network latency, and if I start receiving time information that is +/- 20 ms off it is not going cause the thing to come crashing down, but it will mean that the clocks will constantly be re-syncing and ping times displayed to the user will bounce up and down indefinitely. What if the game is running on a slow machine at 30 fps?

I notice that when commercial playing games over a LAN that my ping times are usually very low (seemingly independent of the framerate) despite the fact that the graphic may only be rendering at 50 fps.

I understand that multithreading isn’t going to make my time-sensitive code accurate to the millisecond. What I am trying to as is: will multithreading be an improvement? Worth a try?

I may just throw a test application together sometime this afternoon so as that I can see exactly what is worth doing and what is not.

Thanks,
Jackson Allan
uncutno
uncutno
Yes, yes and yes!

If you put your recive function in a seperate thread, you get alot of benefits, but! You are only interested in handeling the incoming data between rendering frames, so get the data in a separate thread, and act on it in the main(render) loop! Its easy to create a main loop that updates the world 100fps, even if the rendering is done at 15fps. You dont want to update the world while rendering, so do something like this:

loop:

mesure the time of the last frame,
find out how many times the world should have updated in this time (0-100?)

update world this number of times

render

endloop:

if you save the roundoff, and add it to the next frame time messure, you can get an exact update fps, with a dynamic rendering fps:
only problem with this is when the update world function takes longer time then its given, so that it cant keep 100 fps whitout rendering

the update world func gets the data from your net thread...
send your own data right after it have been created (this is as early as possible, no multithreading could do it faster)



-Anders-Oredsson-Norway-

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.