Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

usleep performance under load

Status
Not open for further replies.

dunk2

Technical User
Jun 10, 2002
14
IE
Hi,
I'm using perl to control a sleep on a Solaris 8 platform. It is part of a load test sript. It basically executes a
command line ($smsPath/sstsms -m $null -f $subId -i $psp_3:5014 5555) and then usleeps for a configurable microsecond, before looping again. This works well up to a usleep value of 100_000 microseconds (1/10 sec) and executes the command line 10 times per second. However when I configure the usleep to a lower value 20_000 (1/50 sec) to execute the command line 50 times per second, I do not get the result I am expecting, I get approx 15 command lines per second.
The maximum I have manage to get is 20 command lines per second when setting the usleep to a very low figure 1_000.
Is there a way to increase the performance of this scripts? Or am I using the wrong tool for the job? Would compiled code be better?

Use Time::HiRes;
while ($t2 < $end) {
$t2 = time();

for ($i = 1; $i <= $smsRate; $i++) {
Time::HiRes::usleep $microseconds;
`$smsPath/sstsms -m $null -f $subId -i $psp_3:5014 5555`;
$cntR++;

if ($subId ne '1319099999') {
$subId++;
}
else {
$subId = '1319000000';
}


}
}
 
Dunk2,
Looks like you're running up against the time it takes for the command to complete, so if you take the sleep out altogether, how many iterations can you get

--Paul
 
Hi Paul,

I should have mentioned that did edit out the usleep and it maxed out at 20 per second. I'm monitoring the cpu (using 'top') and the kernel cpu% increases from 5% to 20% when running inputs from 10 per sec to max. There still is idle cpu% available though, about 20%. The binary I'm executing seems to be dynamic, it's cpu% usage shrinks under load - from 70% to 50% using 10 per sec to max.
Any ideas?
 
The process could be IO bound which means that its not just the CPU as a resource that's being used also, the I/O channels which means the CPU has to wait for the IO to finish

HTH
--Paul
 
That makes sense. I may have another 'faster' platform availble next week, which would decrease IO time.
Thanks
 
dunk2

When you sleep, the kernel only knows that it shouldn't dispatch you until after so many microseconds have elapsed. It doesn't guarantee that you will get scheduled at that time, as there are usually other processes on the box, many of which run at a higher priority than you.

As you seem to have spare CPU, another alternative to improve throughput might be to run two or three of these scripts in parallel. Unless your I/O channels are genuinely maxed out you should see some improvement.

Steve
 
Thanks,
I'll try running the scripts in parallel on a faster platform next week, and I'll keep you updated on improvement stats.
 
Steve,
Valid points, though there may be other users on the system, if so dunk2 would not be likely to experience any further significant improvement, as there may be some throttles in place to prevent single users from commandeering too many resources in deference to others.

As it is a load test script, is it likely that'd it'd be wise to have this as the number one resource hog on the system.

Regards
--Paul
 
dunk2,

Two thoughts:

1 If you could use all Perl commands, rather than including an external command, you could significantly increase the amount of CPU your script will take.

2 Your script is already taking up more CPU than you think. The external command is very shortlived and won't show up in top very often. The resources used by repeatedly running that command are not easily quantifiable; another reason to use an all-perl test script.

Mike

Want to get great answers to your Tek-Tips questions? Have a look at faq219-2884

 
Hi,

sorry about the delay in reply. I checked out a few different methods of controlling processes Vs preformance.
I ended up using the system function call running in parallel on two remote boxes. The boxes were comandeered for this purpose only, and produced my required output of 140 commands per sec.

1) `$smsPath/sstsms -m $null -f $subId -i $psp_3:5014 5555`;
The backquotes creates a process, capturing the standard output of the process as a string value for the Perl program. It basically fires off a command and waits for it's completion.

2) system("$smsPath/sstsms -m $null -f $subId -i $psp_3:5014 5555 &");
The system function fires off a new process to execute the shell command, standard IO are inherited from the Perl process. Processes that end in & are launched and not waited to finish, just like the shell.

3) unless (fork) {
exec("$smsPath/sstsms -m $null -f $subId -i $psp_3:5014 5555");
}
The exec is like the system function, except that Perl replaces the current process with the shell. I tried using this with fork but it created a lot of zombies.

4) Another possible way to get an asynchronous process is to open the command as a filehandle, where the pipe is the command's standard IO. Apparently a command opened as a filehandle for reading inherits the std input while a command opened as a filehandle for writing inherits the std output from the Perl program.
I ran out of time to investigate this further.
 
An example I used over on this DS thread:
Code:
use Fcntl qw/LOCK_EX LOCK_UN/;
use constant MAXKIDS => 10;
my $eggs = 100;

$| = 1;
print "$$\n";
pipe(READER,WRITER);

for(my $i = 0; $i < MAXKIDS && $eggs; $i++)
{
        spawn_kid() unless fork();
        $eggs--;
}


while($eggs)
{
        my $kidpid;
        read READER, $kidpid, 4;
        $kidpid = unpack('L',$kidpid);
        print "$kidpid CLEANING\n";
        waitpid $kidpid, 0;
        spawn_kid() unless fork();
        $eggs--;
}

print "donish...\n";
1 while(wait != -1);
close READER;
close WRITER;

sub spawn_kid
{
        my $t = 2 + int rand 5;
        print "$$ START($t)\n";
        sleep $t;
        print "$$ FINISH($t)\n";
        flock WRITER, LOCK_EX;
        print WRITER pack('L',$$);
        flock WRITER, LOCK_UN;
        exit;
}
It shows how you can use a pipe for your child processes to tell the parent they're done so it can clean up after them. It's a trivial example (the "long running" child processing is a random 2-7 second sleep, just to give non-sequential completion), but is likely adaptable to what you're doing.

________________________________________
Andrew - Perl Monkey
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top