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

Side by Side Diff: tools/tickprocessor.py

Issue 14888: Code regions (Closed)
Patch Set: Created 12 years 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
« src/log.h ('K') | « src/macro-assembler-ia32.h ('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 17 matching lines...) Expand all
28 import csv, splaytree, sys 28 import csv, splaytree, sys
29 29
30 30
31 class CodeEntry(object): 31 class CodeEntry(object):
32 32
33 def __init__(self, start_addr, name): 33 def __init__(self, start_addr, name):
34 self.start_addr = start_addr 34 self.start_addr = start_addr
35 self.tick_count = 0 35 self.tick_count = 0
36 self.name = name 36 self.name = name
37 37
38 def IncrementTickCount(self): 38 def Tick(self, pc):
39 self.tick_count += 1 39 self.tick_count += 1
40 40
41 def RegionTicks(self):
42 return None
43
41 def SetStartAddress(self, start_addr): 44 def SetStartAddress(self, start_addr):
42 self.start_addr = start_addr 45 self.start_addr = start_addr
43 46
44 def ToString(self): 47 def ToString(self):
45 return self.name 48 return self.name
46 49
47 def IsSharedLibraryEntry(self): 50 def IsSharedLibraryEntry(self):
48 return False 51 return False
49 52
50 53
51 class SharedLibraryEntry(CodeEntry): 54 class SharedLibraryEntry(CodeEntry):
52 55
53 def __init__(self, start_addr, name): 56 def __init__(self, start_addr, name):
54 CodeEntry.__init__(self, start_addr, name) 57 CodeEntry.__init__(self, start_addr, name)
55 58
56 def IsSharedLibraryEntry(self): 59 def IsSharedLibraryEntry(self):
57 return True 60 return True
58 61
59 62
60 class JSCodeEntry(CodeEntry): 63 class JSCodeEntry(CodeEntry):
61 64
62 def __init__(self, start_addr, name, type, size): 65 def __init__(self, start_addr, name, type, size, assembler):
63 CodeEntry.__init__(self, start_addr, name) 66 CodeEntry.__init__(self, start_addr, name)
64 self.type = type 67 self.type = type
65 self.size = size 68 self.size = size
69 self.assembler = assembler
70 self.region_ticks = None
71
72 def Tick(self, pc):
73 super(JSCodeEntry, self).Tick(pc)
74 if not pc is None:
75 offset = pc - self.start_addr
76 seen = []
77 narrowest = None
78 narrowest_width = None
79 for region in self.Regions():
80 if region.Contains(offset):
81 if (not region.name in seen):
82 seen.append(region.name)
83 if narrowest is None or region.Width() < narrowest.Width():
84 narrowest = region
85 if len(seen) == 0:
86 return
87 if self.region_ticks is None:
88 self.region_ticks = {}
89 for name in seen:
90 if not name in self.region_ticks:
91 self.region_ticks[name] = [0, 0]
92 self.region_ticks[name][0] += 1
93 if name == narrowest.name:
94 self.region_ticks[name][1] += 1
95
96 def RegionTicks(self):
97 return self.region_ticks
98
99 def Regions(self):
100 if self.assembler:
101 return self.assembler.regions
102 else:
103 return []
66 104
67 def ToString(self): 105 def ToString(self):
68 name = self.name 106 name = self.name
69 if name == '': name = '<anonymous>' 107 if name == '': name = '<anonymous>'
70 return self.type + ': ' + name 108 return self.type + ': ' + name
71 109
72 110
111 class CodeRegion(object):
112
113 def __init__(self, start_offset, name):
114 self.start_offset = start_offset
115 self.name = name
116 self.end_offset = None
117
118 def Contains(self, pc):
119 return (self.start_offset <= pc) and (pc <= self.end_offset)
120
121 def Width(self):
122 return self.end_offset - self.start_offset
123
124
125 class Assembler(object):
126
127 def __init__(self):
128 # Mapping from region ids to open regions
129 self.pending_regions = {}
130 self.regions = []
131
132
73 class TickProcessor(object): 133 class TickProcessor(object):
74 134
75 def __init__(self): 135 def __init__(self):
76 self.log_file = '' 136 self.log_file = ''
77 self.deleted_code = [] 137 self.deleted_code = []
78 self.vm_extent = {} 138 self.vm_extent = {}
139 # Map from assembler ids to the pending assembler objects
140 self.pending_assemblers = {}
141 # Map from code addresses the have been allocated but not yet officially
142 # created to their assemblers.
143 self.assemblers = {}
79 self.js_entries = splaytree.SplayTree() 144 self.js_entries = splaytree.SplayTree()
80 self.cpp_entries = splaytree.SplayTree() 145 self.cpp_entries = splaytree.SplayTree()
81 self.total_number_of_ticks = 0 146 self.total_number_of_ticks = 0
82 self.number_of_library_ticks = 0 147 self.number_of_library_ticks = 0
83 self.unaccounted_number_of_ticks = 0 148 self.unaccounted_number_of_ticks = 0
84 self.excluded_number_of_ticks = 0 149 self.excluded_number_of_ticks = 0
85 150
86 def ProcessLogfile(self, filename, included_state = None): 151 def ProcessLogfile(self, filename, included_state = None):
87 self.log_file = filename 152 self.log_file = filename
88 self.included_state = included_state 153 self.included_state = included_state
89 try: 154 try:
90 logfile = open(filename, 'rb') 155 logfile = open(filename, 'rb')
91 except IOError: 156 except IOError:
92 sys.exit("Could not open logfile: " + filename) 157 sys.exit("Could not open logfile: " + filename)
93 try: 158 try:
94 logreader = csv.reader(logfile) 159 logreader = csv.reader(logfile)
95 for row in logreader: 160 for row in logreader:
96 if row[0] == 'tick': 161 if row[0] == 'tick':
97 self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3])) 162 self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]))
98 elif row[0] == 'code-creation': 163 elif row[0] == 'code-creation':
99 self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4]) 164 self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4])
100 elif row[0] == 'code-move': 165 elif row[0] == 'code-move':
101 self.ProcessCodeMove(int(row[1], 16), int(row[2], 16)) 166 self.ProcessCodeMove(int(row[1], 16), int(row[2], 16))
102 elif row[0] == 'code-delete': 167 elif row[0] == 'code-delete':
103 self.ProcessCodeDelete(int(row[1], 16)) 168 self.ProcessCodeDelete(int(row[1], 16))
104 elif row[0] == 'shared-library': 169 elif row[0] == 'shared-library':
105 self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16)) 170 self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16))
106 self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16)) 171 self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16))
172 elif row[0] == 'begin-code-region':
173 self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(row[ 3], 16), row[4])
174 elif row[0] == 'end-code-region':
175 self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3] , 16))
176 elif row[0] == 'code-allocate':
177 self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16))
107 finally: 178 finally:
108 logfile.close() 179 logfile.close()
109 180
110 def AddSharedLibraryEntry(self, filename, start, end): 181 def AddSharedLibraryEntry(self, filename, start, end):
111 # Mark the pages used by this library. 182 # Mark the pages used by this library.
112 i = start 183 i = start
113 while i < end: 184 while i < end:
114 page = i >> 12 185 page = i >> 12
115 self.vm_extent[page] = 1 186 self.vm_extent[page] = 1
116 i += 4096 187 i += 4096
117 # Add the library to the entries so that ticks for which we do not 188 # Add the library to the entries so that ticks for which we do not
118 # have symbol information is reported as belonging to the library. 189 # have symbol information is reported as belonging to the library.
119 self.cpp_entries.Insert(start, SharedLibraryEntry(start, filename)) 190 self.cpp_entries.Insert(start, SharedLibraryEntry(start, filename))
120 191
121 def ParseVMSymbols(self, filename, start, end): 192 def ParseVMSymbols(self, filename, start, end):
122 return 193 return
123 194
195 def ProcessCodeAllocate(self, addr, assem):
196 if assem in self.pending_assemblers:
197 assembler = self.pending_assemblers.pop(assem)
198 self.assemblers[addr] = assembler
199
124 def ProcessCodeCreation(self, type, addr, size, name): 200 def ProcessCodeCreation(self, type, addr, size, name):
125 self.js_entries.Insert(addr, JSCodeEntry(addr, name, type, size)) 201 if addr in self.assemblers:
202 assembler = self.assemblers.pop(addr)
203 else:
204 assembler = None
205 self.js_entries.Insert(addr, JSCodeEntry(addr, name, type, size, assembler))
126 206
127 def ProcessCodeMove(self, from_addr, to_addr): 207 def ProcessCodeMove(self, from_addr, to_addr):
128 try: 208 try:
129 removed_node = self.js_entries.Remove(from_addr) 209 removed_node = self.js_entries.Remove(from_addr)
130 removed_node.value.SetStartAddress(to_addr); 210 removed_node.value.SetStartAddress(to_addr);
131 self.js_entries.Insert(to_addr, removed_node.value) 211 self.js_entries.Insert(to_addr, removed_node.value)
132 except 'KeyNotFound': 212 except 'KeyNotFound':
133 print('Code move event for unknown code: 0x%x' % from_addr) 213 print('Code move event for unknown code: 0x%x' % from_addr)
134 214
135 def ProcessCodeDelete(self, from_addr): 215 def ProcessCodeDelete(self, from_addr):
136 try: 216 try:
137 removed_node = self.js_entries.Remove(from_addr) 217 removed_node = self.js_entries.Remove(from_addr)
138 self.deleted_code.append(removed_node.value) 218 self.deleted_code.append(removed_node.value)
139 except 'KeyNotFound': 219 except 'KeyNotFound':
140 print('Code delete event for unknown code: 0x%x' % from_addr) 220 print('Code delete event for unknown code: 0x%x' % from_addr)
141 221
222 def ProcessBeginCodeRegion(self, id, assm, start, name):
223 if not assm in self.pending_assemblers:
224 self.pending_assemblers[assm] = Assembler()
225 assembler = self.pending_assemblers[assm]
226 assembler.pending_regions[id] = CodeRegion(start, name)
227
228 def ProcessEndCodeRegion(self, id, assm, end):
229 assm = self.pending_assemblers[assm]
230 region = assm.pending_regions.pop(id)
231 region.end_offset = end
232 assm.regions.append(region)
233
142 def IncludeTick(self, pc, sp, state): 234 def IncludeTick(self, pc, sp, state):
143 return (self.included_state is None) or (self.included_state == state) 235 return (self.included_state is None) or (self.included_state == state)
144 236
145 def ProcessTick(self, pc, sp, state): 237 def ProcessTick(self, pc, sp, state):
146 if not self.IncludeTick(pc, sp, state): 238 if not self.IncludeTick(pc, sp, state):
147 self.excluded_number_of_ticks += 1; 239 self.excluded_number_of_ticks += 1;
148 return 240 return
149 self.total_number_of_ticks += 1 241 self.total_number_of_ticks += 1
150 page = pc >> 12 242 page = pc >> 12
151 if page in self.vm_extent: 243 if page in self.vm_extent:
152 entry = self.cpp_entries.FindGreatestsLessThan(pc).value 244 entry = self.cpp_entries.FindGreatestsLessThan(pc).value
153 if entry.IsSharedLibraryEntry(): 245 if entry.IsSharedLibraryEntry():
154 self.number_of_library_ticks += 1 246 self.number_of_library_ticks += 1
155 entry.IncrementTickCount() 247 entry.Tick(None)
156 return 248 return
157 max = self.js_entries.FindMax() 249 max = self.js_entries.FindMax()
158 min = self.js_entries.FindMin() 250 min = self.js_entries.FindMin()
159 if max != None and pc < max.key and pc > min.key: 251 if max != None and pc < max.key and pc > min.key:
160 self.js_entries.FindGreatestsLessThan(pc).value.IncrementTickCount() 252 code_obj = self.js_entries.FindGreatestsLessThan(pc).value
253 code_obj.Tick(pc)
161 return 254 return
162 self.unaccounted_number_of_ticks += 1 255 self.unaccounted_number_of_ticks += 1
163 256
164 def PrintResults(self): 257 def PrintResults(self):
165 print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d e xcluded).' % 258 print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d e xcluded).' %
166 (self.log_file, 259 (self.log_file,
167 self.total_number_of_ticks, 260 self.total_number_of_ticks,
168 self.unaccounted_number_of_ticks, 261 self.unaccounted_number_of_ticks,
169 self.excluded_number_of_ticks)) 262 self.excluded_number_of_ticks))
170 if self.total_number_of_ticks > 0: 263 if self.total_number_of_ticks > 0:
(...skipping 23 matching lines...) Expand all
194 total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks 287 total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks
195 if entry.IsSharedLibraryEntry(): 288 if entry.IsSharedLibraryEntry():
196 non_library_percentage = 0 289 non_library_percentage = 0
197 else: 290 else:
198 non_library_percentage = entry.tick_count * 100.0 / number_of_non_libr ary_ticks 291 non_library_percentage = entry.tick_count * 100.0 / number_of_non_libr ary_ticks
199 print(' %(total)5.1f%% %(nonlib)6.1f%% %(name)s' % { 292 print(' %(total)5.1f%% %(nonlib)6.1f%% %(name)s' % {
200 'total' : total_percentage, 293 'total' : total_percentage,
201 'nonlib' : non_library_percentage, 294 'nonlib' : non_library_percentage,
202 'name' : entry.ToString() 295 'name' : entry.ToString()
203 }) 296 })
297 region_ticks = entry.RegionTicks()
298 if not region_ticks is None:
299 items = region_ticks.items()
300 items.sort(key=lambda e: e[1][1], reverse=True)
301 for (name, ticks) in items:
302 print(' - %(cumulated)5.1f%% %(total)5.1f%% %(name )s' % {
303 'cumulated' : ticks[1] * 100.0 / entry.tick_count,
304 'total' : ticks[0] * 100.0 / entry.tick_count,
305 'name': name
306 })
204 307
205 if __name__ == '__main__': 308 if __name__ == '__main__':
206 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro cessor.py.') 309 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-pro cessor.py.')
OLDNEW
« src/log.h ('K') | « src/macro-assembler-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698