Mud with or without Multi-Threading ?

Apprentice
Posts: 13
Joined: 2006.09
Post: #1
Hi guys
I'm working on a MUD (actually I'm working on Server). What's the best way to manage clients? It's better the "multi-threading" server, or I can use a single loop where I check every client.
Actually, I'd pick the first one.
Quote this message in a reply
Hog
Member
Posts: 151
Joined: 2002.09
Post: #2
You should go with multi-threading since checking every client takes too long to do sequentially (because of latency issues).
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
I don't see any particular reason to use multithreading here. The UNIX socket layer is designed to avoid any such need.

My general rule is that if you're not sure whether you should be using multithreading, you shouldn't be Wink
Quote this message in a reply
Apprentice
Posts: 13
Joined: 2006.09
Post: #4
Thank you Smile
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #5
For a MUD you're definitely going to want to multithread your server. OSC is very wrong in this case (for once).

Because the connection state of each client is independent of all the other clients, if you don't multithread you're going to run into a protocol handling nightmare. This is primarily because you have no guarantee that the escape/decoding sequences will complete within the current packet you are processing. If you have a single thread you won't be able to sleep on the current client, you have to flush your entire protocol syntax tree (and there's really no easy way to rebuild it other than to keep it all in memory [which is extremely messy]). Once you add MCCP or even the most basic telnet options you're going to be in a world of hurt if you're running a single thread for all clients.

Never even mind that dual/quad core machines are cheap nowadays. A single threaded server with non-trivial I/O is just plain daft.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #6
I'm not so convinced. I think non blocking IO be a lot easier. It would be really easy to mess up and make your game non deterministic if you did the threading improperly. Debugging that would be incredibly hard.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #7
Skorche Wrote:I'm not so convinced. I think non blocking IO be a lot easier. It would be really easy to mess up and make your game non deterministic if you did the threading improperly. Debugging that would be incredibly hard.
My point is not about blocking IO.
Consider this:
You have a user on a 14400 baud modem connected to your MUD. They're downloading email causing their packets to come in with a high latency. They're MUD client sends the beginning of an escape sequence for window sizing and the packet ends.

Now, you have the open escape sequence in your processing buffer and you are sitting waiting for the next packet (which could take a while). What do you do?
Do you...
a) save your call stack to memory? (extremely ugly to implement)
b) dump the buffer and start throwing protocol exceptions? (highly counter productive)
c) wait for the next packet? (meanwhile your other 200 connections are waiting and your MUD just froze)
d) rewind the call stack for the current connection and make this client wait? (meanwhile their character gets slain by the mob and they don't even get feedback to know that it happened.)
e) give up and go multithreaded with blocking IO. (I'm in this camp).

If you have a solution, please correct me. But as far as I can know, there's no easier way to do the protocol handling in the main thread. Synchronizing the game state in the client threads is dirt simple compared to tracking multiple connection states in a single thread while expecting good performance.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
Stick it in a buffer until you see the end of the escape sequence, and go back to your select() loop?
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #9
OneSadCookie Wrote:Stick it in a buffer until you see the end of the escape sequence, and go back to your select() loop?
See (d).

As unforgiving to low bandwidth players as I'd like to be, just stopping the processing in a chunky manner like this is not very beneficial to a soft-realtime environment like a MUD. When I see 'An ugly mob trips you and you go down!' I want my character to stand when I type 'stand' as immediately as possible.

If we're just going to switch contexts every single packet then we're wasting all the optimization of whatever thread package we have available and it's going to mean our buffers are going to get huge. We'll be using more resources to keep our call stacks live than to actually get the processing done. Never mind that we want discrete chunks of text to be passed back and forth for proper rendering on the client side when echo is on.

If we decide instead that we'll process all available packets while the buffer is not empty, then we're giving priority to the client that can dump the most bytes into our socket. Some jerk decides he wants to constantly resize his window, run asinine triggers, or a bot and all the other clients go to shit. If you stick a limit on the buffer size you're going to end up with incomplete commands like I said earlier.

For that matter, what are you going to do if your client doesn't support GoAheads? What if you need live input without a CRLF? Etc. etc. etc.

I'm not trying to be a party pooper here, I'm just speaking from experience. I lived in the telnet RFCs for long enough to know that it's hard enough to manage all these things with just network quirks. If you're trying to implement your own fake threading/time management you're going to be in a world of hurt. Just use your favorite thread package and be done with it. Use your data store to sync the client states, it'll be fast enough for text only and a lot less headache.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
kelvin Wrote:See (d).

As unforgiving to low bandwidth players as I'd like to be, just stopping the processing in a chunky manner like this is not very beneficial to a soft-realtime environment like a MUD. When I see 'An ugly mob trips you and you go down!' I want my character to stand when I type 'stand' as immediately as possible.

I'm really not seeing what you're trying to say here. We're talking TCP; their window resize command will arrive completely before their stand command does.

I'm not seeing how multithreading buys you anything. You get input, you respond to it. You've got to maintain a consistent world view, so you can't do updates on your network threads; all you can do is parse the input into a slightly more useful format. If that's enough work that you need the benefits of multiprocessing to handle it, you should consider optimization.
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #11
It should also be pointed out that tons of MUDs, MOOs, etc, were built with no traces of threading for years and years, and they worked out just fine. Smile Not the prettiest code but they were perfectly functional.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #12
OneSadCookie Wrote:I'm really not seeing what you're trying to say here. We're talking TCP; their window resize command will arrive completely before their stand command does.

I'm not seeing how multithreading buys you anything. You get input, you respond to it. You've got to maintain a consistent world view, so you can't do updates on your network threads; all you can do is parse the input into a slightly more useful format. If that's enough work that you need the benefits of multiprocessing to handle it, you should consider optimization.
I'm not talking about contention between commands from a single client (Yes, TCP will guarantee packet order). I'm talking about contention between clients. If mudder A floods his high bandwidth line with lots of stuff to process, when will you get to mudder B to process his 'stand' command? If you just say, oh I'll stop processing mudder A when I reach a threshold, then how do you save your state for mudder A? If mudder A has MCCP enabled and MXP enabled, then you're possibly inside an MXP decode inside an CHARSET decode inside a zlib deflated stream. You're working with a call stack, do how do you save it?

If you multithread your server all the client balancing is taken care of for you automatically. You don't have to save track your call stack. You don't have to do messy state and context switching. If anything, it makes debugging easier. You just sit there in your thread and process the stream as it comes out; no worrying about saving your state to come back to next time you get to this client.

All the multithreading I'm talking about here is for decoding and parsing only. Yes, your game logic should be in a single thread. But just writing off the decoding and parsing as automatic or easy enough to do in a single thread for multiple clients is bad. In this case multithreading will make your code cleaner, easier to read, and easier to maintain and debug.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #13
Dan Potter Wrote:It should also be pointed out that tons of MUDs, MOOs, etc, were built with no traces of threading for years and years, and they worked out just fine. Smile Not the prettiest code but they were perfectly functional.
They also didn't support compression, images, sound, and 8bit color. I'm not saying a silent, black and white, unformatted text adventure can't be fun, but you have to consider your competition. Most if not all MUDs out there today support at least some of these basics.

I still stand by my assertion that multithreading will make coding the decoding parsing easier.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #14
Sure, though the original poster didn't really specify what sort of game it's going to be. Using the word "MUD" usually implies the old text-based stuff, at least it does to me. I'd expect people to go for MMORPG if they mean the fully graphical stuff.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #15
Dan Potter Wrote:Sure, though the original poster didn't really specify what sort of game it's going to be. Using the word "MUD" usually implies the old text-based stuff, at least it does to me. I'd expect people to go for MMORPG if they mean the fully graphical stuff.
I've been talking about standard text telnet/vt100+ MUDs. What have you been talking about?

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Obtaining GPU deviceID for each window/NSScreen in multi-display/multi-GPU app? dauerbach 1 3,449 Oct 8, 2012 11:58 AM
Last Post: OneSadCookie
  Threading Jones 13 4,955 Jun 13, 2006 03:18 PM
Last Post: Jones