Skip to content

Instantly share code, notes, and snippets.

Created June 29, 2015 07:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/4071a06909f4df8cabb2 to your computer and use it in GitHub Desktop.
Save anonymous/4071a06909f4df8cabb2 to your computer and use it in GitHub Desktop.
mem leak suspect promise+supply
use v6;
class NX::Sys::Stat
{
has %!stat;
has %!index;
has $!queue;
my %PS = enum < pid user pcpu pmem sz rsz vsz nlwp state etime args >;
my $PS; %PS.kv.map: -> $k, $v { $PS[$v] = $k };
submethod BUILD
{
$!queue = Supply.new;
$!queue.act: {
for .EVAL -> [ $index, %stat ] {
my $name = $index.key; ## PS, DF, ROUTE, IOSTAT etc.
my $next = %!index{$name}.elems;
for $index.value.kv -> $i, $s {
my $j = %!index{$name}{$s} //= $next++;
for %stat.kv -> $k, $v { %!stat{$name}{$k}[$j] = $v[$i] }
}
}
}
}
method run( *%mayhem )
{
await {
"ps h -o { $PS.join: ',' } -e" => &ps,
'sar -A 1 1' => &sar,
'route -n' => &route,
'iostat -d' => &iostat,
'iostat -dx' => &iostat,
'df -lmP' => &df,
'df -liP' => &df,
%mayhem,
}.kv.map: -> $cmd, $sub {
start {
my $s := qq:x< $cmd >;
$!queue.emit: $s ?? $sub( $s ).perl !! [ FIXME => [] ].perl;
};
};
self;
}
sub ps( $s )
{
[ PS => $PS, my $h = hash $s.trim.split( "\n" ).map: {
my @s := .trim.split: /\s+/, $PS.elems;
my @t := @s[ %PS<etime> ].split: '-', 2;
my $i = 0; @s[ %PS<etime> ] = [+] @t == 2 ?? @t[0] * 86400 !! 0,
@t[*-1].split( ':' ).reverse.map: { $_ * 60 ** $i++ };
@s[ %PS<pid> ] => @s;
} ]
}
sub sar( $s )
{
my %FIXME = {
PAGE => < pgpgin/s kbhugfree >,
IO => < tps >,
LOAD => < runq-sz proc/s cswch/s >,
MEM => < frmpg/s kbmemfree >,
SWAP => < kbswpfree pswpin/s >,
NFS => < call/s scall/s >,
SOCK => < totsck >,
IP => < irec/s ihdrerr/s >,
ICMP => < imsg/s ierr/s >,
TCP => < active/s atmptf/s >,
UDP => < idgm/s >,
SOCK6 => < tcp6sck >,
IP6 => < irec6/s ihdrer6/s >,
ICMP6 => < imsg6/s ierr6/s >,
UDP6 => < idgm6/s >,
FILE => < dentunusd >,
}.invert;
$s.split( "\n\n" ).map: {
next if $_ !~~ / ^^ Average / ff $_ !~~ / ^^ Average /;
my @s := .trim.split( "\n" ).map: { [ .split: /\s+/ ] };
my $name = @s[0][1]; @s.map: { .shift };
if $name ~~ / << <:Lu>+ >> / { @s[0].shift }
else { @s[1].unshift( $name = %FIXME{ $name } // 'FIXME' ) }
[ $name => @s.shift, my $h = hash @s.map: { .shift => $_ } ]
}
}
sub route( $s )
{
my @s := $s.trim.split( "\n" ).map: { [ .split: /\s+/ ] };
@s.shift;
[ ROUTE => @s.shift, my $h = hash @s.map: { $_[0] => $_ } ]
}
sub iostat( $s )
{
my @s := ( $s.split: "\n\n" )[1].split( "\n" ).map: { [ .split: /\s+/ ] };
@s[0].shift;
[ IOSTAT => @s.shift, my $h = hash @s.map: { .shift => $_ } ]
}
sub df( $s )
{
my @s := $s.trim.split( "\n" ).map: { [ .split: /\s+/, 6 ] };
@s[0].pop;
[ DF => @s.shift, my $h =
hash @s.map: { $_[0] = ( $_[0].split: '/' )[*-1]; .pop => $_ } ]
}
method index
{
hash %!index.kv.map: -> $name, $index {
my $stat; $index.kv.map: -> $k, $v { $stat[$v] = $k };
$name => $stat;
}
}
method eval( $test, :$neg )
{
while $test ~~ / ( \< .+? \> ) ** 2..3 / {
my ( $name, $stat, $id ) = $0.map: { .EVAL };
my $s = %!stat{$name} // last;
my $i = %!index{$name}{$stat} // last;
$test.=subst: "$/", $id.defined
?? ( $s{$id}[$i] // last ).perl
!! ( $s.values.map: { $_[$i] } ).perl
}
$test !~~ / \< .+? \> / && ( $neg.Bool + $test.EVAL.Bool ) % 2;
}
}
my $s = NX::Sys::Stat.new; for 1 .. * { .say; $s.run.index.say }
$ uname -osvm
Linux #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 GNU/Linux
$ perl6 -v
This is perl6 version 2015.06-1-gdf0c3a3 built on MoarVM version 2015.06
$ perl6 sysstat.pm6
1
CPU => %usr %nice %sys %iowait %steal %irq %soft %guest %gnice %idle MHz wghMHz, DEV => tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util, DF => Filesystem 1048576-blocks Used Available Capacity Inodes IUsed IFree IUse%, FILE => dentunusd file-nr inode-nr pty-nr, ICMP => imsg/s omsg/s iech/s iechr/s oech/s oechr/s itm/s itmr/s otm/s otmr/s iadrmk/s iadrmkr/s oadrmk/s oadrmkr/s ierr/s oerr/s idstunr/s odstunr/s itmex/s otmex/s iparmpb/s oparmpb/s isrcq/s osrcq/s iredir/s oredir/s, ICMP6 => imsg6/s omsg6/s iech6/s iechr6/s oechr6/s igmbq6/s igmbr6/s ogmbr6/s igmbrd6/s ogmbrd6/s irtsol6/s ortsol6/s irtad6/s inbsol6/s onbsol6/s inbad6/s onbad6/s ierr6/s idtunr6/s odtunr6/s itmex6/s otmex6/s iprmpb6/s oprmpb6/s iredir6/s oredir6/s ipck2b6/s opck2b6/s, IFACE => rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil rxerr/s txerr/s coll/s rxdrop/s txdrop/s txcarr/s rxfram/s rxfifo/s txfifo/s, INTR => intr/s, IO => tps rtps wtps bread/s bwrtn/s, IOSTAT => tps kB_read/s kB_wrtn/s kB_read kB_wrtn rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util, IP => irec/s fwddgm/s idel/s orq/s asmrq/s asmok/s fragok/s fragcrt/s ihdrerr/s iadrerr/s iukwnpr/s idisc/s odisc/s onort/s asmf/s fragf/s, IP6 => irec6/s fwddgm6/s idel6/s orq6/s asmrq6/s asmok6/s imcpck6/s omcpck6/s fragok6/s fragcr6/s ihdrer6/s iadrer6/s iukwnp6/s i2big6/s idisc6/s odisc6/s inort6/s onort6/s asmf6/s fragf6/s itrpck6/s, LOAD => proc/s cswch/s runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked, MEM => frmpg/s bufpg/s campg/s kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty, NFS => call/s retrans/s read/s write/s access/s getatt/s scall/s badcall/s packet/s udp/s tcp/s hit/s miss/s sread/s swrite/s saccess/s sgetatt/s, PAGE => pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff kbhugfree kbhugused %hugused, PS => pid user pcpu pmem sz rsz vsz nlwp state etime args, ROUTE => Destination Gateway Genmask Flags Metric Ref Use Iface, SOCK => totsck tcpsck udpsck rawsck ip-frag tcp-tw, SOCK6 => tcp6sck udp6sck raw6sck ip6-frag, SWAP => pswpin/s pswpout/s kbswpfree kbswpused %swpused kbswpcad %swpcad, TCP => active/s passive/s iseg/s oseg/s atmptf/s estres/s retrans/s isegerr/s orsts/s, TEMP => degC %temp DEVICE, UDP => idgm/s odgm/s noport/s idgmerr/s, UDP6 => idgm6/s odgm6/s noport6/s idgmer6/s
2
...
$ perl6-valgrind-m sysstat.pm6 > /dev/null
==15089== Memcheck, a memory error detector
==15089== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15089== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==15089== Command: /home/kan/rakudo/install/bin/moar --execname=/home/kan/rakudo/install/bin/perl6-valgrind-m --libpath=/home/kan/rakudo/install/share/nqp/lib --libpath=/home/kan/rakudo/install/share/perl6/lib --libpath=/home/kan/rakudo/install/share/perl6/runtime /home/kan/rakudo/install/share/perl6/runtime/perl6.moarvm sysstat.pm6
==15089==
==15089== Thread 3:
==15089== Invalid read of size 8
==15089== at 0x4FD34A0: MVM_6model_stable_gc_free (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA4D04: MVM_gc_collect_free_stables (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA1AA3: MVM_gc_enter_from_allocator (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA1EC7: MVM_gc_allocate_nursery (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA2107: MVM_gc_allocate_object (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4F80453: MVM_interp_run (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4F9036D: start_thread (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x502F586: uv__thread_start (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x5B15181: start_thread (pthread_create.c:312)
==15089== by 0x553C30C: clone (clone.S:111)
==15089== Address 0x150 is not stack'd, malloc'd or (recently) free'd
==15089==
==15089==
==15089== Process terminating with default action of signal 11 (SIGSEGV)
==15089== Access not within mapped region at address 0x150
==15089== at 0x4FD34A0: MVM_6model_stable_gc_free (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA4D04: MVM_gc_collect_free_stables (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA1AA3: MVM_gc_enter_from_allocator (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA1EC7: MVM_gc_allocate_nursery (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4FA2107: MVM_gc_allocate_object (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4F80453: MVM_interp_run (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x4F9036D: start_thread (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x502F586: uv__thread_start (in /home/kan/rakudo/install/lib/libmoar.so)
==15089== by 0x5B15181: start_thread (pthread_create.c:312)
==15089== by 0x553C30C: clone (clone.S:111)
==15089== If you believe this happened as a result of a stack
==15089== overflow in your program's main thread (unlikely but
==15089== possible), you can try to increase the size of the
==15089== main thread stack using the --main-stacksize= flag.
==15089== The main thread stack size used in this run was 8388608.
==15089==
==15089== HEAP SUMMARY:
==15089== in use at exit: 310,452,472 bytes in 596,655 blocks
==15089== total heap usage: 8,501,197 allocs, 7,904,542 frees, 4,214,055,385 bytes allocated
==15089==
==15089== LEAK SUMMARY:
==15089== definitely lost: 1,097,900 bytes in 33,688 blocks
==15089== indirectly lost: 836,359 bytes in 38,423 blocks
==15089== possibly lost: 378,602 bytes in 6,701 blocks
==15089== still reachable: 308,139,611 bytes in 517,843 blocks
==15089== suppressed: 0 bytes in 0 blocks
==15089== Rerun with --leak-check=full to see details of leaked memory
==15089==
==15089== For counts of detected and suppressed errors, rerun with: -v
==15089== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Killed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment