in reply to Re: use less 'CPU'
in thread use less 'CPU'

Firstly, I want to thank you. It's rare case to get interesting long reply.

I 100% agree with importance of all these guidelines. In my work I use all these guidelines except portable limits (because I've no needs and no ability to test my code on non-linux systems and also in many cases make code portable mean make it slow).

I also agree about my code quality in resource control: CPU - this code was just an example and not really useful because it's too slow (for my tasks at least). But at start of this thread I say "improved, simplifyed and optimized". :-)

About protable code... I don't see any other realization for limiting CPU load issue. My solution based on using things like fork() and signals. I suppose this solution are not really portable, but should work on all/most *NIX systems. And I've seen other people asking about this feature. Really, any who execute long-running process which is working instead of waiting for some event need this feature. And using plain sleep() to free some CPU is ugly solution because it's very hard to know "how much to sleep" to free some CPU and at some time do it work as quickly as possible. So, I think it better to have *NIX-only solution than have no solution.

Here is my current code. I don't see any more possible improvements in main logic, but interface will change because I will package it as module or pragma. Can you please point me to anything not adequate to guidelines except porting one?

# SYNOPSYS # # # start new alarm (fork new process) # $alarm_id = alarm_start(0.01, \$counter); # # # stop alarm (kill forked process) # alarm_stop($alarm_id); # # # sleep without been interrupted by signals # sleepy(0.5); # # # limit CPU usage to 10% # Limit_CPU(); # use Time::HiRes qw(time alarm setitimer ITIMER_PROF); { my %ALARM; sub alarm_start { my ($PARENT, $time, $counter) = ($$, @_); return unless $time > 0; return unless my ($n) = grep { not exists $ALARM{$_} } "NUM50" .. "NUM59"; $SIG{$n} = ref($counter) eq "SCALAR" ? sub { $$counter++ } : ref($counter) eq "CODE" ? sub { local $SIG{$n}="IGNORE"; &$counter } : return; return $n if $ALARM{$n} = fork(); $0 .= " ALARM $n"; $SIG{ALRM} = sub { kill $n, $PARENT or exit }; alarm($time, $time); CORE::sleep 1 while 1; } sub alarm_stop { return unless exists $ALARM{$_[0]}; local $SIG{CHLD} = $SIG{$_[0]} = "IGNORE"; kill 9, $ALARM{$_[0]} and waitpid delete $ALARM{$_[0]}, 0; }} sub sleepy { my $alarm = alarm_start($_[0], \(my $wakeup)) or die "sleepy: alarm failed"; # die or return? CORE::sleep 1 until $wakeup; alarm_stop($alarm); } use constant CPUMAX => 10; # percent, max CPU load by this process use constant INT => 0.1; # sec, how often check for CPU overload { my ($real, $prof, $wait); $SIG{PROF} = sub { $prof++ }; sub Limit_CPU { setitimer(ITIMER_PROF, INT, INT); alarm_start(INT, sub { $wait = ($prof*(100/CPUMAX) - ++$real) / (1/INT); return if INT > $wait; sleepy($wait); $real += int( $wait * (1/INT) ); }); }}

Replies are listed 'Best First'.
Re: Re: Re: use less 'CPU'
by iburrell (Chaplain) on Feb 14, 2003 at 21:05 UTC
    What is wrong with using "nice" to lower the priority of the long-running process? That way the process gets to use all of the CPU when there is nothing else running but doesn't slow down normal processes. The operating system handles the scheduling efficiently. No polling, busy loops, or extra signals required.
      1. This process will take 100% CPU until other process, also very greedy to CPU will execute. Most system administrators, especially web hosting ones, dislike processes take 100% CPU, no matter they use "nice" or not.
      2. Code sometimes contain bugs. Sometimes bug initiate an infinite loop which only take CPU and do nothing. This slow down overall system very much and this slowdown can be detected many time after: for example, some time ago I execute such script in background and log out from system, and then log in after 10 hours (because I estimate time to finish this script to 10 hours) and found very slow system and a lot of complains from customers "why system was too slow yesterday?". My solution allow to limit maximum CPU load and no bug can break this limit.
      3. It's nice to have ability to control how greedy for CPU your script can be. It's nice to have simple way to control speed of your script. And it was very interesting to develop this solution!