Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: Re: Stress testing a web server

by ibanix (Hermit)
on Jan 05, 2003 at 03:45 UTC ( [id://224367]=note: print w/replies, xml ) Need Help??


in reply to Re: Stress testing a web server
in thread Stress testing a web server

Hi, let me add some information.

The web-server in question is IIS 5.0, and the maximum connections is being enforced via it's virtual server properties. Number of connection attempts per second and established (active) connections are monitored via PerfMon.

The original script was able to generate a maximum of 40 connection attempts per second, for a very short period of time (around 2 seconds). After that, it dropped off to 15 or 20 connections attempts per second. This was enough to for my purposes at the time. I was able to show that the server setting for maximum active connections would be enforced.

As I mentioned below, the question that started this was: 'What is my limiting factor in number of attempted connections per second?' All of the responses posted here have been excellent, and I will use them later if I conduct further testing. I was specially hoping that someone would reply and tell me fork was holding me back, or that I should use system() instead of back-ticks, etc.

Another poster mentioned LWP as being more efficent, another one used IO::Socket. I love these -- but I wonder why they work better? Consume less CPU cycles? Less time to allocate memory? Context switching?

Once again, my thanks.

ibanix

$ echo '$0 & $0 &' > foo; chmod a+x foo; foo;

Replies are listed 'Best First'.
Re: Re: Re: Stress testing a web server
by tachyon (Chancellor) on Jan 05, 2003 at 09:40 UTC

    When you do a system call you actually do a fork() followed by an exec(). From the docs for system():

    Does exactly the same thing as ``exec LIST'' except that a fork is don +e first, and the parent process waits for the child process to comple +te.

    The OS requires a reasonable amount of time to fire up a new process (thus mod perl is faster than vanilla perl as you avoid this overhead) - sure less than a second but often in the order of hundreds of miliseconds.

    With your fork/system call example you have 2 forks (with the time overhead) per hit on the web-server. With the basic LWP method you have only one fork so in rough terms you should get double the kids hitting the server given that forking is a bottle neck, not loading/running code or memory.

    As a variation on the hammer theme described above just make the kids hit the server more than once. If each child hit the server say 50 times you will get a steadily increasing load (as more kids fork off); a sustained peak load (all kids hitting the server); and then a taper as the kids die off. This will give you a very sustained peak load. Don't blame me if your server cries - it is IIS ;-)

    <DISCLAIMER>Quite seriously this sort of code can bring you system to its knees so use with due care. It will in all liklihood saturate the network thus performing a DNS attack on yourself. Perhaps best run after hours.</DISCLAIMER>

    #!/usr/bin/perl -w package Brutal::Web::Server::Test; use strict; use LWP::Simple; my $kids = 100; my $hits_per_kid = 50; my $output; while ($kids) { my $pid = fork; # Parent if ($pid) { $kids--; } elsif ($pid == 0) { do {$output = get('http://www.mysitegoeshere.org') } for 1 .. + $hits_per_kid; exit; } else { die "Fork failed $!\n"; } }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Re: Re: Stress testing a web server
by pg (Canon) on Jan 05, 2003 at 04:33 UTC
    Multi-process is definitely very expansive. I would suggest a single process, single thread solution.
    use IO::Socket::INET; use strict; use constant MAX_CONN => 25; $| ++; my @connections; my $request = "HEAD / HTTP/1.1\r\nConnection: Keep-Alive\r\nHost: www. +google.com\r\n\r\n"; for (1..MAX_CONN) { $connections[$_] = new IO::Socket::INET(proto => "tcp", PeerAddr => "www.google.com", PeerPort => 80); print "."; } print "\n"; while (1) { my $sum = 0; for (1.. MAX_CONN) { my $buffer; if ($connections[$_]) { $sum ++; $connections[$_]->send($request); $buffer = ""; while ($buffer !~ m/\r\n\r\n/) { my $piece; sysread($connections[$_], $piece, 10000); if ($piece eq "") { $connections[$_]->close(); $connections[$_] = undef; last; } else { $buffer .= $piece; } } } else { #get those disconnected back $connections[$_] = new IO::Socket::INET(proto => "tcp", PeerAddr => "www.google.com", PeerPort => 80); } } print "there are $sum connections now\n"; }

Log In?
Username:
Password:

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

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

    No recent polls found