#!/usr/bin/env python
#
# Copyright 2015 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This script is used to analyze GCTracer's NVP output."""


# for py2/py3 compatibility
from __future__ import print_function


from argparse import ArgumentParser
from copy import deepcopy
from gc_nvp_common import split_nvp
from math import ceil, log
from sys import stdin


class LinearBucket:
  def __init__(self, granularity):
    self.granularity = granularity

  def value_to_bucket(self, value):
    return int(value / self.granularity)

  def bucket_to_range(self, bucket):
    return (bucket * self.granularity, (bucket + 1) * self.granularity)


class Log2Bucket:
  def __init__(self, start):
    self.start = int(log(start, 2)) - 1

  def value_to_bucket(self, value):
    index = int(log(value, 2))
    index -= self.start
    if index < 0:
      index = 0
    return index

  def bucket_to_range(self, bucket):
    if bucket == 0:
      return (0, 2 ** (self.start + 1))
    bucket += self.start
    return (2 ** bucket, 2 ** (bucket + 1))


class Histogram:
  def __init__(self, bucket_trait, fill_empty):
    self.histogram = {}
    self.fill_empty = fill_empty
    self.bucket_trait = bucket_trait

  def add(self, key):
    index = self.bucket_trait.value_to_bucket(key)
    if index not in self.histogram:
      self.histogram[index] = 0
    self.histogram[index] += 1

  def __str__(self):
    ret = []
    keys = self.histogram.keys()
    keys.sort()
    last = keys[len(keys) - 1]
    for i in range(0, last + 1):
      (min_value, max_value) = self.bucket_trait.bucket_to_range(i)
      if i == keys[0]:
        keys.pop(0)
        ret.append("  [{0},{1}[: {2}".format(
          str(min_value), str(max_value), self.histogram[i]))
      else:
        if self.fill_empty:
          ret.append("  [{0},{1}[: {2}".format(
            str(min_value), str(max_value), 0))
    return "\n".join(ret)


class Category:
  def __init__(self, key, histogram, csv, percentiles):
    self.key = key
    self.values = []
    self.histogram = histogram
    self.csv = csv
    self.percentiles = percentiles

  def process_entry(self, entry):
    if self.key in entry:
      self.values.append(float(entry[self.key]))
      if self.histogram:
        self.histogram.add(float(entry[self.key]))

  def min(self):
    return min(self.values)

  def max(self):
    return max(self.values)

  def avg(self):
    if len(self.values) == 0:
      return 0.0
    return sum(self.values) / len(self.values)

  def empty(self):
    return len(self.values) == 0

  def _compute_percentiles(self):
    ret = []
    if len(self.values) == 0:
      return ret
    sorted_values = sorted(self.values)
    for percentile in self.percentiles:
      index = int(ceil((len(self.values) - 1) * percentile / 100))
      ret.append("  {0}%: {1}".format(percentile, sorted_values[index]))
    return ret

  def __str__(self):
    if self.csv:
      ret = [self.key]
      ret.append(len(self.values))
      ret.append(self.min())
      ret.append(self.max())
      ret.append(self.avg())
      ret = [str(x) for x in ret]
      return ",".join(ret)
    else:
      ret = [self.key]
      ret.append("  len: {0}".format(len(self.values)))
      if len(self.values) > 0:
        ret.append("  min: {0}".format(self.min()))
        ret.append("  max: {0}".format(self.max()))
        ret.append("  avg: {0}".format(self.avg()))
        if self.histogram:
          ret.append(str(self.histogram))
        if self.percentiles:
          ret.append("\n".join(self._compute_percentiles()))
      return "\n".join(ret)

  def __repr__(self):
    return "<Category: {0}>".format(self.key)


def make_key_func(cmp_metric):
  def key_func(a):
    return getattr(a, cmp_metric)()
  return key_func


def main():
  parser = ArgumentParser(description="Process GCTracer's NVP output")
  parser.add_argument('keys', metavar='KEY', type=str, nargs='+',
                      help='the keys of NVPs to process')
  parser.add_argument('--histogram-type', metavar='<linear|log2>',
                      type=str, nargs='?', default="linear",
                      help='histogram type to use (default: linear)')
  linear_group = parser.add_argument_group('linear histogram specific')
  linear_group.add_argument('--linear-histogram-granularity',
                            metavar='GRANULARITY', type=int, nargs='?',
                            default=5,
                            help='histogram granularity (default: 5)')
  log2_group = parser.add_argument_group('log2 histogram specific')
  log2_group.add_argument('--log2-histogram-init-bucket', metavar='START',
                          type=int, nargs='?', default=64,
                          help='initial buck size (default: 64)')
  parser.add_argument('--histogram-omit-empty-buckets',
                      dest='histogram_omit_empty',
                      action='store_true',
                      help='omit empty histogram buckets')
  parser.add_argument('--no-histogram', dest='histogram',
                      action='store_false', help='do not print histogram')
  parser.set_defaults(histogram=True)
  parser.set_defaults(histogram_omit_empty=False)
  parser.add_argument('--rank', metavar='<no|min|max|avg>',
                      type=str, nargs='?',
                      default="no",
                      help="rank keys by metric (default: no)")
  parser.add_argument('--csv', dest='csv',
                      action='store_true', help='provide output as csv')
  parser.add_argument('--percentiles', dest='percentiles',
                      type=str, default="",
                      help='comma separated list of percentiles')
  args = parser.parse_args()

  histogram = None
  if args.histogram:
    bucket_trait = None
    if args.histogram_type == "log2":
      bucket_trait = Log2Bucket(args.log2_histogram_init_bucket)
    else:
      bucket_trait = LinearBucket(args.linear_histogram_granularity)
    histogram = Histogram(bucket_trait, not args.histogram_omit_empty)

  percentiles = []
  for percentile in args.percentiles.split(','):
    try:
      percentiles.append(float(percentile))
    except ValueError:
      pass

  categories = [ Category(key, deepcopy(histogram), args.csv, percentiles)
                 for key in args.keys ]

  while True:
    line = stdin.readline()
    if not line:
      break
    obj = split_nvp(line)
    for category in categories:
      category.process_entry(obj)

  # Filter out empty categories.
  categories = [x for x in categories if not x.empty()]

  if args.rank != "no":
    categories = sorted(categories, key=make_key_func(args.rank), reverse=True)

  for category in categories:
    print(category)


if __name__ == '__main__':
  main()
