Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

threads and low values with Time::HiRes::setitimer

by revdiablo (Prior)
on Sep 05, 2003 at 23:40 UTC ( [id://289385]=perlquestion: print w/replies, xml ) Need Help??

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

Lately I have been playing with threads and Time::HiRes::setitimer. I find it's a pretty neat way to have many threads do something roughly simultaneously. It works quite well, and I haven't had any major problems -- until I started using low values for the interval. I'm trying to have a bunch of worker threads update their state every 0.1 seconds.

So I wrote a little script to play around with threads and timers:

#!/usr/bin/perl use strict; use warnings; use threads; use Time::HiRes qw(setitimer time ITIMER_REAL); my $NUM = 5; # install main signal handler before creating threads $SIG{ALRM} = sub { local $|=1; print time, ": Caught SIGALRM in main\n +" }; setitimer(ITIMER_REAL, 0.1, 0.1); # create all the threads my $tstart = time; threads->create("run_thread", $_) for (1 .. $NUM); my $tdone = time; printf "%d threads in %f seconds == %d threads/second\n\n", $NUM, $tdone - $tstart, $NUM / ($tdone - $tstart); sleep 1 while 1; sub run_thread { my $num = shift; $SIG{ALRM} = sub { local $| = 1; print time, ": Caught SIGALRM in thread $num\n"; print "\n" if $num == $NUM; }; setitimer(ITIMER_REAL, 0.1, 0.1); sleep 1 while 1; }

With $NUM set to 5, things seem to work as expected. Here's some sample output:

5 threads in 0.079028 seconds == 63 threads/second 1062803574.97634: Caught SIGALRM in main 1062803574.99621: Caught SIGALRM in thread 1 1062803575.02622: Caught SIGALRM in thread 2 1062803575.02631: Caught SIGALRM in thread 3 1062803575.04619: Caught SIGALRM in thread 4 1062803575.05619: Caught SIGALRM in thread 5 1062803575.07617: Caught SIGALRM in main 1062803575.09617: Caught SIGALRM in thread 1 1062803575.12616: Caught SIGALRM in thread 2 1062803575.12621: Caught SIGALRM in thread 3 1062803575.14616: Caught SIGALRM in thread 4 1062803575.15617: Caught SIGALRM in thread 5

First, notice that my system is creating about 63 threads per second (this number is actually fairly stable, surprisingly). That's about 6 threads in 1/10th of a second. Now, notice how close the time values are for thread 5 in the 1st group and main in the 2nd group.

Where I'm getting problems is when I try to use more threads than my system can construct in 1/10th of second. If I change $NUM to 7, I get unreliable and unexpected behavior. Sometimes the groups just overlap, as I would expect. Sometimes perl segfaults. Sometimes I get "runaway" threads that don't seem to follow the interval timer at all. I'm not sure what's causing this behavior, and frankly it's out of my league trying to figure it out.

What my question is really about, is what can I do to workaround this? I can think of a few possible solutions:

  1. Don't set the itimer to such a low value. This might be the only acceptible way, though I hope not.
  2. Synchronize the threads so they all start their itimers at closer to the same exact time. This might not be feasible -- they're already starting pretty close to the same time. It might be difficult to correct the 1/100th of a second skew. Even if it's possible, I don't have any good ideas how.
  3. Threads are stupid. So are signals. Stop bothering us.
  4. ...?

Hopefully the ever reliable monks will come up with some ideas for me... :)

Replies are listed 'Best First'.
Re: threads and low values with Time::HiRes::setitimer
by liz (Monsignor) on Sep 06, 2003 at 08:25 UTC
    I guess I have two questions for you:
    1. How many CPU's does your computer have?
    2. How many threads do you think a single CPU can handle simultaneously?

    Then think about what you're trying to achieve.

    I would like to point out that Perl ithreads are not lightweight. Whatever you're trying to achieve is so very CPU dependent that you will never be able to do that in Perl 5 with the current ithreads implementation.

    Maybe you can do what you want using POE.

    Or try using C and POSIX threads. But even then you should realize that (most modern) thread implementations depend on a scheduler that decides to give the next timeslice to this or an other thread. Such a scheduler is usually dependent on some hardware timer event. Once you get close to the resolution of that timer event, you're going to see "disturbances". If you know any physics, think "waves" versus "photons".

    Hope this helps.

    Liz

      How many threads do you think a single CPU can handle simultaneously?

      Well, maybe my question didn't accurately reflect my intentions. I don't necessary want all this stuff to happen simultaneously but just closer to eachother than it currently is (this is what I meant when I said "roughly simultaneously"). Maybe asking for my code to trigger closer than a few 100ths of a second is too much? (This is not a rhetorical question. I really don't know if this is reasonable or not.) If so, I'll think of another approach... though I must admit I was quite excited to be using threads for something like this. =)

      Maybe you can do what you want using POE.

      This may be my next best option. I'll definitely take a good look if I can't get the threads to work.

      Hope this helps.

      Definitely. Thanks very much for the reply.

      PS: Your Things you need to know before programming Perl ithreads post is partially what made me want to play with threads in the first place. I'm not sure if that will be more or less reassuring to you, considering what I'm trying to do. Perhaps I entirely missed the point of your post? :)

        ...Maybe asking for my code to trigger closer than a few 100ths of a second is too much?

        I think it is. I must admit I don't know the kernel nitty gritty of this, but I'm fairly sure that timer 0 (check procinfo on Linux) is related to forced context switches (context switches forced by the Operating System when a thread/process is using more than it's alotted). That timer runs at a frequency of around 100Hz.

        Liz

      How many threads do you think a single CPU can handle simultaneously?

      Maybe slightly OT, but do you happen to know how a Hypertreaded Xeon processor deals with this? The only processors of that type i have access to are on production machines with 5.6.1, so it's not very usefull to test on those i think.

      Kind regards,
      Deliria.
Re: threads and low values with Time::HiRes::setitimer
by Anonymous Monk on Sep 06, 2003 at 01:55 UTC
    perl threads and signals don't mix, so don't mix them. that is all.
      I think a more accurate statement is:
      Threads and signals currently only mix on Linux.
      

      Liz

      Are you sure? I see nowhere in the threads or the signals documentation that indicates this is the case. Perhaps I'm just overlooking it, and you can point out some documentation showing me otherwise?

      PS: I'm using perl 5.8.0.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2024-04-23 11:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found