romele / git-trace public
62 commits · 1 branch · 1 tag · 1 contributor (top: Romele) · first commit 3d ago · last push 11m ago
tests/load.pl
#!/usr/bin/perl # tests/load.pl — honest load numbers for git-trace. # # Phase A: N workers x R sequential GETs on "/" (browse path) # Phase B: N workers x R GETs on /<repo>.git/info/refs?service=git-upload-pack # (the smart-HTTP fetch path, CGI + git http-backend) # # Each worker is a fork()ed child writing its timings over a pipe. # Usage: perl tests/load.pl http://host:port [workers] [reps] use strict; use warnings; use IO::Socket::INET; use Time::HiRes qw(time); my $base = shift or die "usage: $0 http://host:port [workers] [reps]\n"; my $W = shift // 8; my $R = shift // 25; my ($host, $port) = $base =~ m{^https?://([^:/]+)(?::(\d+))?} or die "bad base url\n"; $port //= 80; sub timed_get { my ($path) = @_; my $t0 = time(); my $s = IO::Socket::INET->new( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', Timeout => 10); return -1 unless $s; print $s "GET $path HTTP/1.1\r\nHost: $host:$port\r\n" . "Connection: close\r\n\r\n"; my $ok = 0; while (my $l = <$s>) { $ok += length $l } close $s; return time() - $t0; } sub hammer { my ($path, $label) = @_; pipe(my $rd, my $wr) or die "pipe: $!"; my $t0 = time(); for my $i (1 .. $W) { if (fork() == 0) { # child close $rd; for (1 .. $R) { my $d = timed_get($path); printf $wr "%.4f\n", $d; } exit 0; } } close $wr; my @ms; while (<$rd>) { push @ms, $_ * 1000 } close $rd; wait for 1 .. $W; my $wall = time() - $t0; @ms = sort { $a <=> $b } @ms; my $n = @ms; my ($sum) = 0; $sum += $_ for @ms; printf "%-14s n=%-4d wall=%.1fs rps=%.0f avg=%.1fms " . "p50=%.1fms p95=%.1fms max=%.1fms\n", $label, $n, $wall, $n / ($wall || 1), $sum / $n, $ms[int($n * .50)], $ms[int($n * .95)], $ms[-1]; return $n; } print "== load: $W workers x $R reqs against $base ==\n"; hammer("/", "GET /"); hammer("/alice/demo.git/info/refs?service=git-upload-pack", "info/refs"); print "== done ==\n";