Friday, 1 June 2007

use libumem to make a memory use profile

Solaris 9/10 though we note libumem is being ported to linux.
 https://labs.omniti.com/trac/portableumem


1. run binary with libumem debug

   UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1 <binary file and params>

2. gcore and run mdb on it

   gcore -o myumemcore -p <pid>

3. run mdb commands on core file (step can take a while depending on core size)

   mdb <binary file> myumemcore <umem-test.mdb

less umem-test.mdb    
 $c !tee>>umem.log
 ::walk thread |::findstack !tee>>umem.log

 ::umastat !tee>>umem.log
 ::umem_status !tee>>umem.log
 ::umem_verify !tee>>umem.log
 ::umalog !tee>>umem-umalog.log
 
 ::findleaks !tee>>umem-leaks.log

 ::umausers !tee>umem-umausers.log
 *umem_oversize_arena::walk vmem_alloc | ::vmem_seg -v !tee>umem-oversize.log

 $q


4. Generate simple list of:

bytes  allocation-count  block-size   stack-reference(1st line that is not libumem malloc or libstdc++ new)

#!/bin/bash
# allow over-ride from environment
[[ $UMEMOVER == "" ]] && export UMEMOVER=umem-oversize.log;
[[ $UMEMUSER == "" ]] && export UMEMUSER=umem-umausers.log

UMEMPROFILE1=umem-profile1.log
UMEMPROFILE=umem-profile.log

egrep -v "(ADDR TYPE|THREAD *TIMESTAMP)" $UMEMOVER | perl -00 -pe '$foo = $_; ($ptr,$size,$thread_and_ts,$rest) = m/^\s*(\w+)\s+\w+\s+\w+\s+\w+\s+(\w+)\s*\n(.*)\n([\w\W]*)$/m; print "ptr: $ptr size: $size "; $rest =~ s/libumem.*/URK/g; $rest =~ s/libstd.*_Zn[wa]m.*/CURK/g; $_ = $rest; ($stackref) = m/\s*[CURK\s\W]+\s+(\S+)\s+/m; print "stackref: $stackref\n"; $_="";'  |sed "s/.*size: \(.*\) stackref: /\1 /" |sort |uniq -c |sed "s/  */ /g; s/^ *//" |perl -pe '$foo = $_; ($allocs,$blocksize,$rest) = m/^\s*(\w+)\s+(\w+)\s+(.*)$/; print ($allocs*$blocksize); print " ";' >$UMEMPROFILE

cat $UMEMUSER |gegrep -v "^ *(libumem|libstdc++)" |ggrep -A1 "bytes for" |sed  "s/\-\-//" |perl -00 -pe '$foo = $_; ($bytes,$allocs,$block,$rest) = m/^\s*(\w+)\s+bytes for\s+(\w+)\s+allocations with data size (\w+):\s*\n(.*)$/m; print "$bytes $allocs $block "; $rest =~ s/libumem.*/URK/g; $rest =~ s/libstd.*_Zn[wa]m.*/CURK/g; $_ = $rest; ($stackref) = m/\s*[CURK\s\W]+\s+(\S+)\s+/m; print "$rest\n"; $_="";' >> $UMEMPROFILE1

sort -n $UMEMPROFILE1 |perl -pe 'BEGIN{$tot=0; print "Bytes Allocations Block-size Stackref";} $foo = $_; ($bytes,$allocs,$blocksize,$rest) = m/^\s*(\w+)\s+(\w+)\s+(\w+)\s+(.*)$/; $tot+=$bytes; END{print "Total bytes: $tot\n";}' |tee $UMEMPROFILE



Hmmm. Maybe I should have just done it in perl.

No comments: