Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Score: Perl 1, Ruby 0

by BrowserUk (Patriarch)
on Feb 21, 2006 at 07:33 UTC ( [id://531636]=note: print w/replies, xml ) Need Help??


in reply to Score: Perl 1, Ruby 0

As pointed out, Ruby's threads aren't kernel threads. The scheduling is done by Ruby itself which means that individual opcodes aren't preempted. As backticks are a single opcode, regardless of what you put in them, the opcode won't return, and therefore can't be preempted until the command has finished.

However, you can avoid that by using IO.popen and reading the commands output 1 line at a time

t1 = Thread.new { output = []; cmd = IO.popen( "dir /s u:\\", 'r' ); while cmd.gets output.push $_ end Thread.current["output"] = output } ... t1.join got = t1["output"] got.each{|line| puts line}

That said, you don't appear to be using the output from the backticks, so you probably shouldn't be using them anyway.

As with Perl's threads, you gotta learn to use'em right :)

The nice thing about Ruby's threads is that they are very light. When playing with them a while ago I modified the simple example from the Ruby book and started 100,000 of them concurrently and it only required 130 MB.

With Perl's threads you'll be limited to 64 120* concurrent under Win32 (a Perl implementation limit not Win32), and they will consume 40 MB for even the simplest of subs.

*Update:The limit used to be the same as the pseudo-processes limit, which is still 64, but the threads limit (as of 5.8.6) has been raised to 120. This discovered via the use of the following snippet:

use threads; @t = map{ threads->create( sub{ print threads->self->tid; sleep 60; print threads->self->tid; } ) or die "threads->create failed $^E" } 1 .. 1000;

Which produces

C:\test>maxthreads.pl 1 2 3 ... 116 118 117 threads->create failed Not enough storage is available to process this + command at C:\test\maxthreads.pl li A thread exited while 120 threads were running.

Update2: Having given up trying to unwind the multitude of defines equivalences that surround PERL_GET_CONTEXT

PERL_SET_CONTEXT(aTHX) PERL_SET_CONTEXT((aTHX = PL_sharedsv_space)) PERL_SET_CONTEXT((aTHX = caller_perl)) PERL_SET_CONTEXT(interp) PERL_SET_CONTEXT(aTHX) PERL_SET_CONTEXT(thread->interp) PERL_SET_CONTEXT(aTHX) PERL_SET_THX(t) PERL_SET_CONTEXT(t) PERL_SET_CONTEXT PERL_SET_INTERP(i) Perl_set_context((void*)t) cthread_set_data(cthread_self(), t) (PL_current_context = t) PERL_SET_THX(t) PERL_SET_CONTEXT(t) PERL_SET_CONTEXT(proto_perl);
(and the associated mess that is the whole aTHX pTHX pTHX_ thing), I gave up and took a different tack, that of asking the operating system what TLS indexes are being used. The upshot is that whatever the storage is that is being run out of, it isn't TLS indexes.

From what I can work out, the storage in question is Thread Local Storage, which is a limited resource of 1088 32-bit words per process. The current limit of 120 threads suggests that perl is using 9 or 10 32-bit words of TLS per thread. I think I once suggested that this data could be allocated from the heap, and just a single pointer to it stored in TLS. One extra level of indirection would raise the limit to the OS maximum. There may be considerations relating to the architecture of Perl that make this suggestion impractical.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: Score: Perl 1, Ruby 0
by renodino (Curate) on Feb 21, 2006 at 23:50 UTC
    Thnx for the great info. I went stomping around the 5.8.7 source, and located the TlsAlloc() call (in the ALLOC_THREAD_KEY macro), but can't find more than a couple instances of ALLOC_THREAD_KEY being called...probably requires a hard-core debug effort to track down why/where so many are needed. (Unless any of the p5p'ers out there might shed some light ?)

    I also googled about to see if I could find a registry key to tweak Win32's limit, but wo/ luck, it appears to be a hardcoded value.

    Which is a bit puzzling, given Win32's preference for threading vs. forking. Considering that dual core CPU laptops are now available, and both AMD and Intel have announced quadcores for next year, I'd hope hardcoding this value might need re-examination, if they intend to play in the high end server market. (And the constant's name seems backwards: TLS_MINIMUM_AVAILABLE actually means the maximum available). Guess I'll have to wait and see what Vista brings.

    I guess one can point fingers of shame at both Perl and Win32. Fortunately, 120 threads is sufficient for my needs on Win32 at present.

      I went stomping around the 5.8.7 source, and located the TlsAlloc() call (in the ALLOC_THREAD_KEY macro), but can't find more than a couple instances of ALLOC_THREAD_KEY being called...probably requires a hard-core debug effort to track down why/where so many are needed.

      I've been down that route before and become very lost in the myriad definition and redefinitions of everything that surrounds the whole PERL_GET_CONTEXT/Perl_get_context/aTHX stuff. I just tried again and got royally stuffed trying unwind the macros. Compilers are good at doing that--people (at least this person) ain't.

      Upshot: Took a different tack and queried information about the TLS indexes from the OS from with in the thread itself, and whatever storage is being run out of, it isn't TLS!


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      it appears to be a hardcoded value. Which is a bit puzzling, given Win32's preference for threading vs. forking.

      The limit represents 1088 stateful threads per process, but threads do not have to be, and frequently are not stateful. At the C level, you can easily run 2000+ threads per process if they are not stateful. And remember this is concurrent. You can create fast-lived, do & die threads by the bucket load if that is what the design calls for.

      Also, many of the things you might consider spawning a thread for, like waiting for IO, there is no need for a separate thread as you can use asyncIO. You supply a callback on the read or write and let the OS call you back when it completes. I've seen a server application that could handle very high numbers of concurrent connections written this way, that only used 2 threads.

      I agree with you that 120 threads is more than enough from Perl, given the inherent weight of iThreads. For most purposes, I'd advocate using a mere handful of long running threads rather than zillions of short lived. It just makes best use of the resources available.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: Score: Perl 1, Ruby 0
by Anonymous Monk on Mar 28, 2007 at 17:28 UTC
    t1 = Thread.new { output = []; cmd = IO.popen( "dir /s u:\\", 'r' ); while cmd.gets output.push $_ end Thread.current["output"] = output } ... t1.join got = t1["output"] got.each{|line| puts line}
    This code doesn't give the intended results. I'm still limited as to how many threads I can kick off.
      This code doesn't give the intended results.

      Who's (and what) intended purpose? It certainly served my intended purpose--that of discovering the limit of concurrent threads runnable using the Perl executable when built with the default Win32 configration.

      I'm still limited as to how many threads I can kick off.
      1. Why are you doing this? Is your purpose to simply run lots of threads, or have you a Perl application that you believe would benefit from running >120 concurrent threads.

        If the former, the snippet was not intended to, and could not, bypass the inherent limitations of the Perl executable.

        If the latter, in most cases you should probably think again about your design. If you really believe that you have an application that does benefit from more than 120 concurrent iThreads, then see point 2.

      2. It is possible to modify a (copy of) a win32 Perl executable to allow more than 120 threads to run concurrently. See my post at Use more threads. for the how.

        That said, that post only addresses the how, not the why. To usefully make use of more than 120 concurrent iThreads requires much more than just changing the limit. It also requires that you adopt some very specific coding practices to avoid or work around other limitations inherent in the iThreads architecture.

        These practices are neither intuative, nor what would be readily recognised as standard Perl working practice. They are described, piecemeal, across a whole bunch of posts (by me and others, notably zentara,jdhedden & renodino) here at PM, but to my knowledge there is no one place here or elsewhere that brings all the details together in a comprehensive reference. In part, because I don't think that anyone has really done enough work in multi-cpu environments to have yet tied down what best working practice should be.

      If you still believe you have an application that would benefit from running large numbers of concurrent ithreads, if you were to post a description of that problem, you may well get further advise on implementing it. Along with advice on the possible alternatives to ithreads for achieving your goal.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://531636]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2024-04-18 15:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found