#!/usr/bin/python
#
# Copyright 2011 Google Inc. All Rights Reserved.

"""Summarize hottest basic blocks found while doing a ChromeOS FDO build.

Here is an example execution:

  summarize_hot_blocks.py
   --data_dir=~/chromeos/chroot/var/cache/chromeos-chrome/ --cutoff=10000
   --output_dir=/home/x/y

With the cutoff, it will ignore any basic blocks that have a count less
than what is specified (in this example 10000)
The script looks inside the directory (this is typically a directory where
the object files are generated) for files with *.profile and *.optimized
suffixes. To get these, the following flags were added to the compiler
invokation within vanilla_vs_fdo.py in the profile-use phase.

              "-fdump-tree-optimized-blocks-lineno "
              "-fdump-ipa-profile-blocks-lineno "

Here is an example of the *.profile and *.optimized files contents:

# BLOCK 7 freq:3901 count:60342, starting at line 92
# PRED: 6 [39.0%]  count:60342 (true,exec)
  [url_canon_internal.cc : 92:28] MEM[(const char * *)source_6(D) + 16B] = D.28080_17;
  [url_canon_internal.cc : 93:41] MEM[(struct Component *)parsed_4(D) + 16B] = MEM[(const struct Component &)repl_1(D) + 80];
# SUCC: 8 [100.0%]  count:60342 (fallthru,exec)
# BLOCK 8 freq:10000 count:154667, starting at line 321
# PRED: 7 [100.0%]  count:60342 (fallthru,exec) 6 [61.0%]  count:94325 (false,exec)
  [url_canon_internal.cc : 321:51] # DEBUG D#10 => [googleurl/src/url_canon_internal.cc : 321] &parsed_4(D)->host

this script finds the blocks with highest count and shows the first line
of each block so that it is easy to identify the origin of the basic block.

"""

__author__ = "llozano@google.com (Luis Lozano)"

import optparse
import os
import re
import shutil
import sys
import tempfile

from utils import command_executer


# Given a line, check if it has a block count and return it.
# Return -1 if there is no match
def GetBlockCount(line):
  match_obj = re.match(".*# BLOCK \d+ .*count:(\d+)", line)
  if match_obj:
    return int(match_obj.group(1))
  else:
    return -1


class Collector(object):
  def __init__(self, data_dir, cutoff, output_dir, tempdir):
    self._data_dir = data_dir
    self._cutoff = cutoff
    self._output_dir = output_dir
    self._tempdir = tempdir
    self._ce = command_executer.GetCommandExecuter()

  def CollectFileList(self, file_exp, list_file):
    command = ("find %s -type f -name '%s' > %s" %
               (self._data_dir, file_exp,
                os.path.join(self._tempdir, list_file)))
    ret = self._ce.RunCommand(command)
    if ret:
      raise Exception("Failed: %s" % command)

  def SummarizeLines(self, data_file):
    sum_lines = []
    search_lno = False
    for line in data_file:
      count = GetBlockCount(line)
      if count != -1:
        if count >= self._cutoff:
          search_lno = True
          sum_line = line.strip()
          sum_count = count
      # look for a line that starts with line number information
      elif search_lno and re.match("^\s*\[.*: \d*:\d*]", line):
        search_lno = False
        sum_lines.append("%d:%s: %s %s" %
                         (sum_count, data_file.name, sum_line, line))
    return sum_lines

  # Look for blocks in the data file that have a count larger than the cutoff
  # and generate a sorted summary file of the hottest blocks.
  def SummarizeFile(self, data_file, sum_file):
    with open(data_file, "r") as f:
      sum_lines = self.SummarizeLines(f)

    # sort reverse the list in place by the block count number
    sum_lines.sort(key=GetBlockCount, reverse=True)

    with open(sum_file, "w") as sf:
      sf.write("".join(sum_lines))

    print "Generated file Summary: ", sum_file

  # Find hottest blocks in the list of files, generate a sorted summary for
  # each file and then do a sorted merge of all the summaries.
  def SummarizeList(self, list_file, summary_file):
    with open(os.path.join(self._tempdir, list_file)) as f:
      sort_list = []
      for file_name in f:
        file_name = file_name.strip()
        sum_file = "%s.sum" % file_name
        sort_list.append("%s%s" % (sum_file, chr(0)))
        self.SummarizeFile(file_name, sum_file)

    tmp_list_file = os.path.join(self._tempdir, "file_list.dat")
    with open(tmp_list_file, "w") as file_list_file:
      for x in sort_list:
        file_list_file.write(x)

    merge_command = ("sort -nr -t: -k1 --merge --files0-from=%s > %s " %
                     (tmp_list_file, summary_file))

    ret = self._ce.RunCommand(merge_command)
    if ret:
      raise Exception("Failed: %s" % merge_command)
    print "Generated general summary: ", summary_file

  def SummarizePreOptimized(self, summary_file):
    self.CollectFileList("*.profile", "chrome.profile.list")
    self.SummarizeList("chrome.profile.list",
                       os.path.join(self._output_dir, summary_file))

  def SummarizeOptimized(self, summary_file):
    self.CollectFileList("*.optimized", "chrome.optimized.list")
    self.SummarizeList("chrome.optimized.list",
                       os.path.join(self._output_dir, summary_file))


def Main(argv):
  command_executer.InitCommandExecuter()
  usage = ("usage: %prog --data_dir=<dir> --cutoff=<value> "
           "--output_dir=<dir> [--keep_tmp]")
  parser = optparse.OptionParser(usage=usage)
  parser.add_option("--data_dir",
                    dest="data_dir",
                    help=("directory where the FDO (*.profile and "
                          "*.optimized) files are located"))
  parser.add_option("--cutoff",
                    dest="cutoff",
                    help="Minimum count to consider for each basic block")
  parser.add_option("--output_dir",
                    dest="output_dir",
                    help=("directory where summary data will be generated"
                          "(pre_optimized.txt, optimized.txt)"))
  parser.add_option("--keep_tmp",
                    action="store_true",
                    dest="keep_tmp",
                    default=False,
                    help=("Keep directory with temporary files"
                          "(for debugging purposes)"))
  options = parser.parse_args(argv)[0]
  if not all((options.data_dir, options.cutoff, options.output_dir)):
    parser.print_help()
    sys.exit(1)

  tempdir = tempfile.mkdtemp()

  co = Collector(options.data_dir, int(options.cutoff), options.output_dir,
                 tempdir)
  co.SummarizePreOptimized("pre_optimized.txt")
  co.SummarizeOptimized("optimized.txt")

  if not options.keep_tmp:
    shutil.rmtree(tempdir, ignore_errors=True)

  return 0

if __name__ == "__main__":
  retval = Main(sys.argv)
  sys.exit(retval)
