OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2015 the V8 project authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """This script is used to analyze GCTracer's NVP output.""" | 7 """This script is used to analyze GCTracer's NVP output.""" |
8 | 8 |
9 | 9 |
10 from argparse import ArgumentParser | 10 from argparse import ArgumentParser |
11 from copy import deepcopy | 11 from copy import deepcopy |
12 from gc_nvp_common import split_nvp | 12 from gc_nvp_common import split_nvp |
| 13 from math import log |
13 from sys import stdin | 14 from sys import stdin |
14 | 15 |
15 | 16 |
| 17 class 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 |
| 28 class 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 |
16 class Histogram: | 46 class Histogram: |
17 def __init__(self, granularity, fill_empty): | 47 def __init__(self, bucket_trait, fill_empty): |
18 self.granularity = granularity | |
19 self.histogram = {} | 48 self.histogram = {} |
20 self.fill_empty = fill_empty | 49 self.fill_empty = fill_empty |
| 50 self.bucket_trait = bucket_trait |
21 | 51 |
22 def add(self, key): | 52 def add(self, key): |
23 index = int(key / self.granularity) | 53 index = self.bucket_trait.value_to_bucket(key) |
24 if index not in self.histogram: | 54 if index not in self.histogram: |
25 self.histogram[index] = 0 | 55 self.histogram[index] = 0 |
26 self.histogram[index] += 1 | 56 self.histogram[index] += 1 |
27 | 57 |
28 def __str__(self): | 58 def __str__(self): |
29 ret = [] | 59 ret = [] |
30 keys = self.histogram.keys() | 60 keys = self.histogram.keys() |
31 keys.sort() | 61 keys.sort() |
32 last = -self.granularity | 62 last = keys[len(keys) - 1] |
33 for key in keys: | 63 for i in range(0, last + 1): |
34 min_value = key * self.granularity | 64 (min_value, max_value) = self.bucket_trait.bucket_to_range(i) |
35 max_value = min_value + self.granularity | 65 if i == keys[0]: |
36 | 66 keys.pop(0) |
37 if self.fill_empty: | 67 ret.append(" [{0},{1}[: {2}".format( |
38 while (last + self.granularity) != min_value: | 68 str(min_value), str(max_value), self.histogram[i])) |
39 last += self.granularity | 69 else: |
| 70 if self.fill_empty: |
40 ret.append(" [{0},{1}[: {2}".format( | 71 ret.append(" [{0},{1}[: {2}".format( |
41 str(last), str(last + self.granularity), 0)) | 72 str(min_value), str(max_value), 0)) |
42 | |
43 ret.append(" [{0},{1}[: {2}".format( | |
44 str(min_value), str(max_value), self.histogram[key])) | |
45 last = min_value | |
46 return "\n".join(ret) | 73 return "\n".join(ret) |
47 | 74 |
48 | 75 |
49 class Category: | 76 class Category: |
50 def __init__(self, key, histogram): | 77 def __init__(self, key, histogram): |
51 self.key = key | 78 self.key = key |
52 self.values = [] | 79 self.values = [] |
53 self.histogram = histogram | 80 self.histogram = histogram |
54 | 81 |
55 def process_entry(self, entry): | 82 def process_entry(self, entry): |
(...skipping 10 matching lines...) Expand all Loading... |
66 ret.append(" max: {0}".format(max(self.values))) | 93 ret.append(" max: {0}".format(max(self.values))) |
67 ret.append(" avg: {0}".format(sum(self.values) / len(self.values))) | 94 ret.append(" avg: {0}".format(sum(self.values) / len(self.values))) |
68 if self.histogram: | 95 if self.histogram: |
69 ret.append(str(self.histogram)) | 96 ret.append(str(self.histogram)) |
70 return "\n".join(ret) | 97 return "\n".join(ret) |
71 | 98 |
72 | 99 |
73 def main(): | 100 def main(): |
74 parser = ArgumentParser(description="Process GCTracer's NVP output") | 101 parser = ArgumentParser(description="Process GCTracer's NVP output") |
75 parser.add_argument('keys', metavar='KEY', type=str, nargs='+', | 102 parser.add_argument('keys', metavar='KEY', type=str, nargs='+', |
76 help='the keys (names) to process') | 103 help='the keys of NVPs to process') |
77 parser.add_argument('--histogram-granularity', metavar='GRANULARITY', | 104 parser.add_argument('--histogram-type', metavar='<linear|log2>', |
78 type=int, nargs='?', default=5, | 105 type=str, nargs='?', default="linear", |
79 help='histogram granularity (default: 5)') | 106 help='histogram type to use (default: linear)') |
80 parser.add_argument('--no-histogram-print-empty', dest='histogram_print_empty'
, | 107 linear_group = parser.add_argument_group('linear histogram specific') |
81 action='store_false', | 108 linear_group.add_argument('--linear-histogram-granularity', |
82 help='print empty histogram buckets') | 109 metavar='GRANULARITY', type=int, nargs='?', |
83 feature_parser = parser.add_mutually_exclusive_group(required=False) | 110 default=5, |
84 feature_parser.add_argument('--histogram', dest='histogram', | 111 help='histogram granularity (default: 5)') |
85 action='store_true', | 112 log2_group = parser.add_argument_group('log2 histogram specific') |
86 help='print histogram') | 113 log2_group.add_argument('--log2-histogram-init-bucket', metavar='START', |
87 feature_parser.add_argument('--no-histogram', dest='histogram', | 114 type=int, nargs='?', default=64, |
88 action='store_false', | 115 help='initial buck size (default: 64)') |
89 help='do not print histogram') | 116 parser.add_argument('--histogram-omit-empty-buckets', |
| 117 dest='histogram_omit_empty', |
| 118 action='store_true', |
| 119 help='omit empty histogram buckets') |
| 120 parser.add_argument('--no-histogram', dest='histogram', |
| 121 action='store_false', help='do not print histogram') |
90 parser.set_defaults(histogram=True) | 122 parser.set_defaults(histogram=True) |
91 parser.set_defaults(histogram_print_empty=True) | 123 parser.set_defaults(histogram_omit_empty=False) |
92 args = parser.parse_args() | 124 args = parser.parse_args() |
93 | 125 |
94 histogram = None | 126 histogram = None |
95 if args.histogram: | 127 if args.histogram: |
96 histogram = Histogram(args.histogram_granularity, args.histogram_print_empty
) | 128 bucket_trait = None |
| 129 if args.histogram_type == "log2": |
| 130 bucket_trait = Log2Bucket(args.log2_histogram_init_bucket) |
| 131 else: |
| 132 bucket_trait = LinearBucket(args.linear_histogram_granularity) |
| 133 histogram = Histogram(bucket_trait, not args.histogram_omit_empty) |
97 | 134 |
98 categories = [ Category(key, deepcopy(histogram)) | 135 categories = [ Category(key, deepcopy(histogram)) |
99 for key in args.keys ] | 136 for key in args.keys ] |
100 | 137 |
101 while True: | 138 while True: |
102 line = stdin.readline() | 139 line = stdin.readline() |
103 if not line: | 140 if not line: |
104 break | 141 break |
105 obj = split_nvp(line) | 142 obj = split_nvp(line) |
106 for category in categories: | 143 for category in categories: |
107 category.process_entry(obj) | 144 category.process_entry(obj) |
108 | 145 |
109 for category in categories: | 146 for category in categories: |
110 print(category) | 147 print(category) |
111 | 148 |
112 | 149 |
113 if __name__ == '__main__': | 150 if __name__ == '__main__': |
114 main() | 151 main() |
OLD | NEW |