Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tools/tickprocessor.py

Issue 56064: Fixed numerous issues that were causing errors in profiler log processing (Closed)
Patch Set: Updated according to Soeren's comments Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/regexp-macro-assembler-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 class FunctionEnumerator(object):
151
152 def __init__(self):
153 self.known_funcs = {}
154 self.next_func_id = 0
155
156 def GetFunctionId(self, name):
157 if not self.known_funcs.has_key(name):
158 self.known_funcs[name] = self.next_func_id
159 self.next_func_id += 1
160 return self.known_funcs[name]
161
162 def GetKnownFunctions(self):
163 known_funcs_items = self.known_funcs.items();
164 known_funcs_items.sort(key = itemgetter(1))
165 result = []
166 for func, id_not_used in known_funcs_items:
167 result.append(func)
168 return result
169
170
150 VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3, 'EXTERNAL' : 4 } 171 VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3, 'EXTERNAL' : 4 }
151 172
152 173
153 class TickProcessor(object): 174 class TickProcessor(object):
154 175
155 def __init__(self): 176 def __init__(self):
156 self.log_file = '' 177 self.log_file = ''
157 self.deleted_code = [] 178 self.deleted_code = []
158 self.vm_extent = {} 179 self.vm_extent = {}
159 # Map from assembler ids to the pending assembler objects 180 # Map from assembler ids to the pending assembler objects
160 self.pending_assemblers = {} 181 self.pending_assemblers = {}
161 # Map from code addresses the have been allocated but not yet officially 182 # Map from code addresses the have been allocated but not yet officially
162 # created to their assemblers. 183 # created to their assemblers.
163 self.assemblers = {} 184 self.assemblers = {}
164 self.js_entries = splaytree.SplayTree() 185 self.js_entries = splaytree.SplayTree()
165 self.cpp_entries = splaytree.SplayTree() 186 self.cpp_entries = splaytree.SplayTree()
166 self.total_number_of_ticks = 0 187 self.total_number_of_ticks = 0
167 self.number_of_library_ticks = 0 188 self.number_of_library_ticks = 0
168 self.unaccounted_number_of_ticks = 0 189 self.unaccounted_number_of_ticks = 0
169 self.excluded_number_of_ticks = 0 190 self.excluded_number_of_ticks = 0
170 self.number_of_gc_ticks = 0 191 self.number_of_gc_ticks = 0
171 # Flag indicating whether to ignore unaccounted ticks in the report 192 # Flag indicating whether to ignore unaccounted ticks in the report
172 self.ignore_unknown = False 193 self.ignore_unknown = False
194 self.func_enum = FunctionEnumerator()
195 self.packed_stacks = []
173 196
174 def ProcessLogfile(self, filename, included_state = None, ignore_unknown = Fal se, separate_ic = False): 197 def ProcessLogfile(self, filename, included_state = None, ignore_unknown = Fal se, separate_ic = False, call_graph_json = False):
175 self.log_file = filename 198 self.log_file = filename
176 self.included_state = included_state 199 self.included_state = included_state
177 self.ignore_unknown = ignore_unknown 200 self.ignore_unknown = ignore_unknown
178 self.separate_ic = separate_ic 201 self.separate_ic = separate_ic
202 self.call_graph_json = call_graph_json
179 203
180 try: 204 try:
181 logfile = open(filename, 'rb') 205 logfile = open(filename, 'rb')
182 except IOError: 206 except IOError:
183 sys.exit("Could not open logfile: " + filename) 207 sys.exit("Could not open logfile: " + filename)
184 try: 208 try:
185 logreader = csv.reader(logfile) 209 try:
186 for row in logreader: 210 logreader = csv.reader(logfile)
187 if row[0] == 'tick': 211 row_num = 1
188 self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]), self.P reprocessStack(row[4:])) 212 for row in logreader:
189 elif row[0] == 'code-creation': 213 row_num += 1
190 self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4]) 214 if row[0] == 'tick':
191 elif row[0] == 'code-move': 215 self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]), self .PreprocessStack(row[4:]))
192 self.ProcessCodeMove(int(row[1], 16), int(row[2], 16)) 216 elif row[0] == 'code-creation':
193 elif row[0] == 'code-delete': 217 self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4 ])
194 self.ProcessCodeDelete(int(row[1], 16)) 218 elif row[0] == 'code-move':
195 elif row[0] == 'shared-library': 219 self.ProcessCodeMove(int(row[1], 16), int(row[2], 16))
196 self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16)) 220 elif row[0] == 'code-delete':
197 self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16)) 221 self.ProcessCodeDelete(int(row[1], 16))
198 elif row[0] == 'begin-code-region': 222 elif row[0] == 'shared-library':
199 self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(row[ 3], 16), row[4]) 223 self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16))
200 elif row[0] == 'end-code-region': 224 self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16))
201 self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3] , 16)) 225 elif row[0] == 'begin-code-region':
202 elif row[0] == 'code-allocate': 226 self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(ro w[3], 16), row[4])
203 self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16)) 227 elif row[0] == 'end-code-region':
228 self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[ 3], 16))
229 elif row[0] == 'code-allocate':
230 self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16))
231 except csv.Error:
232 print("parse error in line " + str(row_num))
233 raise
204 finally: 234 finally:
205 logfile.close() 235 logfile.close()
206 236
207 def AddSharedLibraryEntry(self, filename, start, end): 237 def AddSharedLibraryEntry(self, filename, start, end):
208 # Mark the pages used by this library. 238 # Mark the pages used by this library.
209 i = start 239 i = start
210 while i < end: 240 while i < end:
211 page = i >> 12 241 page = i >> 12
212 self.vm_extent[page] = 1 242 self.vm_extent[page] = 1
213 i += 4096 243 i += 4096
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 self.number_of_library_ticks += 1 335 self.number_of_library_ticks += 1
306 if entry.IsICEntry() and not self.separate_ic: 336 if entry.IsICEntry() and not self.separate_ic:
307 if len(stack) > 0: 337 if len(stack) > 0:
308 caller_pc = stack.pop(0) 338 caller_pc = stack.pop(0)
309 self.total_number_of_ticks -= 1 339 self.total_number_of_ticks -= 1
310 self.ProcessTick(caller_pc, sp, state, stack) 340 self.ProcessTick(caller_pc, sp, state, stack)
311 else: 341 else:
312 self.unaccounted_number_of_ticks += 1 342 self.unaccounted_number_of_ticks += 1
313 else: 343 else:
314 entry.Tick(pc, self.ProcessStack(stack)) 344 entry.Tick(pc, self.ProcessStack(stack))
345 if self.call_graph_json:
346 self.AddToPackedStacks(pc, stack)
347
348 def AddToPackedStacks(self, pc, stack):
349 full_stack = stack
350 full_stack.insert(0, pc)
351 func_names = self.ProcessStack(full_stack)
352 func_ids = []
353 for func in func_names:
354 func_ids.append(self.func_enum.GetFunctionId(func))
355 self.packed_stacks.append(func_ids)
315 356
316 def PrintResults(self): 357 def PrintResults(self):
358 if not self.call_graph_json:
359 self.PrintStatistics()
360 else:
361 self.PrintCallGraphJSON()
362
363 def PrintStatistics(self):
317 print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d e xcluded).' % 364 print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d e xcluded).' %
318 (self.log_file, 365 (self.log_file,
319 self.total_number_of_ticks, 366 self.total_number_of_ticks,
320 self.unaccounted_number_of_ticks, 367 self.unaccounted_number_of_ticks,
321 self.excluded_number_of_ticks)) 368 self.excluded_number_of_ticks))
322 if self.total_number_of_ticks > 0: 369 if self.total_number_of_ticks > 0:
323 js_entries = self.js_entries.ExportValueList() 370 js_entries = self.js_entries.ExportValueList()
324 js_entries.extend(self.deleted_code) 371 js_entries.extend(self.deleted_code)
325 cpp_entries = self.cpp_entries.ExportValueList() 372 cpp_entries = self.cpp_entries.ExportValueList()
326 # Print the unknown ticks percentage if they are not ignored. 373 # Print the unknown ticks percentage if they are not ignored.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 'total' : missing_percentage 452 'total' : missing_percentage
406 }) 453 })
407 for stack, count in all_stacks_items: 454 for stack, count in all_stacks_items:
408 total_percentage = count * 100.0 / self.total_number_of_ticks 455 total_percentage = count * 100.0 / self.total_number_of_ticks
409 print(' %(ticks)5d %(total)5.1f%% %(call_path)s' % { 456 print(' %(ticks)5d %(total)5.1f%% %(call_path)s' % {
410 'ticks' : count, 457 'ticks' : count,
411 'total' : total_percentage, 458 'total' : total_percentage,
412 'call_path' : stack[0] + ' <- ' + stack[1] 459 'call_path' : stack[0] + ' <- ' + stack[1]
413 }) 460 })
414 461
462 def PrintCallGraphJSON(self):
463 print('\nvar __profile_funcs = ["' +
464 '",\n"'.join(self.func_enum.GetKnownFunctions()) +
465 '"];')
466 print('var __profile_ticks = [')
467 str_packed_stacks = []
468 for stack in self.packed_stacks:
469 str_packed_stacks.append('[' + ','.join(map(str, stack)) + ']')
470 print(',\n'.join(str_packed_stacks))
471 print('];')
415 472
416 class CmdLineProcessor(object): 473 class CmdLineProcessor(object):
417 474
418 def __init__(self): 475 def __init__(self):
419 self.options = ["js", 476 self.options = ["js",
420 "gc", 477 "gc",
421 "compiler", 478 "compiler",
422 "other", 479 "other",
423 "external", 480 "external",
424 "ignore-unknown", 481 "ignore-unknown",
425 "separate-ic"] 482 "separate-ic",
483 "call-graph-json"]
426 # default values 484 # default values
427 self.state = None 485 self.state = None
428 self.ignore_unknown = False 486 self.ignore_unknown = False
429 self.log_file = None 487 self.log_file = None
430 self.separate_ic = False 488 self.separate_ic = False
489 self.call_graph_json = False
431 490
432 def ProcessArguments(self): 491 def ProcessArguments(self):
433 try: 492 try:
434 opts, args = getopt.getopt(sys.argv[1:], "jgcoe", self.options) 493 opts, args = getopt.getopt(sys.argv[1:], "jgcoe", self.options)
435 except getopt.GetoptError: 494 except getopt.GetoptError:
436 self.PrintUsageAndExit() 495 self.PrintUsageAndExit()
437 for key, value in opts: 496 for key, value in opts:
438 if key in ("-j", "--js"): 497 if key in ("-j", "--js"):
439 self.state = VMStates['JS'] 498 self.state = VMStates['JS']
440 if key in ("-g", "--gc"): 499 if key in ("-g", "--gc"):
441 self.state = VMStates['GC'] 500 self.state = VMStates['GC']
442 if key in ("-c", "--compiler"): 501 if key in ("-c", "--compiler"):
443 self.state = VMStates['COMPILER'] 502 self.state = VMStates['COMPILER']
444 if key in ("-o", "--other"): 503 if key in ("-o", "--other"):
445 self.state = VMStates['OTHER'] 504 self.state = VMStates['OTHER']
446 if key in ("-e", "--external"): 505 if key in ("-e", "--external"):
447 self.state = VMStates['EXTERNAL'] 506 self.state = VMStates['EXTERNAL']
448 if key in ("--ignore-unknown"): 507 if key in ("--ignore-unknown"):
449 self.ignore_unknown = True 508 self.ignore_unknown = True
450 if key in ("--separate-ic"): 509 if key in ("--separate-ic"):
451 self.separate_ic = True 510 self.separate_ic = True
511 if key in ("--call-graph-json"):
512 self.call_graph_json = True
452 self.ProcessRequiredArgs(args) 513 self.ProcessRequiredArgs(args)
453 514
454 def ProcessRequiredArgs(self, args): 515 def ProcessRequiredArgs(self, args):
455 return 516 return
456 517
457 def GetRequiredArgsNames(self): 518 def GetRequiredArgsNames(self):
458 return 519 return
459 520
460 def PrintUsageAndExit(self): 521 def PrintUsageAndExit(self):
461 print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % { 522 print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % {
462 'script_name': os.path.basename(sys.argv[0]), 523 'script_name': os.path.basename(sys.argv[0]),
463 'opts': string.join(self.options, ','), 524 'opts': string.join(self.options, ','),
464 'req_opts': self.GetRequiredArgsNames() 525 'req_opts': self.GetRequiredArgsNames()
465 }) 526 })
466 sys.exit(2) 527 sys.exit(2)
467 528
468 def RunLogfileProcessing(self, tick_processor): 529 def RunLogfileProcessing(self, tick_processor):
469 tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown , self.separate_ic) 530 tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown ,
531 self.separate_ic, self.call_graph_json)
470 532
471 533
472 if __name__ == '__main__': 534 if __name__ == '__main__':
473 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro cessor.py.') 535 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro cessor.py.')
OLDNEW
« no previous file with comments | « src/regexp-macro-assembler-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698