| # ********************************************************** |
| # Copyright (c) 2006 VMware, Inc. All rights reserved. |
| # ********************************************************** |
| |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # * Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # * Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # * Neither the name of VMware, Inc. nor the names of its contributors may be |
| # used to endorse or promote products derived from this software without |
| # specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| # DAMAGE. |
| |
| # measure_mem.pl |
| # |
| # NOTE: ASSUMES drview is in path |
| # NOTE: ASSUMES c:\desktop-nightly\boot_data_scripts and |
| # c:\desktop-nightly\boot_data exist #TODO do a mkdir |
| # NOTE: ASSUMES this script is in c:\desktop-nightly\boot_data_scripts #FIXME |
| # NOTE: USES: lionfish_core_srv_exes.txt |
| # |
| # usage: perl measure_mem.pl --int 3 --boot 57 --summary zzz --nightly $(cygpath /tmp) --name test8r |
| |
| #TODO: exe list from file should be same as procs under DR, if not we have |
| # more running on the machine, warn? |
| #TODO: print usage |
| |
| use strict; |
| use Getopt::Long; |
| |
| my $PROG = "measure_mem.pl"; |
| |
| my %opt; |
| &GetOptions(\%opt, |
| "int:i", |
| "times=i", |
| "tillidle", |
| "boot=i", |
| "name=s", |
| "nightly=s", |
| "summary=s", |
| "help", |
| "usage", |
| "debug", |
| ); |
| |
| $opt{'int'} = 30 if $opt{'int'} == 0; |
| |
| # just paranoid about spaces |
| my $name = qq($opt{'name'}); |
| my $nightly = qq($opt{'nightly'}); |
| my $summary = qq($opt{'summary'}); |
| my $nightly_summary = qq($nightly\\$summary); |
| |
| my $ROOT = qq(C:\\desktop-nightly); |
| my $scriptdir = qq($ROOT\\boot_data_scripts); |
| my $outdir = qq($ROOT\\boot_data); |
| |
| if ($opt{'debug'}) { |
| print "scrdir: $scriptdir\n"; |
| print "outdir: $outdir\n"; |
| print "boot: $opt{'boot'}\n"; |
| print "name: $name\n"; |
| print "nightly: $nightly\n"; |
| print "summary: $summary\n"; |
| print "nightly_summary: $nightly_summary\n"; |
| } |
| |
| # log file |
| my $stamp = ×tamp(); |
| my $drtop_file = qq($outdir\\drtop_$stamp.txt); |
| my $drtop_summary = qq($outdir\\drtop_$stamp).qq(_summary.txt); |
| |
| # exes we care about for summary |
| my $exes_file = qq($scriptdir\\lionfish_core_srv_exes.txt); |
| my @exes = &read_file($exes_file); |
| |
| my $title_string = &title_string(); |
| my $summary_string; |
| my $count = 0; |
| my $CPU_IDX = 1; #TODO: ok? |
| |
| print "$PROG: measuring memorty till idle\n"; |
| |
| # do drview -showmem every 30s and compute summation for exes |
| # in lionfish configuration. Stop when the %cpu is <= 2% |
| for (my $iter = 1; 1 ; $iter++) { |
| my @drtop_out = `drview -listall -showmem`; |
| |
| &append_to_file($drtop_file, @drtop_out); |
| |
| &append_to_file($drtop_summary, ($title_string)) if $iter == 1; |
| |
| $summary_string = |
| &compute_summary($name, $opt{'boot'}, $iter, @drtop_out); |
| |
| &append_to_file($drtop_summary, ($summary_string)); |
| |
| if (defined $opt{'tillidle'}) { |
| # double work |
| my @sums = split /\s+/, $summary_string; |
| |
| $sums[$CPU_IDX] =~ s/%//; |
| my $cpu = $sums[$CPU_IDX]; |
| |
| # increment if cpu is <= 2%, otherwise reset to 0 |
| $count = ($cpu < 3) ? $count + 1 : $count - $count; |
| |
| # exit if cpu utilization is <= 2%, 3 times in a row |
| last if ($count > 2); |
| } |
| else { |
| last if (defined $opt{'times'} && $iter > $opt{'times'}); |
| } |
| |
| sleep($opt{'int'}); |
| } |
| |
| print "$PROG: copying data to $nightly\n"; |
| # copy results to network |
| system("copy /y $drtop_file $nightly"); |
| system("copy /y $drtop_summary $nightly"); |
| |
| print "$PROG: Writing summary to $nightly_summary\n"; |
| # write memory summary when machine is idle to nightly dir summary file |
| &append_to_file($nightly_summary, ($title_string)) unless (-e $nightly_summary); |
| &append_to_file($nightly_summary, ($summary_string)); |
| |
| #-------------------------------------------------------------------------- |
| sub compute_summary() { |
| my $name = shift; |
| my $boot = shift; |
| my $iter = shift; |
| my @drtop_out = @_; |
| |
| my @totals = 0 x 15; |
| my @cols = ( "\n" ); |
| my $name_idx = 0; |
| my $num_exes = 0; |
| my $charge = "0"; |
| |
| my $line; |
| foreach $line (@drtop_out) { |
| chomp($line); |
| |
| # skip uninteresting lines |
| next if $line =~ /^$/i; |
| next if $line =~ /System load is/i; |
| if ($line =~ s/System committed memory.*: //i) { |
| $charge = $line; |
| next; |
| } |
| |
| # skip the title line |
| next if ($line =~ m/Name.*PID.*Bld.*CPU.*WSS.*/i); |
| |
| # split each column (Priv, WSS etc.) |
| @cols = split (/\s+/, $line); |
| |
| # skip the blank process |
| next if $cols[$name_idx] =~ m/^\s*$/; |
| |
| # just get the name of the exe so we can grep for it |
| # for e.g svchost.exe-netsvcs -> svchost |
| $cols[$name_idx] =~ s/\.exe.*//i; |
| |
| # we are only interested in exes listed in the configuration file |
| next unless (scalar grep(m/$cols[$name_idx]/i, @exes)); |
| |
| # list the number of procs in summation |
| $num_exes++; |
| |
| # add the various columns of data up |
| for(my $col = 4; $col < 19; $col++) { |
| $cols[$col] =~ s/%//; |
| $totals[$col - 4] += $cols[$col]; |
| } |
| } |
| |
| # return a line of summary |
| return &summary_string($name, $boot, $iter, $num_exes, $charge, @totals); |
| } |
| |
| sub title_string { |
| my $title = sprintf "Build CPU User Thr PVSz VSz PPriv Priv PWSS WSS Fault PPage Page PNonP NonP Commit charge Boot #Exes *30s\n"; |
| return $title; |
| } |
| |
| sub summary_string { |
| my $name = shift; |
| my $boot = shift; |
| my $iter = shift; |
| my $num_exes = shift; |
| my $charge = shift; |
| my @totals = @_; |
| |
| my $summary = sprintf( |
| "%-14.14s %3d%% %3d%% %4d %7d %7d %8d %7d %7d %7d %7d %5d %5d %5d %5d %s %5d %5d %4d\n", |
| $name, |
| $totals[ 0], # CPU % |
| $totals[ 1], # User % |
| # totals[2] handles, not printed |
| $totals[ 3], # Threads |
| $totals[ 4], # Peak Vsz |
| $totals[ 5], # VSz |
| $totals[ 6], # Peak Priv |
| $totals[ 7], # Priv |
| $totals[ 8], # Peak WSS |
| $totals[ 9], # WSS |
| $totals[10], # Fault |
| $totals[11], # Peak Page pool |
| $totals[12], # Page pool |
| $totals[13], # Peak Non-Paged pool |
| $totals[14], # Non-paged |
| $charge, # commit charge |
| $boot, # boot time |
| $num_exes, # number of exes in summation |
| $iter, # iter |
| ); |
| |
| return $summary; |
| } |
| |
| sub append_to_file { |
| my $file = shift; |
| my @data = @_; |
| |
| open (FD, ">>$file") or |
| die "$PROG: cannot open $file: $!"; |
| print FD @data; |
| close FD; |
| } |
| |
| sub read_file { |
| my $file = shift; |
| my @data = (); |
| |
| open (FD, "<$file") or |
| die "$PROG: cannot open $file: $!"; |
| @data = <FD>; |
| close FD; |
| |
| return @data; |
| } |
| |
| sub timestamp() { |
| # ignore wday - day of the week, $yday - day of the year, and |
| # $is_dst - is daylight savings time |
| my ($sec, $min, $hour, |
| $mday, $mon, $year, |
| $wday, $yday, $is_dst) = localtime(time); |
| |
| # last 2 digits of year |
| $year = ($year + 1900) % 100; |
| my $stamp = sprintf("%02d%02d%02d_%02d%02d%02d", |
| $year,$mon+1,$mday, $hour,$min,$sec); |
| return $stamp; |
| } |