• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
phayer

Threading and networking

11 posts in this topic

So I'm stuck, and can't seem to figure out what the "right way" to solve this is.

 

I'm using enet - and the "enet_host_service" which takes care of sending and receiving data takes a timeout, like 10ms or 5000ms - whatever. The problem is; how large should this be? 1ms?

 

Cause the wait freezes the rest of the thread, of course. But if I have two threads, one that reads from the top of a list(simulation) and another one that writes to the bottom of the list(network) - wouldn't that impact performance hard and in some cases cause problems with locking?

 

Another thing I thought about was using zeromq(zmq) internally as I then don't have to think about locking, but I'm very unsure about zeromq when it comes to latency.

 

Any suggestions?

1

Share this post


Link to post
Share on other sites

So I'm stuck, and can't seem to figure out what the "right way" to solve this is.

 

I'm using enet - and the "enet_host_service" which takes care of sending and receiving data takes a timeout, like 10ms or 5000ms - whatever. The problem is; how large should this be? 1ms?

 

Cause the wait freezes the rest of the thread, of course. But if I have two threads, one that reads from the top of a list(simulation) and another one that writes to the bottom of the list(network) - wouldn't that impact performance hard and in some cases cause problems with locking?

 

Another thing I thought about was using zeromq(zmq) internally as I then don't have to think about locking, but I'm very unsure about zeromq when it comes to latency.

 

Any suggestions?

 

I think what you suggested is the best. Have one thread taking care of network reads and writes (handling the Enet context) and one or however many you need for what you would like to do in terms of other processing. If you are handling messages with one thread then even if there is interlocking due to some queue issues, that should not be a big problem as it's not that heavy operation (locking the mutex) and you don't actually wait all that long as you have 1kHz at most reads from the list, and if you construct the read/write to be "instant" like I suggest below then there should be no issue of waiting.

 

I solved this by having an in process list (with messages to be sent) and one in queue list (with messages to be soon added to be sent). Like this you off-load the interlocking by only making the lock-unlock depend on a super fast pointer setting operation between two lists.

 

1 ms is good I think, depends on your latency issues.

 

PS - Also you might be too smart for your own good. You seem to be doing future-proof-development. Just wing it, implement it and see ;-)

Edited by jbadams
Restored post contents from history.
0

Share this post


Link to post
Share on other sites
There are two main options:

1) Use a thread for networking. Set the timeout to infinity. Use some kind of queue between network thread and main (or other processing) threads. That queue could be non-blocking if you want, if you know how to deal with back-ups/overflows.

2) Poll networking in your main thread. Unless your main thread funnels all different timing events into a single dispatcher (clock, I/O, etc) then it's likely best to pass a zero timeout, to make it truly a "poll" rather than a "wait."
1

Share this post


Link to post
Share on other sites
If you want to see a source-code of an implementation of the 2nd solution that hplus described, you can check out my UdpKit networking library: https://github.com/fholm/udpkit

More specifically you can check out the chat example: https://github.com/fholm/udpkit/blob/master/src/managed/udpkit.example.chat/Program.cs as it implements this type of polling that hplus describes. All of this is in C# so maybe it doesnt apply for you.
0

Share this post


Link to post
Share on other sites

I am wondering about this myself. I use a thread which Enet is created and managed on. The whole thing boils down to 1ms latency vs 100% CPU usage.

 

In the networking thread I can set the timeout to 1ms, such that it will use less then 1% of the CPU. But this may cause 1ms latency, or if Sleep() is used inside the Enet library upto 10ms iirc. I have only found some while loops in the Enet code, I can't figure out how it waits for packets, maybe it has driver interupts waking it up. Which eliminates the latency, but idk.

 

Or have a 0ms timeout and the thread will consume 100% of the core it is running on. So I don't know which to use to be honest.

 

But anyway, I don't think one should have more then 1ms timeout. Since your main thread needs to send packets too. If you have a 5000ms timeout then you only send out packets every 5seconds...

 

I don't think Enet has internal threads for recieving/sending packets. Because if you don't service the host within 15-20seconds it will disconnect from the server. So if you have it in your main thread and the game freeze for 20sec then you disconnect.

Edited by Tispe
0

Share this post


Link to post
Share on other sites

this may cause 1ms latency


If you have a 5000ms timeout then you only send out packets every 5seconds


I would expect Enet to return immediately if there is any data received, not wait the full time-out.
Thus, as long as data is coming in, there is zero latency between received data and getting the data in the program (for the first piece -- the next piece gets whatever latency your processing imposes.)

Now, for the outgoing data, you will need some kind of maximum send rate. One packet 20 times a second? That would mean you should set the timeout to no more than 50 milliseconds.
0

Share this post


Link to post
Share on other sites

Now, for the outgoing data, you will need some kind of maximum send rate. One packet 20 times a second? That would mean you should set the timeout to no more than 50 milliseconds.

 

I disagree. Suppose your enemy is using a spell on you or some other action. You want to get that packet ASAP. For position updates 50ms between each packet is fine.
 
You don't want Enet to manage how often you send packets. You want Enet to send a packet as soon as you tell it to. You can't have Enet waiting 50ms on another thread while an outgoing packets is waiting to be sent. If you are "lucky" and get an incoming message in those 50ms then your waiting is interupted and you can send that outgoing packet, but be unlucky and that outgoing packets sits in a queue for 50ms.
 
You want another layer ontop of Enet to decide which packets are sent and at what frequency. And thus Enet must be very responsive for any requests, be it a position update or an action.
 
So, 1ms (which can mean upto 10ms if Sleep() is used inside Enet) or 100% CPU usage....
Edited by Tispe
0

Share this post


Link to post
Share on other sites

Okey, so I implemented something that seems to work well;

 

2 threads and 2 queues. 

1 thread for handling networking, 1 for the game.

1 queue for incoming data, 1 for outgoing data.

 

Does this seem like a reasonable design? I don't want to get hung up on this, but on the other hand I don't want to make a lot code smell -- Like, I don't want to spend a month later rewriting the entire network only because my prototype implementation was bad.

0

Share this post


Link to post
Share on other sites

Other than to beware of concurrent edits (e.g. network thread adding to the queue while the processing thread is removing from the queue) yes, that can work quite well. The network is just a data transfer medium. You are right to want to keep it simple. Write data, read data, that's it.

 

The interesting part is what you do with that data inside the game.

Edited by frob
0

Share this post


Link to post
Share on other sites

Other than to beware of concurrent edits (e.g. network thread adding to the queue while the processing thread is removing from the queue) yes, that can work quite well. The network is just a data transfer medium. You are right to want to keep it simple. Write data, read data, that's it.

 

The interesting part is what you do with that data inside the game.

 

Well, I'm locking the queues while I'm reading or writing to them. The current mechanism tries to;

 

Network thread --

Lock incoming queue and write to it, then unlock

Lock outgoing queue and send packages, then unlock

 

Game thread --

Lock outgoing thread and write to it, then unlock

Lock incoming queue and read from it, then unlock.

 

Just to minimize locking. Probably not perfect, but it works so far and I'm happy.

 

 

 

If any of you have any experience regarding entity-component-systems and how to integrate network to them easily while still keeping them flexible/extendable, the whole point of a entity-component-system, then please drop by in my other thread.

Edited by phayer
0

Share this post


Link to post
Share on other sites

I disagree. Suppose your enemy is using a spell on you or some other action. You want to get that packet ASAP.


Most actual shipped network games (and their programmers) disagree with you.

Instead, make your gameplay and simulation absorb this time (just like it already has to absorb transmission latency.) Typically, through wind-up animations that are longer on the sending side than the receiving side.

Sure, you're free to schedule your own packets any way you want, and you can probably make a fun game that way, too. It's just that experience says that it's probably not a good return on investment/cost to build a system that sends some kinds of events out-of-line.
0

Share this post


Link to post
Share on other sites

 

Other than to beware of concurrent edits (e.g. network thread adding to the queue while the processing thread is removing from the queue) yes, that can work quite well. The network is just a data transfer medium. You are right to want to keep it simple. Write data, read data, that's it.

 

The interesting part is what you do with that data inside the game.

 

Well, I'm locking the queues while I'm reading or writing to them. The current mechanism tries to;

 

Network thread --

Lock incoming queue and write to it, then unlock

Lock outgoing queue and send packages, then unlock

 

Game thread --

Lock outgoing thread and write to it, then unlock

Lock incoming queue and read from it, then unlock.

 

Just to minimize locking. Probably not perfect, but it works so far and I'm happy.

 

 

 

If any of you have any experience regarding entity-component-systems and how to integrate network to them easily while still keeping them flexible/extendable, the whole point of a entity-component-system, then please drop by in my other thread.

 

 

Looks good to me!

 

I have a full message/scheduling environment (called Flow) built around lazy type evaluation and the like a bit like AgentC describes in his answer to the other thread.

 

You can build one too if you like, no big deal to it. Also like that there is no distinction to networked or non-networked messages as all individual variables come with full type info (this means that yes bit compressed flags and small variables can take a lot of space - in which case you send a special binary field and compress them all into it) and if you as receiver cannot handle it you just don't. Simple. The approach of creating elaborate class hierarchies, special message container structures and the like is antiquated and quaint (in my opinion), but it is used by industry giants such as google, so it must be good for something :-)

Edited by jbadams
Restored post contents from history.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0