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

Unified Diff: tools/tickprocessor.py

Issue 21403: Added the simplest call stack sampling and call profile in tick processor output. (Closed)
Patch Set: Merged after Soren's changes to logging Created 11 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/platform-win32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/tickprocessor.py
diff --git a/tools/tickprocessor.py b/tools/tickprocessor.py
index 7de022f1dde6f78b71e21ee56bf73bc943f1875b..cc5137143572caffa42184359c9b508bae5fbda1 100644
--- a/tools/tickprocessor.py
+++ b/tools/tickprocessor.py
@@ -26,6 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import csv, splaytree, sys
+from operator import itemgetter
class CodeEntry(object):
@@ -34,9 +35,14 @@ class CodeEntry(object):
self.start_addr = start_addr
self.tick_count = 0
self.name = name
+ self.stacks = {}
- def Tick(self, pc):
+ def Tick(self, pc, stack):
self.tick_count += 1
+ if len(stack) > 0:
+ stack.insert(0, self.ToString())
+ stack_key = tuple(stack)
+ self.stacks[stack_key] = self.stacks.setdefault(stack_key, 0) + 1
def RegionTicks(self):
return None
@@ -69,8 +75,8 @@ class JSCodeEntry(CodeEntry):
self.assembler = assembler
self.region_ticks = None
- def Tick(self, pc):
- super(JSCodeEntry, self).Tick(pc)
+ def Tick(self, pc, stack):
+ super(JSCodeEntry, self).Tick(pc, stack)
if not pc is None:
offset = pc - self.start_addr
seen = []
@@ -162,7 +168,7 @@ class TickProcessor(object):
logreader = csv.reader(logfile)
for row in logreader:
if row[0] == 'tick':
- self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]))
+ self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]), row[4:])
elif row[0] == 'code-creation':
self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4])
elif row[0] == 'code-move':
@@ -237,25 +243,41 @@ class TickProcessor(object):
def IncludeTick(self, pc, sp, state):
return (self.included_state is None) or (self.included_state == state)
- def ProcessTick(self, pc, sp, state):
- if not self.IncludeTick(pc, sp, state):
- self.excluded_number_of_ticks += 1;
- return
- self.total_number_of_ticks += 1
+ def FindEntry(self, pc):
page = pc >> 12
if page in self.vm_extent:
- entry = self.cpp_entries.FindGreatestsLessThan(pc).value
- if entry.IsSharedLibraryEntry():
- self.number_of_library_ticks += 1
- entry.Tick(None)
- return
+ entry = self.cpp_entries.FindGreatestsLessThan(pc)
+ if entry != None:
+ return entry.value
+ else:
+ return entry
max = self.js_entries.FindMax()
min = self.js_entries.FindMin()
if max != None and pc < max.key and pc > min.key:
- code_obj = self.js_entries.FindGreatestsLessThan(pc).value
- code_obj.Tick(pc)
+ return self.js_entries.FindGreatestsLessThan(pc).value
+ return None
+
+ def ProcessStack(self, stack):
+ result = []
+ for frame in stack:
+ if frame.startswith('0x'):
+ entry = self.FindEntry(int(frame, 16))
+ if entry != None:
+ result.append(entry.ToString())
+ return result
+
+ def ProcessTick(self, pc, sp, state, stack):
+ if not self.IncludeTick(pc, sp, state):
+ self.excluded_number_of_ticks += 1;
return
- self.unaccounted_number_of_ticks += 1
+ self.total_number_of_ticks += 1
+ entry = self.FindEntry(pc)
+ if entry == None:
+ self.unaccounted_number_of_ticks += 1
+ return
+ if entry.IsSharedLibraryEntry():
+ self.number_of_library_ticks += 1
+ entry.Tick(pc, self.ProcessStack(stack))
def PrintResults(self):
print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d excluded).' %
@@ -276,6 +298,11 @@ class TickProcessor(object):
# Print the C++ ticks.
self.PrintHeader('C++')
self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry())
+ # Print call profile.
+ print('\n [Call profile]:')
+ print(' total call path')
+ js_entries.extend(cpp_entries)
+ self.PrintCallProfile(js_entries)
def PrintHeader(self, header_title):
print('\n [%s]:' % header_title)
@@ -309,5 +336,21 @@ class TickProcessor(object):
'name': name
})
+ def PrintCallProfile(self, entries):
+ all_stacks = {}
+ total_stacks = 0
+ for entry in entries:
+ all_stacks.update(entry.stacks)
+ for count in entry.stacks.itervalues():
+ total_stacks += count
+ all_stacks_items = all_stacks.items();
+ all_stacks_items.sort(key = itemgetter(1), reverse=True)
+ for stack, count in all_stacks_items:
+ total_percentage = count * 100.0 / total_stacks
+ print(' %(total)5.1f%% %(call_path)s' % {
+ 'total' : total_percentage,
+ 'call_path' : stack[0] + ' <- ' + stack[1]
+ })
+
if __name__ == '__main__':
sys.exit('You probably want to run windows-tick-processor.py or linux-tick-processor.py.')
« no previous file with comments | « src/platform-win32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698