learnedbyerror has asked for the wisdom of the Perl Monks concerning the following question:

Oh Monks,

Please tolerate yet another question from the village idiot :)

I would very much like to achieve the functionality of Thread::Pool::Simple; however, I often see posts about the ills of using modules for thread pools. How should I proceed forward?

Creating a pool of threads is straight forward; however, insuring that they run without error on long running worker threads ( 100 - 200K executions per worker) is a problem in my case. I need to start a new worker up if one of my worker threads abends.

I have placed eval around pretty much everything that I can think of and have a wrapper that I use to restart the worker sub in a thread if the sub exits unexpectedly. The combination of the two has my app running pretty damn realiably. But, it is not quiet reliable enough to put in a batch environment and ignore.

What I like about Threads::Pool::Simple and the ilk is the purported ability to start a new thread if the wrapper et al gets blown away. My worker threads do not depend upon the thread manager (i.e. Boss) to send any data to them or to process any data upon completion. The worker threads do this on their own either through Thread::Queues or based upon date from a MySQL database. So freeze/thaw issues aren't a concern of mine.

My concern is that I really don't want to have to crank crank my own handler and the associated HOH to manage the state, on my own if I can help it.

Can anyone recommend an approach or point me to sample code that addresses Boss/Worker Pool thread management?

Thanks in advance, lbe

Replies are listed 'Best First'.
Re: Thread::Pool::Simple || !
by BrowserUk (Patriarch) on Jul 17, 2012 at 18:18 UTC
    . But, it is not quiet reliable enough to put in a batch environment and ignore.

    Hm. If it is "not reliable"; how does it break? And why haven't you wrapped that bit in an eval?

    Come to that; why are you wrapping bits of the code in eval, why not just wrap all of it? Eg.

    sub worker { my( ... ) = @_; eval { ... ... return 1 if <cond>; ... 1; } or threads->create( \&worker, @_ ); }

    Just remember that when you want to quit the thread permanently, to drop out of the bottom of the eval block, or return a true value to avoid the restart.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    The start of some sanity?

Re: Thread::Pool::Simple || !
by bulk88 (Priest) on Jul 18, 2012 at 08:48 UTC
    What are your threads dieing from? they are done running code/returned to caller? If your threads are dieing from something an eval can't catch, you have other problems.

      I'll combine my response to both BrowserUK and bulk88 together.

      BrowserUK, my threads are wrappped as you have shown.

      Both - I have not been able to identify the cause of the threads failing. I suspect that I am probably tripping on some unholy synchronization between the OS (RH15 - 2.6.32.308.el5stab099.3 currently), perl's thread implementation (5.12.4 currently)and my code. The failures happen intermittently recurring anywhere from 1 hour to 1 week/month. My guess is that something is going on the the "thread unit of execution" where there is a failure from an eval and that before perl can recover on the next step, the OS steps in and terminates that unit before perl can log or recover. In all honesty, this is a SWAG or maybe a WAG. I have not been successful in findinb the root cause.

      Yesterday afternoon, I started an alternative approach. I have added a sub that I call check_threads to my thread management module. This sub checks to see if all of the thread objects registered are still running or joinable, if not, it calls my start_threads sub to add a replacement thread(s). Given my current use of Thread::Queue to feed the threads, the new thread(s) will dequeue and proceed. I will loose the work against the data that the failed thread dequeued. This is acceptable in my case as subsequent executions of the overall process will pick it up.

      I'm fairly confident that this approach will get me to the reliability and performance levels that I need. But, I'm not too happy with the overall code. I "feel" like I have had to write too much code and have, in my ignorance, missed a "better" way of getting my work done. With all of my code functioning, I am going through one more refactoring effort primarily to insure supportability of the code. Once in production and when I get a bit of free time, I want to come up with a test scenario, that I can share freely, and throw out here to get more brains looking at it. I want to go back and test it against the models on CPAN that I tried earlier as well as Coro which I deselected because of a preference to not use coroutines. I also want to look at Perl6 and possibly functional languages like Erlang and Haskell.

      My gut is still telling me that there is a simpler approach to this than what I have. If there isn't, then I need to spiff up my thread management kit and put it up on CPAN.

      Cheers, lbe

        The failures happen intermittently recurring anywhere from 1 hour to 1 week/month. My guess is ...
        I want to go back and test it against the models on CPAN that I tried earlier

        To paraphrase: I've a bug in my code which I can't be bothered to track down and I'm hoping there is a CPAN module that will allow me to conceal it.

        BrowserUK, my threads are wrappped as you have shown.

        Then how do you know threads are failing? Are you logging errors? Logging when threads end? How?

        My gut is still telling me that there is a simpler approach to this than what I have. If there isn't, then I need to spiff up my thread management kit and put it up on CPAN.

        NO! NO! Please no! There is enough ill-conceived, bug-ridden, utterly useless, "threading management" crap on CPAN already.

        It is no wonder so many people are put off from using Perl's threading, given their first experiences of it are installing a module with a fanciful named, (and often as not, with a positive CPAN rating or two from know-nothing sycophants), only to discover that it is either completely broken -- or worse -- kind of works some of the time, but every now and again, silently throws away a bunch of work items.

        Even if your application is tolerant of your threads module throwing work away every now and again, please don't "spiff it up" with a little concealer and foist it upon unsuspecting others.

        If you truly believe that your threads management module is a) generic enough; b) lightweight enough; and c) reliable enough; to have the potential to become a widely deployable thread-pool module -- and you obviously aren't there yet -- then post it here along with your current application -- suitably cut-cown and anonymised as necessary -- and let us help you solve the known problem.

        Once we've done that, I'll willingly throw a few of my testcase applications at it and see if it a) actually works for them; b) is actually any simpler and/or better than hand-coding.

        As you may be aware, I am pretty skeptical that it is possible to write a properly generic thread-pool solution that isn't actually more complex than hand-coding them to fit the specific application. But I am willing to be proved wrong. And more than willing to help prove me wrong, if I see an architecture/API that seems to work.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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.

        The start of some sanity?