1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| | #!/usr/bin/perl -w
# Benchmark script to spawn some processes and hammer a local unicorn
# to test accept loop performance. This only does Unix sockets.
# There's plenty of TCP benchmarking tools out there, and TCP port reuse
# has predictability problems since unicorn can't do persistent connections.
# Written in Perl for the same reason: predictability.
# Ruby GC is not as predictable as Perl refcounting.
use strict;
use Socket qw(AF_UNIX SOCK_STREAM sockaddr_un);
use POSIX qw(:sys_wait_h);
use Getopt::Std;
# -c / -n switches stolen from ab(1)
my $usage = "$0 [-c CONCURRENCY] [-n NUM_REQUESTS] SOCKET_PATH\n";
our $opt_c = 2;
our $opt_n = 1000;
getopts('c:n:') or die $usage;
my $unix_path = shift or die $usage;
use constant REQ => "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
use constant REQ_LEN => length(REQ);
use constant BUFSIZ => 8192;
$^F = 99; # don't waste syscall time with FD_CLOEXEC
my %workers; # pid => worker num
die "-n $opt_n not evenly divisible by -c $opt_c\n" if $opt_n % $opt_c;
my $n_per_worker = $opt_n / $opt_c;
my $addr = sockaddr_un($unix_path);
for my $num (1..$opt_c) {
defined(my $pid = fork) or die "fork failed: $!\n";
if ($pid) {
$workers{$pid} = $num;
} else {
work($n_per_worker);
}
}
reap_worker(0) while scalar keys %workers;
exit;
sub work {
my ($n) = @_;
my ($buf, $x);
for (1..$n) {
socket(S, AF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
connect(S, $addr) or die "connect: $!";
defined($x = syswrite(S, REQ)) or die "write: $!";
$x == REQ_LEN or die "short write: $x != ".REQ_LEN."\n";
do {
$x = sysread(S, $buf, BUFSIZ);
unless (defined $x) {
next if $!{EINTR};
die "sysread: $!\n";
}
} until ($x == 0);
}
exit 0;
}
sub reap_worker {
my ($flags) = @_;
my $pid = waitpid(-1, $flags);
return if !defined $pid || $pid <= 0;
my $p = delete $workers{$pid} || '(unknown)';
warn("$pid [$p] exited with $?\n") if $?;
$p;
}
|