1e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org#!/usr/bin/env python 2e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# 3e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# Copyright 2009 the V8 project authors. All rights reserved. 4e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# Redistribution and use in source and binary forms, with or without 5e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# modification, are permitted provided that the following conditions are 6e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# met: 7e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# 8e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# * Redistributions of source code must retain the above copyright 9e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# notice, this list of conditions and the following disclaimer. 10e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# * Redistributions in binary form must reproduce the above 11e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# copyright notice, this list of conditions and the following 12e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# disclaimer in the documentation and/or other materials provided 13e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# with the distribution. 14e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# * Neither the name of Google Inc. nor the names of its 15e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# contributors may be used to endorse or promote products derived 16e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# from this software without specific prior written permission. 17e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# 18e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 30e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# This is an utility for converting V8 heap logs into .hp files that can 31e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# be further processed using 'hp2ps' tool (bundled with GHC and Valgrind) 32e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# to produce heap usage histograms. 33e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 34e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# Sample usage: 35e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# $ ./shell --log-gc script.js 36e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# $ tools/process-heap-prof.py v8.log | hp2ps -c > script-heap-graph.ps 37e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org# ('-c' enables color, see hp2ps manual page for more options) 380b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org# or 390b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org# $ tools/process-heap-prof.py --js-cons-profile v8.log | hp2ps -c > script-heap-graph.ps 400b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org# to get JS constructor profile 410b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org 42e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 43c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgimport csv, sys, time, optparse 44e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 45c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgdef ProcessLogFile(filename, options): 46c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if options.js_cons_profile: 47c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org itemname = 'heap-js-cons-item' 48c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org else: 49c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org itemname = 'heap-sample-item' 501805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 51e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org first_call_time = None 52e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sample_time = 0.0 53e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sampling = False 54e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org try: 55e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org logfile = open(filename, 'rb') 56e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org try: 57e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org logreader = csv.reader(logfile) 58e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 59e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('JOB "v8"') 60e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('DATE "%s"' % time.asctime(time.localtime())) 61e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('SAMPLE_UNIT "seconds"') 62e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('VALUE_UNIT "bytes"') 63e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 64e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org for row in logreader: 65e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org if row[0] == 'heap-sample-begin' and row[1] == 'Heap': 66e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sample_time = float(row[3])/1000.0 67e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org if first_call_time == None: 68e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org first_call_time = sample_time 69e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sample_time -= first_call_time 70e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('BEGIN_SAMPLE %.2f' % sample_time) 71e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sampling = True 72e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org elif row[0] == 'heap-sample-end' and row[1] == 'Heap': 73e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org print('END_SAMPLE %.2f' % sample_time) 74e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sampling = False 750b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org elif row[0] == itemname and sampling: 76c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org print(row[1]), 77c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if options.count: 78c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org print('%d' % (int(row[2]))), 79c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if options.size: 80c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org print('%d' % (int(row[3]))), 81c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org print 82e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org finally: 83e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org logfile.close() 84e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org except: 85e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org sys.exit('can\'t open %s' % filename) 86e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 87c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 88c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgdef BuildOptions(): 89c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org result = optparse.OptionParser() 90c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org result.add_option("--js_cons_profile", help="Constructor profile", 91c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org default=False, action="store_true") 92c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org result.add_option("--size", help="Report object size", 93c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org default=False, action="store_true") 94c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org result.add_option("--count", help="Report object count", 95c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org default=False, action="store_true") 96c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org return result 97c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 98c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 99c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgdef ProcessOptions(options): 100c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if not options.size and not options.count: 101c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org options.size = True 102c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org return True 103c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 104c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 105c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgdef Main(): 106c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org parser = BuildOptions() 107c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org (options, args) = parser.parse_args() 108c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if not ProcessOptions(options): 109c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org parser.print_help() 110c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org sys.exit(); 1111805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 112c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org if not args: 113c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org print "Missing logfile" 114c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org sys.exit(); 1151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 116c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org ProcessLogFile(args[0], options) 117c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 118c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 119c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgif __name__ == '__main__': 120c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org sys.exit(Main()) 121