| 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 |