Update contrib.
3 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
5 # This component and the accompanying materials are made available
6 # under the terms of "Eclipse Public License v1.0"
7 # which accompanies this distribution, and is available
8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
10 # Initial Contributors:
11 # Nokia Corporation - initial contribution.
16 # This script parses trace data produced by OST from FBS, using the the FBSCLI,
17 # FBSERV and Symbian BTrace Hooks OST dictionaries, to produce a CSV output of
18 # the amount of bitmap memory used per-thread over a user-definable time
19 # granularity, since the start of the trace.
21 # To use, enable SYMBIAN_KERNEL_THREAD_IDENTIFICATION trace group in Symbian
22 # BTrace Hooks OST dictionary, GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS in FBSERV
23 # OST dictionary, and GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS,
24 # GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in
25 # FBSCLI OST dictionary. Once tracing is gathered, save trace output as ascii
26 # and run this script against it. The resulting file can then be imported into
27 # a spreadsheet application to be visually processed.
30 # Once the log time goes beyond midnight, snapshots will stop being taken.
35 # Sanity checking of the command line parameters...
36 if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?")
38 print "\nusage: $0 filename [-h]\n";
40 print " -h : Specifies the heartbeat in millisecs (default=10000)\n";
45 ## Modifiable constants...
46 my $CSV_DELIMITER = ',';
48 # Time after start to take first snapshot, in millisecs
49 my $firstHeartBeatTimeMS = 1000;
51 # Default heartbeat in millisecs if none specified.
52 my $heartBeatMS = 10000;
56 ## Internal structures...
58 my $heartBeatCount = 0;
59 my $nextHeartBeatMS = -1;
61 # A hash of thread names to the amount of bitmap memory they
62 # have used since the start of the trace.
63 my %bmpMemoryPerThread = ();
65 # A hash of bitmaps fully qualified by the session they belong to,
66 # and their local handle (because bitmaps can have the same local
67 # handle in different threads), mapped to their size in bytes.
68 my %bmpMemoryByServerHandle = ();
70 # Hash of FbsSessions to thread IDs.
71 my %SessionThreadMap = ();
73 # Array of the above hashes, one hash per heartbeat.
76 # Hashes of thread and process names to IDs.
82 ## Command line options parsing...
83 ## First arg is assumed to be the filename.
88 if ($cma =~ m/-h(\d*)/)
94 print "Unrecognised parameter: $cma , ignoring...\n";
98 ## Read from the file.
99 ## Read the log into an array line by line.
100 my $TRACE_FILENAME = $ARGV[0];
101 open(INPUT_FILE, $TRACE_FILENAME) or die $!;
102 my @traceLines = <INPUT_FILE>;
106 ## Parse each line sequentially...
108 foreach my $line (@traceLines)
110 my $timeFromMidnightMS;
113 ## If this line is about a new process, make a note of the name and the
114 ## associated process id, so that FbsSessions can be mapped to their
117 if ($line =~ /^.*Thread:Process name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i)
121 my $processName = $3;
122 $ProcessNames{$processId} = $processName ;
126 ## If this line is about a new process, make a note of the name and the
127 ## associated process id, so that FbsSessions can be mapped to their
128 ## thread by name when the csv is generated.
130 if (($line =~ /^.*Thread:Thread created;NThread:(.*);DProcess:(.*);Name:(.*)$/i) ||
131 ($line =~ /^.*Thread:Thread name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i))
136 my $fullThreadName = $ProcessNames{$processId} . ":" . $threadName;
137 $ThreadNames{$threadId} = $fullThreadName;
141 ## Determine timestamp. If this time is beyond the heartbeat,
142 ## take a snapshot and
144 if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/)
146 $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4;
147 # Set up the time for the first snapshot.
148 if ($nextHeartBeatMS == -1)
150 $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS;
155 ## If heartbeat reached, take snapshot of bmp memory per thread
156 ## and set next heartbeat time.
158 while ($timeFromMidnightMS >= $nextHeartBeatMS)
160 $nextHeartBeatMS += $heartBeatMS;
161 # take a snapshot of the current bitmap memory usage per thread
162 while ((my $thread, my $bmpMemory) = each(%bmpMemoryPerThread))
164 $arrayOfSnapshots[$heartBeatCount]{$thread} = $bmpMemory;
169 ## FBS Client-side traces.
170 if ($line =~ m/\tFBSCLI: /)
173 ## If this line is an FBSCLI trace, and it contains iSSH then
174 ## it gives a chance to map a client thread ID to a session handle.
176 if ( $line =~ m/iSSH=(\w*);.*Thread ID:(.*)$/)
178 my $ServerSessionHandle = $1;
180 if ($thread ne "0x00000000")
182 $SessionThreadMap{$ServerSessionHandle} = $thread;
188 ## FBS Server-side traces.
190 if ($line =~ m/\tFBSERV: /)
192 ## The line must have a s= parameter to be useful - the session server handle.
193 ## Any FBSERV line without this is not considered for parsing.
194 if ($line =~ m/; iSSH=(\w*);/)
196 my $FbsSessionHandle = $1;
197 my $thread = "Unknown Thread [Session=$FbsSessionHandle]";
198 if (defined($SessionThreadMap{$FbsSessionHandle}))
200 $thread = $SessionThreadMap{$FbsSessionHandle};
202 if ($line =~ m/# Server resource destroyed; .*iH=(\w*);/)
205 my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
206 if (defined($bmpMemoryByServerHandle{$bmpIdentifier}))
208 $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$bmpIdentifier};
209 delete $bmpMemoryByServerHandle{$bmpIdentifier};
212 if ($line =~ m/# Server bitmap resized; .*iOldH=(\w*); iNewH=(\w*); newbytes=(\d*);/)
214 # When a bitmap is resized, the amount of memory held by the bitmap may change
215 # and the bitmap localhandle will change.
216 my $oldBmpHandle = $1;
217 my $newBmpHandle = $2;
218 my $newBmpBytes = $3;
219 my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
220 my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
221 if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
223 $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$oldBmpIdentifier};
224 delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
226 $bmpMemoryPerThread{$thread} += $newBmpBytes;
227 $bmpMemoryByServerHandle{$newBmpIdentifier} = $newBmpBytes;
229 elsif ($line =~ m/#.*iOldH=(\w*); iNewH=(\w*);/)
231 # When a bitmap is compressed, cleaned or resized, the bitmap local handle changes
232 my $oldBmpHandle = $1;
233 my $newBmpHandle = $2;
234 my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
235 my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
236 if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
238 my $bytes = $bmpMemoryByServerHandle{$oldBmpIdentifier};
239 delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
240 $bmpMemoryByServerHandle{$newBmpIdentifier} = $bytes;
243 elsif ($line =~ m/#.*iH=(\w*);.*bytes=(\d+);/)
245 # Duplication of a bitmap typically. When a bitmap is duplicated,
246 # the memory is 'owned' by all threads that duplicate it.
249 my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
250 $bmpMemoryPerThread{$thread} += $bmpBytes;
251 $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes;
261 ## Make a map of unique threads across all snapshots
262 ## This is so only one occurrence of each thread will appear
265 my %uniqueThreads = ();
266 for my $i (0..$#arrayOfSnapshots)
268 for my $thread (keys %{$arrayOfSnapshots[$i]})
270 $uniqueThreads{$thread} = 1;
275 ## Start writing to file.
276 ## First row, which contains the heartbeat number column headings...
278 my $OUTPUT_FILENAME = sprintf("%s.csv", $TRACE_FILENAME);
279 open(OUTPUT_FILE,">$OUTPUT_FILENAME") or die $!;
280 print OUTPUT_FILE "Session$CSV_DELIMITER";
281 for my $i (0..$heartBeatCount)
283 print OUTPUT_FILE "$i$CSV_DELIMITER";
287 ## For each subsequent row, print the first thread and the
288 ## memory at each snapshot...
290 print OUTPUT_FILE "\n";
291 while ((my $thread, my $dummy) = each(%uniqueThreads))
293 # Resolve the thread to its full name...
294 print OUTPUT_FILE "$thread";
295 if (defined($ThreadNames{$thread}) )
297 my $threadName = $ThreadNames{$thread};
298 print OUTPUT_FILE ":$threadName";
300 print OUTPUT_FILE "$CSV_DELIMITER";
302 # print the memory use per thread, for each snapshot...
303 for my $i (0..$#arrayOfSnapshots)
305 my %snapshot = %{$arrayOfSnapshots[$i]};
306 while ((my $snapshotThread, my $bmpMemory) = each(%snapshot))
308 if ($snapshotThread eq $thread)
310 print OUTPUT_FILE "$bmpMemory";
313 print OUTPUT_FILE "$CSV_DELIMITER";
315 print OUTPUT_FILE "\n";