Quote: ThomasWatts wrote:
Separated the networking and the lua into two threads. One for the networking, and one for the lua world. Both do things and then sleep, the networking runs at 4 pulses a second, the lua 2.
I don't know why you would want pulses for the networking or the lua.
The big advantage of a thread-driven model is you don't have to have a polling loop. The network code can sleep (select()) until it has input to process and the lua game state should be mostly event driven?
Quote: Nick Gammon wrote:
For example, if the Lua lock is taken, and then calls the network code (eg. to send a message) and some error condition arises that needs to execute Lua code, then the Lua lock is already taken and the whole process halts.
That's what reentrant locks are for.
Though if you are doing threading the lua code should dispatch an event to the network code, release its locks and sleep until the response is ready? (Or otherwise keep itself occupied doing other stuff rather than blocking until the network code is finished.)
Quote: David Haley wrote:
I agree though that this adds a lot of complexities and it's worth thinking why exactly you want to break it into threads. In general, you need threads in the following kind of situation:
Or if you're mud is processor intensive (lots of scripting code, lots of players, mccp, physics?) AND it running on a multi-core (or multi-processor) box.
Ideally, you want 1 thread/processor core.
Quote: David Haley wrote:
Classic example is a GUI application with some processing going on where it needs to remain responsive to e.g. a cancel button being pressed.
The definition of "responsive" varies too, a GUI should respond in less than 1/10 of a second, but a MUD that might have a ping of up to 300ms can be called "responsive" if it takes 2-3 seconds between entering a command and seeing it enacted.
Quote: David Haley wrote:
In MUD terms, what operations are you running that take a long time? I can only think of one, really: the reverse IP lookup, which sometimes stalls the game for many seconds at a time.
Can't that be done asynchronously? Most of the time taken is blocking waiting for a response from the DNS server?
Quote: Nick Gammon wrote:
And in fact you could make a case for throttling the server, in the sense that, if you carefully write it to be really really responsive, then it could handle 1000 commands per second spewed out by a client bot, to the disadvantage of "real" players.
Every command should take some "time" to enact, you might be able to handle 1000 commands/sec/player (and it's something to aim for, since 1000 commands/sec on a playerbase of 1 is only 5 commands/sec on a playerbase of 200) but you should only allow a queue of 20 or so commands and each command should take at least 1/16 of a second (for preference changes or other OOG things that translate into a single function call) up to 4 or 5 seconds (for time consuming IG activities... searching, digging, expensive spells, repairing, crafting). Longer than 5 seconds where the game seems unresponsive (because your character is busy) can be problematic :(
Quote: ThomasWatts wrote:
As it stands I'm just going to see how a single thread goes for now. Input 4 times a second, and the world tick 2 times everything shouldn't get bogged down unless I really write some terrible lua. We shall see in the future.
If anyone else tries for multi-threaded, I'm sure all of us will want to know how it goes.
Python has an implementation called "Stackless", I don't know if Lua has something similar?
Stackless is single threaded BUT provides lots of tools for cooperative multitasking with "microthreads" or "green threads". The idea is that instead of being preempted by the OS scheduler, individual tasklets hand off to each other so you don't need to worry about locks because there is only one thread, and you get all the advantages (except multi-processor use) provided each tasklet hands off the execution when it no longer needs it (or periodically even if it does). |