www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Light-weight threads

reply Norbert Nemec <Norbert Nemec-online.de> writes:
Hi there,

I just found that recent change in the language to make all global 
variables thread-local by default. This makes me think of a major 
performance problem: every thread creation will have to copy all the 
thread-local variables. This makes it impossible to efficiently spawn 
many light-weight threads even if they do not make use of the global 
variables at all.

I guess I am not the first one to spot this problem? I believe that 
thread creation should come with as little overhead as possible. Maybe a 
concept of light-weight threads based on side-effect free code could 
complement the regular threads?

Just a quick idea to throw into discussion...

Greetings,
Norbert
Feb 24 2010
next sibling parent reply ds <dsimcha yahoo.com> writes:
== Quote from Norbert Nemec (Norbert Nemec-online.de)'s article
 Hi there,
 I just found that recent change in the language to make all global
 variables thread-local by default. This makes me think of a major
 performance problem: every thread creation will have to copy all the
 thread-local variables. This makes it impossible to efficiently spawn
 many light-weight threads even if they do not make use of the global
 variables at all.
 I guess I am not the first one to spot this problem? I believe that
 thread creation should come with as little overhead as possible. Maybe a
 concept of light-weight threads based on side-effect free code could
 complement the regular threads?
 Just a quick idea to throw into discussion...
 Greetings,
 Norbert
What's wrong with using thread/task pools for these situations?
Feb 24 2010
parent reply Norbert Nemec <Norbert Nemec-online.de> writes:
ds wrote:
 == Quote from Norbert Nemec (Norbert Nemec-online.de)'s article
 Hi there,
 I just found that recent change in the language to make all global
 variables thread-local by default. This makes me think of a major
 performance problem: every thread creation will have to copy all the
 thread-local variables. This makes it impossible to efficiently spawn
 many light-weight threads even if they do not make use of the global
 variables at all.
 I guess I am not the first one to spot this problem? I believe that
 thread creation should come with as little overhead as possible. Maybe a
 concept of light-weight threads based on side-effect free code could
 complement the regular threads?
 Just a quick idea to throw into discussion...
 Greetings,
 Norbert
What's wrong with using thread/task pools for these situations?
That's always an option, of course. It just adds one layer of complexity to the code. If spawning a thread were as cheap as putting a task in a queue you could simply spawn one thread per task and leave it to the scheduler to handle it all. Assuming, of course, that the scheduler is clever enough to handle it efficiently.
Feb 24 2010
parent Stanley Steel <news-steel kryas.com> writes:
On 2/24/10 7:57 AM, Norbert Nemec wrote:
 ds wrote:
 == Quote from Norbert Nemec (Norbert Nemec-online.de)'s article
 Hi there,
 I just found that recent change in the language to make all global
 variables thread-local by default. This makes me think of a major
 performance problem: every thread creation will have to copy all the
 thread-local variables. This makes it impossible to efficiently spawn
 many light-weight threads even if they do not make use of the global
 variables at all.
 I guess I am not the first one to spot this problem? I believe that
 thread creation should come with as little overhead as possible. Maybe a
 concept of light-weight threads based on side-effect free code could
 complement the regular threads?
 Just a quick idea to throw into discussion...
 Greetings,
 Norbert
What's wrong with using thread/task pools for these situations?
That's always an option, of course. It just adds one layer of complexity to the code. If spawning a thread were as cheap as putting a task in a queue you could simply spawn one thread per task and leave it to the scheduler to handle it all. Assuming, of course, that the scheduler is clever enough to handle it efficiently.
The problem is they are divergent. If I spawn a thread to reorder an array for the UI, then of course I use that thread again for the same task, its array hasn't been updated by all the new elements that the original was keeping track of. Right? I guess you could make it shared, but then how is it better than using a traditional language?
Feb 24 2010
prev sibling next sibling parent Stanley Steel <news-steel kryas.com> writes:
On 2/24/10 2:15 AM, Norbert Nemec wrote:
 Hi there,

 I just found that recent change in the language to make all global
 variables thread-local by default. This makes me think of a major
 performance problem: every thread creation will have to copy all the
 thread-local variables. This makes it impossible to efficiently spawn
 many light-weight threads even if they do not make use of the global
 variables at all.

 I guess I am not the first one to spot this problem? I believe that
 thread creation should come with as little overhead as possible. Maybe a
 concept of light-weight threads based on side-effect free code could
 complement the regular threads?

 Just a quick idea to throw into discussion...

 Greetings,
 Norbert
That is why features like "immutability by default" are important. You don't have to copy immutable objects.
Feb 24 2010
prev sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 24 Feb 2010 04:15:03 -0500, Norbert Nemec  
<Norbert nemec-online.de> wrote:

 Hi there,

 I just found that recent change in the language to make all global  
 variables thread-local by default. This makes me think of a major  
 performance problem: every thread creation will have to copy all the  
 thread-local variables. This makes it impossible to efficiently spawn  
 many light-weight threads even if they do not make use of the global  
 variables at all.

 I guess I am not the first one to spot this problem? I believe that  
 thread creation should come with as little overhead as possible. Maybe a  
 concept of light-weight threads based on side-effect free code could  
 complement the regular threads?

 Just a quick idea to throw into discussion...

 Greetings,
 Norbert
Norbert, you are confusing threads with fibers. OS Threads have never been, nor will ever be, "light-weight" in any sense of the word. If they were, no one would care about thread-pools and the like. Languages that feature light-weight threads, such as Erlang, are actually spawning fibers. The Erlang runtime, for example, only ever uses one D style thread to host millions of 'logical' threads. Basic fiber support is already in druntime. Actually, it looks like the std.thread and std.concurrency updates will internally use either a thread pool or a fiber based back-end, so you might not have to worry about it. If you're simply looking for a task library, dsimcha has been working on one as have others (look in scrapple and for the blip project on dsource, IIRC)
Feb 24 2010
next sibling parent reply Norbert Nemec <Norbert Nemec-online.de> writes:
Robert Jacques wrote:
 Norbert, you are confusing threads with fibers. OS Threads have never 
 been, nor will ever be, "light-weight" in any sense of the word.
What I had in mind were discussions about OSes that make thread creation extremely cheap, but indeed: OS threads will probably always carry sufficient overhead to leave plenty of room for application-level mechanism... Does anyone know how expensive thread creation is for typical and for experimental OSes? How does this compare to the overhead of initializing thread-local data? I.e.: How much should one actually worry about TLS?
Feb 24 2010
parent Bane <branimir.milosavljevic gmail.com> writes:
Norbert Nemec Wrote:

 Robert Jacques wrote:
 Norbert, you are confusing threads with fibers. OS Threads have never 
 been, nor will ever be, "light-weight" in any sense of the word.
What I had in mind were discussions about OSes that make thread creation extremely cheap, but indeed: OS threads will probably always carry sufficient overhead to leave plenty of room for application-level mechanism... Does anyone know how expensive thread creation is for typical and for experimental OSes? How does this compare to the overhead of initializing thread-local data? I.e.: How much should one actually worry about TLS?
Your worries looks like 'premature optimization' to me. I had little experieance with similar story while ago, web server that was happily creating bunch of threads for each request. XP handled it well, up to couple hundred threads, then started to suffocate. CentOS did better up to 1000, then some strange bugs emerged. On both I had to do manual memory management as GC wasn't smart enough (finished thead is not deleted thread, and os wont give you more before). Most headaches were. of course, synchronization of operations on complex data types (arrays and such), handles etc. Hate to say it, but there were some issues I couldn't track down, so I switched to multi process instead of multi threaded, and it works fine :D Lot of people are saying that threads are evil. There might be something in it :D
Feb 24 2010
prev sibling parent reply sybrandy <sybrandy gmail.com> writes:
 Norbert, you are confusing threads with fibers. OS Threads have never
 been, nor will ever be, "light-weight" in any sense of the word. If they
 were, no one would care about thread-pools and the like. Languages that
 feature light-weight threads, such as Erlang, are actually spawning
 fibers. The Erlang runtime, for example, only ever uses one D style
 thread to host millions of 'logical' threads.
Actually, newer versions of Erlang now use multiple threads, typically 1 per CPU and one pool of processes and a scheduler per thread. Processes can also be moved between threads in case one is busier than the others. Casey
Feb 24 2010
parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 24 Feb 2010 21:08:02 -0500, sybrandy <sybrandy gmail.com> wrote:

 Norbert, you are confusing threads with fibers. OS Threads have never
 been, nor will ever be, "light-weight" in any sense of the word. If they
 were, no one would care about thread-pools and the like. Languages that
 feature light-weight threads, such as Erlang, are actually spawning
 fibers. The Erlang runtime, for example, only ever uses one D style
 thread to host millions of 'logical' threads.
Actually, newer versions of Erlang now use multiple threads, typically 1 per CPU and one pool of processes and a scheduler per thread. Processes can also be moved between threads in case one is busier than the others. Casey
I looked into this 1 or 2 years ago. Erlang was designed for the cluster, so they just use multiple processes (1 per CPU) not multiple threads. There's very little little overhead to this technique and it was a simple, elegant and trivial solution. Besides there are a lot of pitfalls to going to a true multi-threaded runtime, not the least of which is the GC. There are a lot of technical issues which make moving fibers between threads very dangerous: doing so requires you to be aware of all the operations you can't use/do and to program around them accordingly. Otherwise you end up with data races.
Feb 24 2010