--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv1/abld/memtrace/memtrace.pl Wed Jun 30 11:35:58 2010 +0800
@@ -0,0 +1,265 @@
+# Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# Postprocess EPOC memory usage trace file
+#
+#
+
+no strict 'vars';
+use English;
+# Standard Symbian boilerplate to find and load E32env library
+use FindBin; # for FindBin::Bin
+use Getopt::Long;
+
+my $PerlLibPath; # fully qualified pathname of the directory containing our Perl modules
+
+BEGIN {
+# check user has a version of perl that will cope
+ require 5.005_03;
+# establish the path to the Perl libraries: currently the same directory as this script
+ $PerlLibPath = $FindBin::Bin; # X:/epoc32/tools
+ $PerlLibPath =~ s/\//\\/g; # X:\epoc32\tools
+ $PerlLibPath .= "\\";
+}
+
+use lib $PerlLibPath;
+use Modload;
+Load_SetModulePath($PerlLibPath);
+
+my $tickperiod = 0;
+my $emulproc = quotemeta("epoc[00000000]0001::");
+my $apprun = quotemeta("apprun[10003a4b]");
+my $ramdrive = quotemeta("TheRamDriveChunk");
+
+my @chunknames; # Array of chunk names, indexed by chunkid
+my @traces; # Array of chunk traces, each trace being an array
+ # of (tick,chunkid,size) triples
+my @chunkgroup; # Group that a chunk belongs to, indexed by chunkid
+my @groupnames; # Array of chunk group names (normally a group==a process)
+my @groups; # Array of chunk groups, each group being an array of chunkids
+
+my %opts;
+my $result = GetOptions (\%opts, "detailed", "help");
+if($result && ($opts{'help'} || $#ARGV<0))
+ {
+ &help;
+ exit 0;
+ }
+if(!$result || $#ARGV>0)
+ {
+ &usage;
+ exit 1;
+ }
+
+my $file = $ARGV[0];
+open TRACE,$file or die "Error: Can't open trace file \"$file\".\n";
+
+#
+# Parse trace file
+#
+my %current; # chunkids hashed by DChunk address
+my $nextchunkid;
+while(<TRACE>)
+ {
+ if (/MT:P\s+(\d+)\s*$/)
+ {
+ $tickperiod = $1;
+ }
+ elsif (/MT:C\s+(\d+)\s+([0-9a-fA-F]+)\s+(.+)\s*$/)
+ {
+ $current{$2} = $nextchunkid++;
+ push @chunknames, $3;
+ }
+ elsif (my ($tick, $addr, $size, $name) =
+ (/MT:A\s+(\d+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+(.+)\s*$/))
+ {
+ my $chunkid = $current{$addr};
+ die "Error: Parsing failure - is trace file complete ?"
+ unless (defined $chunkid);
+ push @traces, [0+$tick, $chunkid, hex($size)];
+
+ # Check whether chunk has been renamed to something more useful
+ $chunknames[$chunkid] = $name
+ if (($chunknames[$chunkid] =~ /^$emulproc/io) ||
+ ($chunknames[$chunkid] =~ /^$apprun/io));
+ }
+ elsif (/MT:D\s+(\d+)\s+([0-9a-fA-F]+)\s+(.+)\s*$/)
+ {
+ die "Error: Parsing failure" unless (defined $current{$2});
+ push @traces, [0+$1, $current{$2}, 0];
+ delete $current{$2};
+ }
+ elsif (/(MT:.\s+.*)/)
+ {
+ printf "Warning: Unrecognised trace line \"$1\".\n";
+ }
+ }
+close TRACE;
+die "Error: File \"$file\" does not contain any memory traces.\n"
+ unless ($#chunknames>0);
+
+
+#
+# Group chunks together by name
+#
+for (0..$#chunknames)
+ {
+ my $chunkid = $_;
+ my $name = $chunknames[$chunkid];
+ $name = $1 if ($name =~ /($ramdrive)$/i); # Special handling for ramdrive
+ $name = $1 if ($name =~ /^$emulproc(.*)/i); # Use thread names on Emulator
+ ($name) = ($name =~ /([^:]+)/); # otherwise strip thread name
+
+ # yuck! linear search
+ my $found = 0;
+ for (0..$#groupnames)
+ {
+ my $groupid = $_;
+ if ($groupnames[$groupid] eq $name)
+ {
+ $found = 1;
+ push @{$groups[$groupid]}, $chunkid;
+ $chunkgroup[$chunkid] = $groupid;
+ last;
+ }
+ }
+
+ if (!$found)
+ {
+ push @groupnames, $name;
+ push @groups, [$chunkid];
+ $chunkgroup[$chunkid] = $#groups;
+ }
+ }
+
+# Strip instance number (if any) from group name for presentation
+for (0..$#groupnames)
+ {
+ $groupnames[$_] = $1 if ($groupnames[$_] =~ /^([^]]+]?)/);
+ }
+
+#
+# Output
+#
+my @chunksizes; # Array of chunk sizes, indexed by chunkid
+for (0..$#chunknames) { $chunksizes[$_] = 0 };
+
+if ($opts{'detailed'})
+ {
+ # Detailed output
+
+ foreach my $name (@groupnames) { print ",\"$name\"" };
+ print "\n";
+
+ # if the tick size in microseconds hasn't been reported in the log with MT:P, take a guess
+ my $tickdiv = 0;
+ if ($tickperiod == 0)
+ {
+ # Uses hacky method to determine whether on Emulator or Target
+ $tickdiv = ($chunknames[0] =~ /^$emulproc/io) ? 10 : 64;
+ }
+ else
+ {
+ # tickperiod is number of microseconds
+ $tickdiv = 1000000 / $tickperiod;
+ }
+
+ my ($oldtick, $minitick) = (0,0);
+ my @groupsizes;
+ for my $trace (@traces)
+ {
+ my ($tick, $chunkid, $size) = @$trace;
+ if ($oldtick != $tick)
+ {
+ $oldtick = $tick;
+ $minitick=0;
+ }
+
+ $chunksizes[$chunkid] = $size;
+ my $groupid=$chunkgroup[$chunkid];
+ my $groupsize = 0;
+ foreach $chunkid (@{$groups[$groupid]})
+ {
+ $groupsize += $chunksizes[$chunkid];
+ }
+ $groupsizes[$groupid] = $groupsize;
+
+ print $tick/$tickdiv + ($minitick++)/1000000;
+ foreach $groupsize (@groupsizes)
+ {
+ if ($groupsize)
+ {
+ printf ",%d", $groupsize/1024;
+ }
+ else
+ {
+ print ','; # make output prettier by omitting 0s
+ }
+ }
+ print "\n";
+ }
+ }
+else
+ {
+ # Summary output
+
+ my @grouphighs;
+ for my $trace (@traces)
+ {
+ my ($tick, $chunkid, $size) = @$trace;
+ $chunksizes[$chunkid] = $size;
+ my $groupid=$chunkgroup[$chunkid];
+ my $groupsize = 0;
+ foreach $chunkid (@{$groups[$groupid]})
+ {
+ $groupsize += $chunksizes[$chunkid];
+ }
+ $grouphighs[$groupid] = $groupsize
+ if (!defined($grouphighs[$groupid]) ||
+ ($grouphighs[$groupid] < $groupsize));
+ }
+
+ printf "\"Process\", Size [K]\n";
+ for (0..$#groupnames)
+ {
+ printf "\"$groupnames[$_]\", %d\n", $grouphighs[$_]/1024;
+ }
+ }
+exit 0;
+
+
+sub help ()
+ {
+ my $build;
+
+ &Load_ModuleL('E32TPVER');
+ print "\nmemtrace - " .
+ "Postprocess EPOC memory usage trace (Build ", &E32tpver, ")\n";
+ &usage;
+ }
+
+sub usage ()
+ {
+ print <<EOF
+
+Usage:
+ memtrace [-d] <logfile>
+
+Where:
+ <logfile> Memory usage trace file.
+
+Options:
+ -d Produce a detailed listing.
+EOF
+ ;
+ }