blob: fcb6d8b9a2232ff24b04709d9520df0bd0b61755 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001#!/usr/bin/env python
2#
3# Copyright 2015 the V8 project authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""This script is used to analyze GCTracer's NVP output."""
8
9
10from argparse import ArgumentParser
11from copy import deepcopy
12from gc_nvp_common import split_nvp
13from math import log
14from sys import stdin
15
16
17class LinearBucket:
18 def __init__(self, granularity):
19 self.granularity = granularity
20
21 def value_to_bucket(self, value):
22 return int(value / self.granularity)
23
24 def bucket_to_range(self, bucket):
25 return (bucket * self.granularity, (bucket + 1) * self.granularity)
26
27
28class Log2Bucket:
29 def __init__(self, start):
30 self.start = int(log(start, 2)) - 1
31
32 def value_to_bucket(self, value):
33 index = int(log(value, 2))
34 index -= self.start
35 if index < 0:
36 index = 0
37 return index
38
39 def bucket_to_range(self, bucket):
40 if bucket == 0:
41 return (0, 2 ** (self.start + 1))
42 bucket += self.start
43 return (2 ** bucket, 2 ** (bucket + 1))
44
45
46class Histogram:
47 def __init__(self, bucket_trait, fill_empty):
48 self.histogram = {}
49 self.fill_empty = fill_empty
50 self.bucket_trait = bucket_trait
51
52 def add(self, key):
53 index = self.bucket_trait.value_to_bucket(key)
54 if index not in self.histogram:
55 self.histogram[index] = 0
56 self.histogram[index] += 1
57
58 def __str__(self):
59 ret = []
60 keys = self.histogram.keys()
61 keys.sort()
62 last = keys[len(keys) - 1]
63 for i in range(0, last + 1):
64 (min_value, max_value) = self.bucket_trait.bucket_to_range(i)
65 if i == keys[0]:
66 keys.pop(0)
67 ret.append(" [{0},{1}[: {2}".format(
68 str(min_value), str(max_value), self.histogram[i]))
69 else:
70 if self.fill_empty:
71 ret.append(" [{0},{1}[: {2}".format(
72 str(min_value), str(max_value), 0))
73 return "\n".join(ret)
74
75
76class Category:
Ben Murdochda12d292016-06-02 14:46:10 +010077 def __init__(self, key, histogram, csv):
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 self.key = key
79 self.values = []
80 self.histogram = histogram
Ben Murdochda12d292016-06-02 14:46:10 +010081 self.csv = csv
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082
83 def process_entry(self, entry):
84 if self.key in entry:
85 self.values.append(float(entry[self.key]))
86 if self.histogram:
87 self.histogram.add(float(entry[self.key]))
88
89 def min(self):
90 return min(self.values)
91
92 def max(self):
93 return max(self.values)
94
95 def avg(self):
Ben Murdochda12d292016-06-02 14:46:10 +010096 if len(self.values) == 0:
97 return 0.0
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 return sum(self.values) / len(self.values)
99
Ben Murdochda12d292016-06-02 14:46:10 +0100100 def empty(self):
101 return len(self.values) == 0
102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 def __str__(self):
Ben Murdochda12d292016-06-02 14:46:10 +0100104 if self.csv:
105 ret = [self.key]
106 ret.append(len(self.values))
107 ret.append(self.min())
108 ret.append(self.max())
109 ret.append(self.avg())
110 ret = [str(x) for x in ret]
111 return ",".join(ret)
112 else:
113 ret = [self.key]
114 ret.append(" len: {0}".format(len(self.values)))
115 if len(self.values) > 0:
116 ret.append(" min: {0}".format(self.min()))
117 ret.append(" max: {0}".format(self.max()))
118 ret.append(" avg: {0}".format(self.avg()))
119 if self.histogram:
120 ret.append(str(self.histogram))
121 return "\n".join(ret)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122
123 def __repr__(self):
124 return "<Category: {0}>".format(self.key)
125
126
127def make_key_func(cmp_metric):
128 def key_func(a):
129 return getattr(a, cmp_metric)()
130 return key_func
131
132
133def main():
134 parser = ArgumentParser(description="Process GCTracer's NVP output")
135 parser.add_argument('keys', metavar='KEY', type=str, nargs='+',
136 help='the keys of NVPs to process')
137 parser.add_argument('--histogram-type', metavar='<linear|log2>',
138 type=str, nargs='?', default="linear",
139 help='histogram type to use (default: linear)')
140 linear_group = parser.add_argument_group('linear histogram specific')
141 linear_group.add_argument('--linear-histogram-granularity',
142 metavar='GRANULARITY', type=int, nargs='?',
143 default=5,
144 help='histogram granularity (default: 5)')
145 log2_group = parser.add_argument_group('log2 histogram specific')
146 log2_group.add_argument('--log2-histogram-init-bucket', metavar='START',
147 type=int, nargs='?', default=64,
148 help='initial buck size (default: 64)')
149 parser.add_argument('--histogram-omit-empty-buckets',
150 dest='histogram_omit_empty',
151 action='store_true',
152 help='omit empty histogram buckets')
153 parser.add_argument('--no-histogram', dest='histogram',
154 action='store_false', help='do not print histogram')
155 parser.set_defaults(histogram=True)
156 parser.set_defaults(histogram_omit_empty=False)
157 parser.add_argument('--rank', metavar='<no|min|max|avg>',
158 type=str, nargs='?',
159 default="no",
160 help="rank keys by metric (default: no)")
Ben Murdochda12d292016-06-02 14:46:10 +0100161 parser.add_argument('--csv', dest='csv',
162 action='store_true', help='provide output as csv')
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 args = parser.parse_args()
164
165 histogram = None
166 if args.histogram:
167 bucket_trait = None
168 if args.histogram_type == "log2":
169 bucket_trait = Log2Bucket(args.log2_histogram_init_bucket)
170 else:
171 bucket_trait = LinearBucket(args.linear_histogram_granularity)
172 histogram = Histogram(bucket_trait, not args.histogram_omit_empty)
173
Ben Murdochda12d292016-06-02 14:46:10 +0100174 categories = [ Category(key, deepcopy(histogram), args.csv)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 for key in args.keys ]
176
177 while True:
178 line = stdin.readline()
179 if not line:
180 break
181 obj = split_nvp(line)
182 for category in categories:
183 category.process_entry(obj)
184
Ben Murdochda12d292016-06-02 14:46:10 +0100185 # Filter out empty categories.
186 categories = [x for x in categories if not x.empty()]
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 if args.rank != "no":
189 categories = sorted(categories, key=make_key_func(args.rank), reverse=True)
190
191 for category in categories:
192 print(category)
193
194
195if __name__ == '__main__':
196 main()