{'userid'},"mcrate:$u->{'userid'}"]) : undef; my $ret; my $mode = $GET{'mode'}; if ($GET{'host'}) { $mode ||= "host"; } $mode ||= "overview"; $ret .= "
[Overview]\n"; if ($mode eq "overview") { $ret .= <<"END_TOP";

Memory Cache Overview

END_TOP } my %now_hits; if ($prev_hits) { %now_hits = %$prev_hits; } my ($tot_hits, $tot_misses) = (); foreach my $entry (@LJ::MEMCACHE_SERVERS) { my $host = ref $entry ? $entry->[0] : $entry; next if $mode eq "host" && $host ne $GET{'host'}; LJ::MemCache::forget_dead_hosts(); my $sock = Cache::Memcached::sock_to_host($host); my $t1 = Time::HiRes::time(); my $log; my %stat; my @cmds = ("", "malloc", "items", "slabs"); my $cmd; if ($sock) { while (defined($cmd = shift @cmds)) { my $realcmd = "stats" . ($cmd ? " $cmd" : ""); $log .= "$realcmd\n"; foreach (LJ::MemCache::run_command($sock, "$realcmd\r\n")) { last if $_ eq "END\r\n"; $log .= $_; next if $cmd eq "maps"; if (/^STAT (\S+) (\S+)/) { $stat{$cmd}{$1} = $2; } } } } my $t2 = Time::HiRes::time(); my $cpu = 0; foreach my $key (qw(rusage_user rusage_system)) { my $sec = $stat{''}{$key}; $sec =~ s/:/\./; $cpu += $sec; #$ret .= "Host $host was $stat{''}{$key} = $sec, cpu = $cpu
\n"; } $now_hits{$host} = [ $stat{''}{'get_hits'}, $stat{''}{'get_misses'}, $cpu ]; my $hit_rate = sprintf("%0.02f%%", $stat{''}{'get_hits'}/($stat{''}{'get_hits'}+$stat{''}{'get_misses'}||1)*100); if ($mode eq "overview") { $ret .= "\n"; $ret .= ""; my $gb_used = ($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) / (1024*1024*1024); my $gb_max = $stat{''}{'limit_maxbytes'} / (1024*1024*1024); if ($gb_used >= $gb_max) { $ret .= sprintf("", $gb_max); } else { $ret .= sprintf("", $gb_used, $gb_max, $gb_used*100/($gb_max||1)); } my $utiliz = $stat{''}{'bytes'} / (($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) || 1); $ret .= sprintf("", $utiliz*100); my $up = $stat{''}{'uptime'}; my $upstring; foreach my $u ([86400,"d"],[3600,"h"],[60,"m"],[1,"s"]) { if ($up / $u->[0] > 1) { my $v = int($up / $u->[0]); $upstring .= "${v}$u->[1] "; $up -= $v * $u->[0]; } } $ret .= ""; $ret .= ""; $ret .= ""; } if ($mode eq "host" && $host eq $GET{'host'}) { $ret .= "[Raw Data]"; $ret .= "

Details for $host

"; $ret .= "

Slab classes

"; $ret .= "
HostHit RateCurr/Max SizeUtlz %UptimeVersion
$host$hit_rate"; if ($prev_hits && $prev_hits->{$host}) { my $nh = $now_hits{$host}; my $ph = $prev_hits->{$host}; my $new_hits = $now_hits{$host}[0] - $prev_hits->{$host}[0]; my $new_misses = $now_hits{$host}[1] - $prev_hits->{$host}[1]; $tot_hits += $new_hits; $tot_misses += $new_misses; my $new_whatev = $new_hits + $new_misses; my $new_rate = $new_hits / ($new_whatev || 1); my $cpu = sprintf("%0.6f", $nh->[2] - $ph->[2]); $ret .= sprintf(" [%0.02f%% {$new_whatev} $cpu]", $new_rate * 100); } $ret .= sprintf(" %0.02f", $t2-$t1); $ret .= "%0.01fG%0.02f/%0.01fG (%0.02f%%)%0.02f%%$upstring$stat{''}{'version'}
"; $ret .= "\n"; foreach my $cls (0..31) { my $size = $stat{'slabs'}{"$cls:chunk_size"}; next unless $size; $ret .= "" . join('', map { "" } qw(chunk_size used_chunks total_chunks free_chunks free_chunks_end total_pages)); my $age = $stat{'items'}{"items:$cls:age"}; $ret .= ""; $ret .= ""; } $ret .= "
classsizeusedtotalfreepagesmax age
$cls" . $stat{'slabs'}{"$cls:$_"} . "$age
\n"; } if ($mode eq "raw" && $host eq $GET{'host'}) { $ret .= "[Host Stats]"; $ret .= "

Raw data for $host

"; $ret .= "
$log
"; } } LJ::MemCache::set([$u->{'userid'},"mcrate:$u->{'userid'}"], \%now_hits) if $u; if ($mode eq "overview") { $ret .= "\n"; my $new_whatev = $tot_hits + $tot_misses; my $new_rate = $tot_hits / ($new_whatev || 1); $ret .= sprintf("Global [%0.02f%% {$new_whatev}]", $new_rate * 100); } return $ret; } _code?>