D
dmitrym
Afternoon ladies and gentlemen. I have a strange problem that
I've ran into, and I'd appreciate any and all input that you can
provide.
Essentially, I'm writing a quick and dirty stress test script
with WWW::Mechanize. For the purposes of development, I worked on
the single process version first. I ran my script and got about
0.5 seconds per transaction. To make matters more interesting, I
modified my script so that there's an option to spawn multiple
threads with fork(). Here's where the interesting stuff begins.
Even with two threads, the performance fell sharply, to around
1.5 seconds/transaction. Increasing the threads count provided
for further degradation.
Now the obvious thing would be to assume that the remote service
is slowing down, however this is not so. I simply ran 2 instances
of the the single thread versions of my script and received the initial
0.5
seconds/thread results. Furthermore, some of the stress scripts
are implemented in jmeter which seem to indicate that the remote
service is capable of far more throughput that I'm doing with my
perl script.
I combed through the script but couldn't find anything that would
explain the delay. I then went and wrote a simple script to
emulate what I'm doing and the results are similar.
If I start a single process, I get an average of about 0.0001
second per "transaction" (which in this case is a few hundreds of
iteration of a square root).
If I start a single process which spawns 2 threads, I get about
0.0004 seconds per transaction.
If I start two single thread processes they'll run at around
0.0001 seconds/transaction.
So why is this happening? As far as I know, fork() will just copy
all the data (might be slow, but I dont care about that) and then
the two processes go their separate ways. So why isn't this
happening, and why are my processing slowing down significantly
with moderate increase in thread number?
Here's the script I used to for playing around. Modify the
$threads and $iterations and it'll dump the average time per
transaction and standard deviation.
I'll appreciate any insight.
Thanks.
Script is attached below:
-------------------------
#!/usr/bin/perl -w
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep );
use Statistics:escriptive;
use File::Temp qw/ tempfile tempdir /;
use strict;
use diagnostics;
my $threads = 2;
my $iterations = 100;
my ($fh, $STAT) = tempfile();
# let every thread do it's thing.
for(my $i = 0; $i < $threads; ++$i)
{
my $pid = fork();
if (!$pid)
{
sleep(1);
for(my $k = 0; $k < $iterations; ++$k)
{
my $t0 = [gettimeofday()];
for(my $j = 0; $j < 1000; ++$j)
{
my $asdf = sqrt(123234234234123);
}
my $elapsed = tv_interval ($t0);
#print "$elapsed\n";
writeStat($elapsed);
}
exit(0);
}
}
# sleep waiting for threads to finish.
for (my $i = 0; $i < $threads; ++$i)
{
wait();
}
analyzeStats();
exit(0);
# done
sub writeStat
{
my $time = shift;
open (STAT, ">>$STAT");
print STAT $time . "\n";
close(STAT);
}
sub analyzeStats
{
print "Analyzing stats...\n";
open (STAT, "$STAT");
my @data;
while(<STAT>)
{
chomp; chomp;
push (@data, $_);
}
if (@data)
{
my $stat = Statistics:escriptive::Full->new();
$stat->add_data(@data);
print "Mean time per wager: " . $stat->mean() . "
seconds\n";
if (scalar(@data) > 1)
{
print "StdDev : " .
$stat->standard_deviation() . " seconds\n";
}
}
else
{
print "There appears to be no data.\n";
}
}
PS: I have posted this in comp.lang.perl.moderated originally, but I'm
not getting many responses there.
Cheers.
I've ran into, and I'd appreciate any and all input that you can
provide.
Essentially, I'm writing a quick and dirty stress test script
with WWW::Mechanize. For the purposes of development, I worked on
the single process version first. I ran my script and got about
0.5 seconds per transaction. To make matters more interesting, I
modified my script so that there's an option to spawn multiple
threads with fork(). Here's where the interesting stuff begins.
Even with two threads, the performance fell sharply, to around
1.5 seconds/transaction. Increasing the threads count provided
for further degradation.
Now the obvious thing would be to assume that the remote service
is slowing down, however this is not so. I simply ran 2 instances
of the the single thread versions of my script and received the initial
0.5
seconds/thread results. Furthermore, some of the stress scripts
are implemented in jmeter which seem to indicate that the remote
service is capable of far more throughput that I'm doing with my
perl script.
I combed through the script but couldn't find anything that would
explain the delay. I then went and wrote a simple script to
emulate what I'm doing and the results are similar.
If I start a single process, I get an average of about 0.0001
second per "transaction" (which in this case is a few hundreds of
iteration of a square root).
If I start a single process which spawns 2 threads, I get about
0.0004 seconds per transaction.
If I start two single thread processes they'll run at around
0.0001 seconds/transaction.
So why is this happening? As far as I know, fork() will just copy
all the data (might be slow, but I dont care about that) and then
the two processes go their separate ways. So why isn't this
happening, and why are my processing slowing down significantly
with moderate increase in thread number?
Here's the script I used to for playing around. Modify the
$threads and $iterations and it'll dump the average time per
transaction and standard deviation.
I'll appreciate any insight.
Thanks.
Script is attached below:
-------------------------
#!/usr/bin/perl -w
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep );
use Statistics:escriptive;
use File::Temp qw/ tempfile tempdir /;
use strict;
use diagnostics;
my $threads = 2;
my $iterations = 100;
my ($fh, $STAT) = tempfile();
# let every thread do it's thing.
for(my $i = 0; $i < $threads; ++$i)
{
my $pid = fork();
if (!$pid)
{
sleep(1);
for(my $k = 0; $k < $iterations; ++$k)
{
my $t0 = [gettimeofday()];
for(my $j = 0; $j < 1000; ++$j)
{
my $asdf = sqrt(123234234234123);
}
my $elapsed = tv_interval ($t0);
#print "$elapsed\n";
writeStat($elapsed);
}
exit(0);
}
}
# sleep waiting for threads to finish.
for (my $i = 0; $i < $threads; ++$i)
{
wait();
}
analyzeStats();
exit(0);
# done
sub writeStat
{
my $time = shift;
open (STAT, ">>$STAT");
print STAT $time . "\n";
close(STAT);
}
sub analyzeStats
{
print "Analyzing stats...\n";
open (STAT, "$STAT");
my @data;
while(<STAT>)
{
chomp; chomp;
push (@data, $_);
}
if (@data)
{
my $stat = Statistics:escriptive::Full->new();
$stat->add_data(@data);
print "Mean time per wager: " . $stat->mean() . "
seconds\n";
if (scalar(@data) > 1)
{
print "StdDev : " .
$stat->standard_deviation() . " seconds\n";
}
}
else
{
print "There appears to be no data.\n";
}
}
PS: I have posted this in comp.lang.perl.moderated originally, but I'm
not getting many responses there.
Cheers.