OLD | NEW |
1 # Copyright 2008 the V8 project authors. All rights reserved. | 1 # Copyright 2008 the V8 project authors. All rights reserved. |
2 # Redistribution and use in source and binary forms, with or without | 2 # Redistribution and use in source and binary forms, with or without |
3 # modification, are permitted provided that the following conditions are | 3 # modification, are permitted provided that the following conditions are |
4 # met: | 4 # met: |
5 # | 5 # |
6 # * Redistributions of source code must retain the above copyright | 6 # * Redistributions of source code must retain the above copyright |
7 # notice, this list of conditions and the following disclaimer. | 7 # notice, this list of conditions and the following disclaimer. |
8 # * Redistributions in binary form must reproduce the above | 8 # * Redistributions in binary form must reproduce the above |
9 # copyright notice, this list of conditions and the following | 9 # copyright notice, this list of conditions and the following |
10 # disclaimer in the documentation and/or other materials provided | 10 # disclaimer in the documentation and/or other materials provided |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 | 140 |
141 | 141 |
142 class Assembler(object): | 142 class Assembler(object): |
143 | 143 |
144 def __init__(self): | 144 def __init__(self): |
145 # Mapping from region ids to open regions | 145 # Mapping from region ids to open regions |
146 self.pending_regions = {} | 146 self.pending_regions = {} |
147 self.regions = [] | 147 self.regions = [] |
148 | 148 |
149 | 149 |
| 150 VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3 } |
| 151 |
| 152 |
150 class TickProcessor(object): | 153 class TickProcessor(object): |
151 | 154 |
152 def __init__(self): | 155 def __init__(self): |
153 self.log_file = '' | 156 self.log_file = '' |
154 self.deleted_code = [] | 157 self.deleted_code = [] |
155 self.vm_extent = {} | 158 self.vm_extent = {} |
156 # Map from assembler ids to the pending assembler objects | 159 # Map from assembler ids to the pending assembler objects |
157 self.pending_assemblers = {} | 160 self.pending_assemblers = {} |
158 # Map from code addresses the have been allocated but not yet officially | 161 # Map from code addresses the have been allocated but not yet officially |
159 # created to their assemblers. | 162 # created to their assemblers. |
160 self.assemblers = {} | 163 self.assemblers = {} |
161 self.js_entries = splaytree.SplayTree() | 164 self.js_entries = splaytree.SplayTree() |
162 self.cpp_entries = splaytree.SplayTree() | 165 self.cpp_entries = splaytree.SplayTree() |
163 self.total_number_of_ticks = 0 | 166 self.total_number_of_ticks = 0 |
164 self.number_of_library_ticks = 0 | 167 self.number_of_library_ticks = 0 |
165 self.unaccounted_number_of_ticks = 0 | 168 self.unaccounted_number_of_ticks = 0 |
166 self.excluded_number_of_ticks = 0 | 169 self.excluded_number_of_ticks = 0 |
| 170 self.number_of_gc_ticks = 0 |
167 # Flag indicating whether to ignore unaccounted ticks in the report | 171 # Flag indicating whether to ignore unaccounted ticks in the report |
168 self.ignore_unknown = False | 172 self.ignore_unknown = False |
169 | 173 |
170 def ProcessLogfile(self, filename, included_state = None, ignore_unknown = Fal
se, separate_ic = False): | 174 def ProcessLogfile(self, filename, included_state = None, ignore_unknown = Fal
se, separate_ic = False): |
171 self.log_file = filename | 175 self.log_file = filename |
172 self.included_state = included_state | 176 self.included_state = included_state |
173 self.ignore_unknown = ignore_unknown | 177 self.ignore_unknown = ignore_unknown |
174 self.separate_ic = separate_ic | 178 self.separate_ic = separate_ic |
175 | 179 |
176 try: | 180 try: |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 284 |
281 def ProcessStack(self, stack): | 285 def ProcessStack(self, stack): |
282 result = [] | 286 result = [] |
283 for frame in stack: | 287 for frame in stack: |
284 entry = self.FindEntry(frame) | 288 entry = self.FindEntry(frame) |
285 if entry != None: | 289 if entry != None: |
286 result.append(entry.ToString()) | 290 result.append(entry.ToString()) |
287 return result | 291 return result |
288 | 292 |
289 def ProcessTick(self, pc, sp, state, stack): | 293 def ProcessTick(self, pc, sp, state, stack): |
| 294 if state == VMStates['GC']: |
| 295 self.number_of_gc_ticks += 1 |
290 if not self.IncludeTick(pc, sp, state): | 296 if not self.IncludeTick(pc, sp, state): |
291 self.excluded_number_of_ticks += 1; | 297 self.excluded_number_of_ticks += 1; |
292 return | 298 return |
293 self.total_number_of_ticks += 1 | 299 self.total_number_of_ticks += 1 |
294 entry = self.FindEntry(pc) | 300 entry = self.FindEntry(pc) |
295 if entry == None: | 301 if entry == None: |
296 self.unaccounted_number_of_ticks += 1 | 302 self.unaccounted_number_of_ticks += 1 |
297 return | 303 return |
298 if entry.IsSharedLibraryEntry(): | 304 if entry.IsSharedLibraryEntry(): |
299 self.number_of_library_ticks += 1 | 305 self.number_of_library_ticks += 1 |
(...skipping 13 matching lines...) Expand all Loading... |
313 self.total_number_of_ticks, | 319 self.total_number_of_ticks, |
314 self.unaccounted_number_of_ticks, | 320 self.unaccounted_number_of_ticks, |
315 self.excluded_number_of_ticks)) | 321 self.excluded_number_of_ticks)) |
316 if self.total_number_of_ticks > 0: | 322 if self.total_number_of_ticks > 0: |
317 js_entries = self.js_entries.ExportValueList() | 323 js_entries = self.js_entries.ExportValueList() |
318 js_entries.extend(self.deleted_code) | 324 js_entries.extend(self.deleted_code) |
319 cpp_entries = self.cpp_entries.ExportValueList() | 325 cpp_entries = self.cpp_entries.ExportValueList() |
320 # Print the unknown ticks percentage if they are not ignored. | 326 # Print the unknown ticks percentage if they are not ignored. |
321 if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0: | 327 if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0: |
322 self.PrintHeader('Unknown') | 328 self.PrintHeader('Unknown') |
323 unknown_percentage = self.unaccounted_number_of_ticks * 100.0 / self.tot
al_number_of_ticks | 329 self.PrintCounter(self.unaccounted_number_of_ticks) |
324 print(' %(ticks)5d %(total)5.1f%%' % { | |
325 'ticks' : self.unaccounted_number_of_ticks, | |
326 'total' : unknown_percentage, | |
327 }) | |
328 # Print the library ticks. | 330 # Print the library ticks. |
329 self.PrintHeader('Shared libraries') | 331 self.PrintHeader('Shared libraries') |
330 self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry()) | 332 self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry()) |
331 # Print the JavaScript ticks. | 333 # Print the JavaScript ticks. |
332 self.PrintHeader('JavaScript') | 334 self.PrintHeader('JavaScript') |
333 self.PrintEntries(js_entries, lambda e:not e.IsSharedLibraryEntry()) | 335 self.PrintEntries(js_entries, lambda e:not e.IsSharedLibraryEntry()) |
334 # Print the C++ ticks. | 336 # Print the C++ ticks. |
335 self.PrintHeader('C++') | 337 self.PrintHeader('C++') |
336 self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry()) | 338 self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry()) |
| 339 # Print the GC ticks. |
| 340 self.PrintHeader('GC') |
| 341 self.PrintCounter(self.number_of_gc_ticks) |
337 # Print call profile. | 342 # Print call profile. |
338 print('\n [Call profile]:') | 343 print('\n [Call profile]:') |
339 print(' total call path') | 344 print(' total call path') |
340 js_entries.extend(cpp_entries) | 345 js_entries.extend(cpp_entries) |
341 self.PrintCallProfile(js_entries) | 346 self.PrintCallProfile(js_entries) |
342 | 347 |
343 def PrintHeader(self, header_title): | 348 def PrintHeader(self, header_title): |
344 print('\n [%s]:' % header_title) | 349 print('\n [%s]:' % header_title) |
345 print(' ticks total nonlib name') | 350 print(' ticks total nonlib name') |
346 | 351 |
| 352 def PrintCounter(self, ticks_count): |
| 353 percentage = ticks_count * 100.0 / self.total_number_of_ticks |
| 354 print(' %(ticks)5d %(total)5.1f%%' % { |
| 355 'ticks' : ticks_count, |
| 356 'total' : percentage, |
| 357 }) |
| 358 |
347 def PrintEntries(self, entries, condition): | 359 def PrintEntries(self, entries, condition): |
348 # If ignoring unaccounted ticks don't include these in percentage | 360 # If ignoring unaccounted ticks don't include these in percentage |
349 # calculations | 361 # calculations |
350 number_of_accounted_ticks = self.total_number_of_ticks | 362 number_of_accounted_ticks = self.total_number_of_ticks |
351 if self.ignore_unknown: | 363 if self.ignore_unknown: |
352 number_of_accounted_ticks -= self.unaccounted_number_of_ticks | 364 number_of_accounted_ticks -= self.unaccounted_number_of_ticks |
353 | 365 |
354 number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_lib
rary_ticks | 366 number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_lib
rary_ticks |
355 entries.sort(key=lambda e:e.tick_count, reverse=True) | 367 entries.sort(key=lambda e:e.tick_count, reverse=True) |
356 for entry in entries: | 368 for entry in entries: |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 self.log_file = None | 423 self.log_file = None |
412 self.separate_ic = False | 424 self.separate_ic = False |
413 | 425 |
414 def ProcessArguments(self): | 426 def ProcessArguments(self): |
415 try: | 427 try: |
416 opts, args = getopt.getopt(sys.argv[1:], "jgco", self.options) | 428 opts, args = getopt.getopt(sys.argv[1:], "jgco", self.options) |
417 except getopt.GetoptError: | 429 except getopt.GetoptError: |
418 self.PrintUsageAndExit() | 430 self.PrintUsageAndExit() |
419 for key, value in opts: | 431 for key, value in opts: |
420 if key in ("-j", "--js"): | 432 if key in ("-j", "--js"): |
421 self.state = 0 | 433 self.state = VMStates['JS'] |
422 if key in ("-g", "--gc"): | 434 if key in ("-g", "--gc"): |
423 self.state = 1 | 435 self.state = VMStates['GC'] |
424 if key in ("-c", "--compiler"): | 436 if key in ("-c", "--compiler"): |
425 self.state = 2 | 437 self.state = VMStates['COMPILER'] |
426 if key in ("-o", "--other"): | 438 if key in ("-o", "--other"): |
427 self.state = 3 | 439 self.state = VMStates['OTHER'] |
428 if key in ("--ignore-unknown"): | 440 if key in ("--ignore-unknown"): |
429 self.ignore_unknown = True | 441 self.ignore_unknown = True |
430 if key in ("--separate-ic"): | 442 if key in ("--separate-ic"): |
431 self.separate_ic = True | 443 self.separate_ic = True |
432 self.ProcessRequiredArgs(args) | 444 self.ProcessRequiredArgs(args) |
433 | 445 |
434 def ProcessRequiredArgs(self, args): | 446 def ProcessRequiredArgs(self, args): |
435 return | 447 return |
436 | 448 |
437 def GetRequiredArgsNames(self): | 449 def GetRequiredArgsNames(self): |
438 return | 450 return |
439 | 451 |
440 def PrintUsageAndExit(self): | 452 def PrintUsageAndExit(self): |
441 print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % { | 453 print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % { |
442 'script_name': os.path.basename(sys.argv[0]), | 454 'script_name': os.path.basename(sys.argv[0]), |
443 'opts': string.join(self.options, ','), | 455 'opts': string.join(self.options, ','), |
444 'req_opts': self.GetRequiredArgsNames() | 456 'req_opts': self.GetRequiredArgsNames() |
445 }) | 457 }) |
446 sys.exit(2) | 458 sys.exit(2) |
447 | 459 |
448 def RunLogfileProcessing(self, tick_processor): | 460 def RunLogfileProcessing(self, tick_processor): |
449 tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown
, self.separate_ic) | 461 tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown
, self.separate_ic) |
450 | 462 |
451 | 463 |
452 if __name__ == '__main__': | 464 if __name__ == '__main__': |
453 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro
cessor.py.') | 465 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro
cessor.py.') |
OLD | NEW |