Skip to main content
gamedev.net
🔒 Locked

Multithreading a Simple Game Server

Started by Luth 2 replies 2.2k views
Original Post
Luth
Luth
So after a number of rousing talks at GDC, I decided that it'd behoove me to learn a little about multi-threading. I've read some articles and posts, and think (or rather, thought) I knew enough to begin striking out on some architecture for some trial-by-fire attempts. I decided to start with a simple application in order to wrap my head around the architecture needs: a tcp/ip chat client. So there are four basic structures to a chat client server: Listen for new connections, read incoming data, process the information, send outgoing data. Easy enough, so then I got to designing architecture. An obvious first approach was Functional Threading; one thread for each task. But that doesn't scale well, so I scrapped it. Much nail biting later, I happened upon the concept of a Job Queue. One Foreman (a monitor) who controls a bunch of Workers (threads, one for each core), each of whom pick away at Jobs (parallel-able task functions) in the Job Queue. Basically a completely parallel structure. Just keep adding Jobs to the queue, and they'd get done eventually by some Worker. But I didn't really feel comfortable with the notion that there is no level of "This-before-That", so I added a little mod to the structure. Using the same Foreman/Worker/Job model, I applied it to each of the main systems instead. First the Read-Incoming-Data Foreman would hire Workers to process all the Read-Incoming-Data Jobs, then it'd wait until all the Jobs were finished before halting that Foreman and letting the Process-Information Foreman take over, etc etc. This version does scale well, and it does keep login in-line (which makes it easier on my head), but it's far from perfect. Really, at this point, any comments or a point in the right direction would be helpful. What's wrong with my design? What's right? How do I deal with Jobs that need to be run at a certain frequency (like rendering)? I don't want to use pre-made code, since I'm learning architecture, not APIs, but examples or explanations of what other, more experienced multi-thread programmers have done would do me well.
jeremymm
jeremymm
This task is not something I would multithread. However, If I would it would be a very simple, two thread, producer-consumer model with messages being stored in a shared queue.

For a chat server its really simple and effective to NOT use threads. Use something that is like C's select() method. When data is avalible, login, broadcast it, and/or whatever it. I use this basic method in production software with great success. However, I use a "custom" UDP ACK instead of TCP.
Luth
Luth
Right, of course its silly to worry about multi-threading on something as simple as a chat server, but I'm using a simple application to learn more about a complicated architecture. I -could- start off by programming a MMO game server, but then I'd have to worry about learning MMO architecture concurrently with multi-threading architecture.

What I want to do is learn some fundamental principles and methodologies to build other, more complicated, and wholly more deserving multi-threaded server applications.

I'm not aiming to learn how to make a chat server. I already did that; took about an hour to do from the ground up. Now I'm looking to learn specifically more about multi-threading architecture from a practical perspective.

I hope this better clarifies my intentions. :)
Bob Janova
Bob Janova
The main guidelines for multithreading are twofold, in my somewhat uninformed opinion:

  • Look for separable tasks that don't write to the same data, so you can thread without worrying about synchronisation or locks, which lose a lot of the performance boosts. Output-only tasks – which only read data – are the most obvious targets; rendering, sound and network output streams are the 'low fruit' of multithreading. For many games that will be enough. Physics/entity update (which has solo write access to the game world) is also a possibility.
  • Where there is a large collection of high-computation tasks which are independent of each other, you can run them in parallel. You'd use the .Net thread pool model for this (a few threads which take tasks whenever they're ready). However, this is, in my experience, rare in games – entity update typically is not independent of other entities around it, and it may be important to have a predictable order of updates. A cellular simulation, for an atmospheric or water simulation, would be the textbook example of this technique. If the order of entity update is not important you may be able to do that or collisions in this way.

Topic Locked

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

Sign in to reply to this topic.