1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/fbs/fontandbitmapserver/utils/fbsbitmap_memory.pl Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,318 @@
1.4 +#!/usr/local/bin/perl
1.5 +#
1.6 +# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
1.7 +# All rights reserved.
1.8 +# This component and the accompanying materials are made available
1.9 +# under the terms of "Eclipse Public License v1.0"
1.10 +# which accompanies this distribution, and is available
1.11 +# at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.12 +#
1.13 +# Initial Contributors:
1.14 +# Nokia Corporation - initial contribution.
1.15 +#
1.16 +# Contributors:
1.17 +#
1.18 +# Description:
1.19 +# This script parses trace data produced by OST from FBS, using the the FBSCLI,
1.20 +# FBSERV and Symbian BTrace Hooks OST dictionaries, to produce a CSV output of
1.21 +# the amount of bitmap memory used per-thread over a user-definable time
1.22 +# granularity, since the start of the trace.
1.23 +#
1.24 +# To use, enable SYMBIAN_KERNEL_THREAD_IDENTIFICATION trace group in Symbian
1.25 +# BTrace Hooks OST dictionary, GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS in FBSERV
1.26 +# OST dictionary, and GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS,
1.27 +# GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in
1.28 +# FBSCLI OST dictionary. Once tracing is gathered, save trace output as ascii
1.29 +# and run this script against it. The resulting file can then be imported into
1.30 +# a spreadsheet application to be visually processed.
1.31 +#
1.32 +# KNOWN DEFECTS:
1.33 +# Once the log time goes beyond midnight, snapshots will stop being taken.
1.34 +#
1.35 +
1.36 +use strict;
1.37 +
1.38 +# Sanity checking of the command line parameters...
1.39 +if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?")
1.40 +{
1.41 + print "\nusage: $0 filename [-h]\n";
1.42 + print "where\n";
1.43 + print " -h : Specifies the heartbeat in millisecs (default=10000)\n";
1.44 + exit;
1.45 +}
1.46 +
1.47 +
1.48 +## Modifiable constants...
1.49 +my $CSV_DELIMITER = ',';
1.50 +
1.51 +# Time after start to take first snapshot, in millisecs
1.52 +my $firstHeartBeatTimeMS = 1000;
1.53 +
1.54 +# Default heartbeat in millisecs if none specified.
1.55 +my $heartBeatMS = 10000;
1.56 +
1.57 +
1.58 +##
1.59 +## Internal structures...
1.60 +##
1.61 +my $heartBeatCount = 0;
1.62 +my $nextHeartBeatMS = -1;
1.63 +
1.64 +# A hash of thread names to the amount of bitmap memory they
1.65 +# have used since the start of the trace.
1.66 +my %bmpMemoryPerThread = ();
1.67 +
1.68 +# A hash of bitmaps fully qualified by the session they belong to,
1.69 +# and their local handle (because bitmaps can have the same local
1.70 +# handle in different threads), mapped to their size in bytes.
1.71 +my %bmpMemoryByServerHandle = ();
1.72 +
1.73 +# Hash of FbsSessions to thread IDs.
1.74 +my %SessionThreadMap = ();
1.75 +
1.76 +# Array of the above hashes, one hash per heartbeat.
1.77 +my @arrayOfSnapshots;
1.78 +
1.79 +# Hashes of thread and process names to IDs.
1.80 +my %ThreadNames;
1.81 +my %ProcessNames;
1.82 +
1.83 +
1.84 +##
1.85 +## Command line options parsing...
1.86 +## First arg is assumed to be the filename.
1.87 +##
1.88 +for my $i (1..$#ARGV)
1.89 +{
1.90 + my $cma = $ARGV[$i];
1.91 + if ($cma =~ m/-h(\d*)/)
1.92 + {
1.93 + $heartBeatMS = $1;
1.94 + }
1.95 + else
1.96 + {
1.97 + print "Unrecognised parameter: $cma , ignoring...\n";
1.98 + }
1.99 +}
1.100 +
1.101 +## Read from the file.
1.102 +## Read the log into an array line by line.
1.103 +my $TRACE_FILENAME = $ARGV[0];
1.104 +open(INPUT_FILE, $TRACE_FILENAME) or die $!;
1.105 +my @traceLines = <INPUT_FILE>;
1.106 +
1.107 +
1.108 +##
1.109 +## Parse each line sequentially...
1.110 +##
1.111 +foreach my $line (@traceLines)
1.112 +{
1.113 + my $timeFromMidnightMS;
1.114 +
1.115 + ##
1.116 + ## If this line is about a new process, make a note of the name and the
1.117 + ## associated process id, so that FbsSessions can be mapped to their
1.118 + ## thread by name.
1.119 + ##
1.120 + if ($line =~ /^.*Thread:Process name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i)
1.121 + {
1.122 + my $threadId = $1;
1.123 + my $processId = $2;
1.124 + my $processName = $3;
1.125 + $ProcessNames{$processId} = $processName ;
1.126 + }
1.127 +
1.128 + ##
1.129 + ## If this line is about a new process, make a note of the name and the
1.130 + ## associated process id, so that FbsSessions can be mapped to their
1.131 + ## thread by name when the csv is generated.
1.132 + ##
1.133 + if (($line =~ /^.*Thread:Thread created;NThread:(.*);DProcess:(.*);Name:(.*)$/i) ||
1.134 + ($line =~ /^.*Thread:Thread name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i))
1.135 + {
1.136 + my $threadId = $1;
1.137 + my $processId = $2;
1.138 + my $threadName = $3;
1.139 + my $fullThreadName = $ProcessNames{$processId} . ":" . $threadName;
1.140 + $ThreadNames{$threadId} = $fullThreadName;
1.141 + }
1.142 +
1.143 + ##
1.144 + ## Determine timestamp. If this time is beyond the heartbeat,
1.145 + ## take a snapshot and
1.146 + ##
1.147 + if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/)
1.148 + {
1.149 + $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4;
1.150 + # Set up the time for the first snapshot.
1.151 + if ($nextHeartBeatMS == -1)
1.152 + {
1.153 + $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS;
1.154 + }
1.155 + }
1.156 +
1.157 + ##
1.158 + ## If heartbeat reached, take snapshot of bmp memory per thread
1.159 + ## and set next heartbeat time.
1.160 + ##
1.161 + while ($timeFromMidnightMS >= $nextHeartBeatMS)
1.162 + {
1.163 + $nextHeartBeatMS += $heartBeatMS;
1.164 + # take a snapshot of the current bitmap memory usage per thread
1.165 + while ((my $thread, my $bmpMemory) = each(%bmpMemoryPerThread))
1.166 + {
1.167 + $arrayOfSnapshots[$heartBeatCount]{$thread} = $bmpMemory;
1.168 + }
1.169 + $heartBeatCount++;
1.170 + }
1.171 +
1.172 + ## FBS Client-side traces.
1.173 + if ($line =~ m/\tFBSCLI: /)
1.174 + {
1.175 + ##
1.176 + ## If this line is an FBSCLI trace, and it contains iSSH then
1.177 + ## it gives a chance to map a client thread ID to a session handle.
1.178 + ##
1.179 + if ( $line =~ m/iSSH=(\w*);.*Thread ID:(.*)$/)
1.180 + {
1.181 + my $ServerSessionHandle = $1;
1.182 + my $thread = $2;
1.183 + if ($thread ne "0x00000000")
1.184 + {
1.185 + $SessionThreadMap{$ServerSessionHandle} = $thread;
1.186 + }
1.187 + }
1.188 + }
1.189 +
1.190 + ##
1.191 + ## FBS Server-side traces.
1.192 + ##
1.193 + if ($line =~ m/\tFBSERV: /)
1.194 + {
1.195 + ## The line must have a s= parameter to be useful - the session server handle.
1.196 + ## Any FBSERV line without this is not considered for parsing.
1.197 + if ($line =~ m/; iSSH=(\w*);/)
1.198 + {
1.199 + my $FbsSessionHandle = $1;
1.200 + my $thread = "Unknown Thread [Session=$FbsSessionHandle]";
1.201 + if (defined($SessionThreadMap{$FbsSessionHandle}))
1.202 + {
1.203 + $thread = $SessionThreadMap{$FbsSessionHandle};
1.204 + }
1.205 + if ($line =~ m/# Server resource destroyed; .*iH=(\w*);/)
1.206 + {
1.207 + my $bmpHandle = $1;
1.208 + my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
1.209 + if (defined($bmpMemoryByServerHandle{$bmpIdentifier}))
1.210 + {
1.211 + $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$bmpIdentifier};
1.212 + delete $bmpMemoryByServerHandle{$bmpIdentifier};
1.213 + }
1.214 + }
1.215 + if ($line =~ m/# Server bitmap resized; .*iOldH=(\w*); iNewH=(\w*); newbytes=(\d*);/)
1.216 + {
1.217 + # When a bitmap is resized, the amount of memory held by the bitmap may change
1.218 + # and the bitmap localhandle will change.
1.219 + my $oldBmpHandle = $1;
1.220 + my $newBmpHandle = $2;
1.221 + my $newBmpBytes = $3;
1.222 + my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
1.223 + my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
1.224 + if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
1.225 + {
1.226 + $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$oldBmpIdentifier};
1.227 + delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
1.228 + }
1.229 + $bmpMemoryPerThread{$thread} += $newBmpBytes;
1.230 + $bmpMemoryByServerHandle{$newBmpIdentifier} = $newBmpBytes;
1.231 + }
1.232 + elsif ($line =~ m/#.*iOldH=(\w*); iNewH=(\w*);/)
1.233 + {
1.234 + # When a bitmap is compressed, cleaned or resized, the bitmap local handle changes
1.235 + my $oldBmpHandle = $1;
1.236 + my $newBmpHandle = $2;
1.237 + my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
1.238 + my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
1.239 + if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
1.240 + {
1.241 + my $bytes = $bmpMemoryByServerHandle{$oldBmpIdentifier};
1.242 + delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
1.243 + $bmpMemoryByServerHandle{$newBmpIdentifier} = $bytes;
1.244 + }
1.245 + }
1.246 + elsif ($line =~ m/#.*iH=(\w*);.*bytes=(\d+);/)
1.247 + {
1.248 + # Duplication of a bitmap typically. When a bitmap is duplicated,
1.249 + # the memory is 'owned' by all threads that duplicate it.
1.250 + my $bmpHandle = $1;
1.251 + my $bmpBytes = $2;
1.252 + my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
1.253 + $bmpMemoryPerThread{$thread} += $bmpBytes;
1.254 + $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes;
1.255 + }
1.256 + }
1.257 + }
1.258 +}
1.259 +
1.260 +close (INPUT_FILE);
1.261 +
1.262 +
1.263 +##
1.264 +## Make a map of unique threads across all snapshots
1.265 +## This is so only one occurrence of each thread will appear
1.266 +## in the csv file.
1.267 +##
1.268 +my %uniqueThreads = ();
1.269 +for my $i (0..$#arrayOfSnapshots)
1.270 +{
1.271 + for my $thread (keys %{$arrayOfSnapshots[$i]})
1.272 + {
1.273 + $uniqueThreads{$thread} = 1;
1.274 + }
1.275 +}
1.276 +
1.277 +##
1.278 +## Start writing to file.
1.279 +## First row, which contains the heartbeat number column headings...
1.280 +##
1.281 +my $OUTPUT_FILENAME = sprintf("%s.csv", $TRACE_FILENAME);
1.282 +open(OUTPUT_FILE,">$OUTPUT_FILENAME") or die $!;
1.283 +print OUTPUT_FILE "Session$CSV_DELIMITER";
1.284 +for my $i (0..$heartBeatCount)
1.285 +{
1.286 + print OUTPUT_FILE "$i$CSV_DELIMITER";
1.287 +}
1.288 +
1.289 +##
1.290 +## For each subsequent row, print the first thread and the
1.291 +## memory at each snapshot...
1.292 +##
1.293 +print OUTPUT_FILE "\n";
1.294 +while ((my $thread, my $dummy) = each(%uniqueThreads))
1.295 +{
1.296 + # Resolve the thread to its full name...
1.297 + print OUTPUT_FILE "$thread";
1.298 + if (defined($ThreadNames{$thread}) )
1.299 + {
1.300 + my $threadName = $ThreadNames{$thread};
1.301 + print OUTPUT_FILE ":$threadName";
1.302 + }
1.303 + print OUTPUT_FILE "$CSV_DELIMITER";
1.304 +
1.305 + # print the memory use per thread, for each snapshot...
1.306 + for my $i (0..$#arrayOfSnapshots)
1.307 + {
1.308 + my %snapshot = %{$arrayOfSnapshots[$i]};
1.309 + while ((my $snapshotThread, my $bmpMemory) = each(%snapshot))
1.310 + {
1.311 + if ($snapshotThread eq $thread)
1.312 + {
1.313 + print OUTPUT_FILE "$bmpMemory";
1.314 + }
1.315 + }
1.316 + print OUTPUT_FILE "$CSV_DELIMITER";
1.317 + }
1.318 + print OUTPUT_FILE "\n";
1.319 +}
1.320 +close (OUTPUT_FILE);
1.321 +