blob: 7b0f49266f3a0ba64857adc150f13c3f855fd5fd [file] [log] [blame]
# **********************************************************
# 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 = &timestamp();
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;
}