Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ SMAUG ➜ SMAUG coding ➜ Who knows windows threads (or any threads)

Who knows windows threads (or any threads)

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1  2 

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #15 on Mon 12 Nov 2007 04:38 AM (UTC)
Message
On windows Lua has proven to me to not be thread-safe. Two threads, one networking, one lua, both calling lua code. With no sync both threads would eventually trash each others stack resulting in string constants becoming nils, functions becoming numbers, etc. At least, that's what I experienced.
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #16 on Mon 12 Nov 2007 05:43 AM (UTC)
Message
Quote:
I believe Lua is supposed to be potentially thread safe, although there may be compile-time considerations.

I think the stuff is there, you just have to turn it on and tell it what functions to call for locking. I think the Lua coroutines are very close to being actual threads. In any case it does require a different compilation of the core, if memory serves.

But yes, Lua is by default not at all thread-safe, and you need to manage the synchronization on your own. But Lua is supposed to be reentrant, in the sense that if you have two threads each running their own Lua states, everything is (supposed to be) ok. Problems only come up when two threads need to talk to the same state.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #17 on Mon 12 Nov 2007 05:49 AM (UTC)
Message
Quote:

Two threads, one networking, one lua, both calling lua code.


Like I said, I would expect that to fail, without considerable effort put into synchronizing. However, remember you can have multiple Lua states (as I do in my Smaug task system), so if each subsystem called a separate Lua state there would be no problems, or less anyway.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Isthiriel   (113 posts)  Bio
Date Reply #18 on Mon 12 Nov 2007 06:39 AM (UTC)

Amended on Mon 12 Nov 2007 08:56 AM (UTC) by Isthiriel

Message
Quote:
ThomasWatts wrote:
I was using pathetic boolean checks for locks and a message queue for when the locks were engaged. I tried either/or and a system of both, and neither solved the eventual problem of race conditions. It was alot of hassle that I decided to not deal with at the time.

You need at the absolute minimum an atomic (un-preemptable, no other thread or process can do anything meanwhile) test-and-set function to attempt to implement a lock yourself, if you don't have that then you're just moving the race condition around.

Usually whatever library provides that will also provide higher level constructs, like mutexes, reentrant locks, bounded semaphores ...

EDIT: I just proved myself wrong on this point *sigh*.
While looking for something else I found Wikipedia's explanation of Test-and-Set (http://en.wikipedia.org/wiki/Test-and-set) which has a link to "Peterson's Algorithm" (http://en.wikipedia.org/wiki/Peterson's_algorithm) and while I don't remember it being called that, I do remember being taught it (or at the least the flag/turn bit and the three criteria) at some stage.

Quote:
David Haley wrote:
(In other words, there's no reason to be multi-threaded just because you have several processors.)

A single-threaded application can occupy, at most, one core. A dual core system will never see the global utilization rise above 50% because one core will always be idle. :P

Quote:
David Haley wrote:Still, you would need some kind of synchronization, depending on what exactly is being done.

Just add the UDP listen port to the select() call that waits for player input and process it when it arrives?

Quote:
David Haley wrote:
I suspect that the term "stackless" is something of a misnomer, because each of these "tasklets" (in Python terminology) would have their own stacks, no?

The name "Stackless" is because they removed the underlying C stack, so while Python frames may be part of a Python stack, Python function calls don't add or remove from the C stack.

Quote:
Nick Gammon wrote:
I think there is a slight misunderstanding here. The way you have written that, you are saying the server should handle 1000/commands/sec overall (not per player) to give 5 commands/sec for a single player, if the playerbase is 200.

I don't think you need to design in to handle 1000 commands/sec/player as that seems to me to be abuse of the server. How many genuine players are going to enter 1000 commands in one second?

None, the only way 1000 cmds/sec is useful is as a poor method of benchmarking and/or profiling the server. Having said that, I can't really think of a better way :-/

Aim for oodles of commands per second because it's usually harder to fix performance issues after-the-fact when the mud is sitting with a longterm average > 60% utilization and lagging all the players than when you're in the preliminary design/implementation phase.

(The disadvantage of using 1000 cmd/sec/1 player [or 2 players or 3 players] as a test to see how well the server copes with a large number of commands/sec from a number of players is because a larger number of players is going to be scattered all over the world and have a more varied inventory which affects the performance of processor/memory caching.)
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #19 on Mon 12 Nov 2007 07:25 AM (UTC)
Message
Quote:
Isthiriel:
A single-threaded application can occupy, at most, one core. A dual core system will never see the global utilization rise above 50% because one core will always be idle. :P

Well, sure, but that's not a problem unless you often run at full capacity and you can parallelize that task to begin with. :)

Quote:
Isthiriel:
Aim for oodles of commands per second because it's usually harder to fix performance issues after-the-fact when the mud is sitting with a longterm average > 60% utilization and lagging all the players than when you're in the preliminary design/implementation phase.

I'm not sure that's true. On the contrary, having such high utilization lets you run profiling to figure out where you're actually spending your time. Of course, you should be profiling during development, too, but it's hard to simulate "actual load" until you've seen, well, actual load. As the saying goes, premature optimization is the root of all evils.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Isthiriel   (113 posts)  Bio
Date Reply #20 on Mon 12 Nov 2007 08:49 AM (UTC)

Amended on Mon 12 Nov 2007 08:58 AM (UTC) by Isthiriel

Message
Quote:
David Haley wrote:
I believe he was describing a situation where the Lua thread needs to lock on the networking thread, and then the networking thread needs to lock on the Lua thread. Poof, deadlock. So no, it can't be solved by reentrant locks. It's a classic deadlock problem, like dining philosophers.

I just remembered why I've never had this problem before :P (and it's not like dining philosophers, it is dining philosophers, with two philosophers and two chopsticks)

Always (always!) take locks in the same order.

The same advice applies for semaphores, mutexes &c..

In this case, I think the network lock is less likely to be taken at any given time, so if you want to have both the network lock and the lua lock, you need to take them in that order. If you already have the lua lock (and don't have the network lock), you release the lua lock, take the network lock then retake the lua lock.

You never have a deadlock. You have to be more careful with the state when you release the lua lock (so you can grab the network lock) because you will be preempted at that point by a thread that has the network lock and wants the lua lock.


... and I still contend Nick meant the lua thread would call a network function (send_to_buffer or something) that threw a lua exception (buffer overflow perhaps) without involving the network thread at all, a problem which would be solved by using reentrant locks.


Ideally if the lua thread wanted the network thread to do something, it would dispatch a message to the thread and then give up the lua lock and block until it had received a response. The networking thread (when it woke up) would take the networking lock, check its messages, do what the lua thread wanted (without ever taking the lua lock), dispatch the result back to the lua thread, release the network lock and go back to sleep. The lua thread would then wake up, take the lua lock and merrily go about its business.

... which actually makes both the lua lock and the networking lock redundant since the synchronization is handled by the (implied) message-queue lock, which just goes to show the first rule of inter-thread communication is to minimize the data that needs to be synchronized (in this case going from the network state and the lua state to just the message queue between the two threads).
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #21 on Mon 12 Nov 2007 10:45 AM (UTC)
Message
I'm not sure why the is/like distinction is really that important, but I chose to use the word "like" and not "is" because it is a concrete instantiation of the problem illustrated by the dining philosophers. But anyhow, I don't think we're talking about the same thing... Some deadlocks cannot be solved by taking locks in the right order. Sometimes the fundamental design of the system is just wrong.

Thread 1:
Holds lock 1. Sends a message to Thread 2. Waits for response.

Thread 2:
Notices message. Grabs lock 1. Oops.

The problem here is that t1 is keeping its lock while waiting for t2 to do its thing, and t2 needs t1's lock. No amount of choosing locks in the right order will solve this. You'd need t1 to release its lock while letting t2 do its thing.

Besides, occasionally you need to hold two locks at once, so it's not always an option to have a strict protocol of only holding one lock at a time and acquiring them in a specific order. (Of course, that often helps. It's just not a solve-all solution.)

And yes, the message solution is as I suggested a better way of designing the system.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #22 on Mon 12 Nov 2007 09:34 PM (UTC)
Message
Yeah, this is why I asked for some help. You all know quite a bit more about thread theory then I do. Thanks.
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #23 on Mon 12 Nov 2007 09:51 PM (UTC)
Message
Quote:

Always (always!) take locks in the same order.


I agree that to solve deadly embrace situations, you won't get them if you take locks in sequence. That is, if each possible lock is numbered, and you can only lock a higher number than you currently hold. That way, lock 1 can take lock 2, but lock 2 can't take lock 1.

However this can be easier said than done, and also relies on discipline by the programmer, I don't think it can be enforced in any useful way.

Quote:

Ideally if the lua thread wanted the network thread to do something, it would dispatch a message to the thread and then give up the lua lock and block until it had received a response.


If the Lua lock is on the whole Lua script engine, it isn't really meaningful to talk about a Lua script giving up the Lua lock - either the Lua script engine is locked or it isn't.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


80,028 views.

This is page 2, subject is 2 pages long:  [Previous page]  1  2 

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.