24 # GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in |
24 # GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in |
25 # FBSCLI OST dictionary. Once tracing is gathered, save trace output as ascii |
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 |
26 # and run this script against it. The resulting file can then be imported into |
27 # a spreadsheet application to be visually processed. |
27 # a spreadsheet application to be visually processed. |
28 # |
28 # |
29 # KNOWN DEFECTS: |
|
30 # Once the log time goes beyond midnight, snapshots will stop being taken. |
|
31 # |
|
32 |
29 |
33 use strict; |
30 use strict; |
34 |
31 |
35 # Sanity checking of the command line parameters... |
32 # Sanity checking of the command line parameters... |
36 if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?") |
33 if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?") |
37 { |
34 { |
38 print "\nusage: $0 filename [-h]\n"; |
35 print "\nusage: $0 filename [-h]\n"; |
39 print "where\n"; |
36 print "where\n"; |
40 print " -h : Specifies the heartbeat in millisecs (default=10000)\n"; |
37 print " -h : Specifies the heartbeat in millisecs (default=10000)\n"; |
|
38 print " -d : Ignore duplicated handles\n"; |
41 exit; |
39 exit; |
42 } |
40 } |
43 |
41 |
44 |
42 |
45 ## Modifiable constants... |
43 ## Modifiable constants... |
55 ## |
53 ## |
56 ## Internal structures... |
54 ## Internal structures... |
57 ## |
55 ## |
58 my $heartBeatCount = 0; |
56 my $heartBeatCount = 0; |
59 my $nextHeartBeatMS = -1; |
57 my $nextHeartBeatMS = -1; |
|
58 my $logLastLineTimeMS = 0; |
60 |
59 |
61 # A hash of thread names to the amount of bitmap memory they |
60 # A hash of thread names to the amount of bitmap memory they |
62 # have used since the start of the trace. |
61 # have used since the start of the trace. |
63 my %bmpMemoryPerThread = (); |
62 my %bmpMemoryPerThread = (); |
64 |
63 |
87 my $cma = $ARGV[$i]; |
89 my $cma = $ARGV[$i]; |
88 if ($cma =~ m/-h(\d*)/) |
90 if ($cma =~ m/-h(\d*)/) |
89 { |
91 { |
90 $heartBeatMS = $1; |
92 $heartBeatMS = $1; |
91 } |
93 } |
|
94 elsif ($cma =~ m/-d/) |
|
95 { |
|
96 $countDuplicates = 0; |
|
97 } |
92 else |
98 else |
93 { |
99 { |
94 print "Unrecognised parameter: $cma , ignoring...\n"; |
100 print "Unrecognised parameter: $cma , ignoring...\n"; |
95 } |
101 } |
96 } |
102 } |
97 |
103 |
98 ## Read from the file. |
104 ## Read from the file. |
99 ## Read the log into an array line by line. |
105 ## Read the log into an array line by line. |
100 my $TRACE_FILENAME = $ARGV[0]; |
106 my $TRACE_FILENAME = $ARGV[0]; |
101 open(INPUT_FILE, $TRACE_FILENAME) or die $!; |
107 open(INPUT_FILE, '<', $TRACE_FILENAME) or die $!; |
102 my @traceLines = <INPUT_FILE>; |
108 binmode(INPUT_FILE); |
103 |
|
104 |
109 |
105 ## |
110 ## |
106 ## Parse each line sequentially... |
111 ## Parse each line sequentially... |
107 ## |
112 ## |
108 foreach my $line (@traceLines) |
113 while ( my $line = <INPUT_FILE> ) |
109 { |
114 { |
110 my $timeFromMidnightMS; |
115 my $timeFromMidnightMS; |
111 |
116 |
112 ## |
117 ## |
113 ## If this line is about a new process, make a note of the name and the |
118 ## If this line is about a new process, make a note of the name and the |
142 ## take a snapshot and |
147 ## take a snapshot and |
143 ## |
148 ## |
144 if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/) |
149 if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/) |
145 { |
150 { |
146 $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4; |
151 $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4; |
147 # Set up the time for the first snapshot. |
|
148 if ($nextHeartBeatMS == -1) |
152 if ($nextHeartBeatMS == -1) |
149 { |
153 { |
150 $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS; |
154 $nextHeartBeatMS = $firstHeartBeatTimeMS; |
151 } |
155 $logLastLineTimeMS = $timeFromMidnightMS; |
152 } |
156 } |
153 |
157 ## We have wrapped around midnight! |
154 ## |
158 ## Add a 1000ms cushion to the comparison to avoid wrapping around |
155 ## If heartbeat reached, take snapshot of bmp memory per thread |
159 ## midnight if a trace is buffered too slowly. |
156 ## and set next heartbeat time. |
160 if (($timeFromMidnightMS+1000) < $logLastLineTimeMS) |
157 ## |
161 { |
158 while ($timeFromMidnightMS >= $nextHeartBeatMS) |
162 $timeFromMidnightMS += 86400000; |
159 { |
163 } |
160 $nextHeartBeatMS += $heartBeatMS; |
164 $nextHeartBeatMS -= ($timeFromMidnightMS - $logLastLineTimeMS); |
161 # take a snapshot of the current bitmap memory usage per thread |
165 $logLastLineTimeMS = $timeFromMidnightMS; |
162 while ((my $thread, my $bmpMemory) = each(%bmpMemoryPerThread)) |
166 |
163 { |
167 ## |
164 $arrayOfSnapshots[$heartBeatCount]{$thread} = $bmpMemory; |
168 ## If heartbeat reached, take snapshot of bmp memory per thread |
165 } |
169 ## and set next heartbeat time. |
166 $heartBeatCount++; |
170 ## |
|
171 while ($nextHeartBeatMS <= 0) |
|
172 { |
|
173 $nextHeartBeatMS += $heartBeatMS; |
|
174 # take a snapshot of the current bitmap memory usage per thread |
|
175 while ((my $thread, my $bmpMemory) = each(%bmpMemoryPerThread)) |
|
176 { |
|
177 $arrayOfSnapshots[$heartBeatCount]{$thread} = $bmpMemory; |
|
178 } |
|
179 $heartBeatCount++; |
|
180 } |
167 } |
181 } |
168 |
182 |
169 ## FBS Client-side traces. |
183 ## FBS Client-side traces. |
170 if ($line =~ m/\tFBSCLI: /) |
184 if ($line =~ m/\tFBSCLI: /) |
171 { |
185 { |
238 my $bytes = $bmpMemoryByServerHandle{$oldBmpIdentifier}; |
252 my $bytes = $bmpMemoryByServerHandle{$oldBmpIdentifier}; |
239 delete $bmpMemoryByServerHandle{$oldBmpIdentifier}; |
253 delete $bmpMemoryByServerHandle{$oldBmpIdentifier}; |
240 $bmpMemoryByServerHandle{$newBmpIdentifier} = $bytes; |
254 $bmpMemoryByServerHandle{$newBmpIdentifier} = $bytes; |
241 } |
255 } |
242 } |
256 } |
|
257 elsif ($line =~ m/# Server bitmap duplicated.*iH=(\w*);.*bytes=(\d+);/) |
|
258 { |
|
259 if ($countDuplicates == 1) |
|
260 { |
|
261 # When a bitmap is duplicated, the memory is 'owned' by all |
|
262 # threads that duplicate it. |
|
263 my $bmpHandle = $1; |
|
264 my $bmpBytes = $2; |
|
265 my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle"; |
|
266 $bmpMemoryPerThread{$thread} += $bmpBytes; |
|
267 $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes; |
|
268 } |
|
269 } |
243 elsif ($line =~ m/#.*iH=(\w*);.*bytes=(\d+);/) |
270 elsif ($line =~ m/#.*iH=(\w*);.*bytes=(\d+);/) |
244 { |
271 { |
245 # Duplication of a bitmap typically. When a bitmap is duplicated, |
|
246 # the memory is 'owned' by all threads that duplicate it. |
|
247 my $bmpHandle = $1; |
272 my $bmpHandle = $1; |
248 my $bmpBytes = $2; |
273 my $bmpBytes = $2; |
249 my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle"; |
274 my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle"; |
250 $bmpMemoryPerThread{$thread} += $bmpBytes; |
275 $bmpMemoryPerThread{$thread} += $bmpBytes; |
251 $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes; |
276 $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes; |