#!/usr/bin/env python3
# Copyright 2017 The PDFium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Measures performance for rendering a single test case with pdfium.

The output is a number that is a metric which depends on the profiler specified.
"""

import argparse
import os
import re
import subprocess
import sys

from common import PrintErr

CALLGRIND_PROFILER = 'callgrind'
PERFSTAT_PROFILER = 'perfstat'
NONE_PROFILER = 'none'

PDFIUM_TEST = 'pdfium_test'


class PerformanceRun:
  """A single measurement of a test case."""

  def __init__(self, args):
    self.args = args
    self.pdfium_test_path = os.path.join(self.args.build_dir, PDFIUM_TEST)

  def _CheckTools(self):
    """Returns whether the tool file paths are sane."""
    if not os.path.exists(self.pdfium_test_path):
      PrintErr(
          "FAILURE: Can't find test executable '%s'" % self.pdfium_test_path)
      PrintErr('Use --build-dir to specify its location.')
      return False
    if not os.access(self.pdfium_test_path, os.X_OK):
      PrintErr("FAILURE: Test executable '%s' lacks execution permissions" %
               self.pdfium_test_path)
      return False
    return True

  def Run(self):
    """Runs test harness and measures performance with the given profiler.

    Returns:
      Exit code for the script.
    """
    if not self._CheckTools():
      return 1

    if self.args.profiler == CALLGRIND_PROFILER:
      time = self._RunCallgrind()
    elif self.args.profiler == PERFSTAT_PROFILER:
      time = self._RunPerfStat()
    elif self.args.profiler == NONE_PROFILER:
      time = self._RunWithoutProfiler()
    else:
      PrintErr('profiler=%s not supported, aborting' % self.args.profiler)
      return 1

    if time is None:
      return 1

    print(time)
    return 0

  def _RunCallgrind(self):
    """Runs test harness and measures performance with callgrind.

    Returns:
      int with the result of the measurement, in instructions or time.
    """
    # Whether to turn instrument the whole run or to use the callgrind macro
    # delimiters in pdfium_test.
    instrument_at_start = 'no' if self.args.interesting_section else 'yes'
    output_path = self.args.output_path or '/dev/null'

    valgrind_cmd = ([
        'valgrind', '--tool=callgrind',
        '--instr-atstart=%s' % instrument_at_start,
        '--callgrind-out-file=%s' % output_path
    ] + self._BuildTestHarnessCommand())
    output = subprocess.check_output(
        valgrind_cmd, stderr=subprocess.STDOUT).decode('utf-8')

    # Match the line with the instruction count, eg.
    # '==98765== Collected : 12345'
    return self._ExtractIrCount(r'\bCollected\b *: *\b(\d+)', output)

  def _RunPerfStat(self):
    """Runs test harness and measures performance with perf stat.

    Returns:
      int with the result of the measurement, in instructions or time.
    """
    # --no-big-num: do not add thousands separators
    # -einstructions: print only instruction count
    cmd_to_run = (['perf', 'stat', '--no-big-num', '-einstructions'] +
                  self._BuildTestHarnessCommand())
    output = subprocess.check_output(
        cmd_to_run, stderr=subprocess.STDOUT).decode('utf-8')

    # Match the line with the instruction count, eg.
    # '        12345      instructions'
    return self._ExtractIrCount(r'\b(\d+)\b.*\binstructions\b', output)

  def _RunWithoutProfiler(self):
    """Runs test harness and measures performance without a profiler.

    Returns:
      int with the result of the measurement, in instructions or time. In this
      case, always return 1 since no profiler is being used.
    """
    cmd_to_run = self._BuildTestHarnessCommand()
    subprocess.check_output(cmd_to_run, stderr=subprocess.STDOUT)

    # Return 1 for every run.
    return 1

  def _BuildTestHarnessCommand(self):
    """Builds command to run the test harness."""
    cmd = [self.pdfium_test_path, '--send-events']

    if self.args.interesting_section:
      cmd.append('--callgrind-delim')
    if self.args.png:
      cmd.append('--png')
    if self.args.pages:
      cmd.append('--pages=%s' % self.args.pages)

    cmd.append(self.args.pdf_path)
    return cmd

  def _ExtractIrCount(self, regex, output):
    """Extracts a number from the output with a regex."""
    matched = re.search(regex, output)

    if not matched:
      return None

    # Group 1 is the instruction number, eg. 12345
    return int(matched.group(1))


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      'pdf_path', help='test case to measure load and rendering time')
  parser.add_argument(
      '--build-dir',
      default=os.path.join('out', 'Release'),
      help='relative path to the build directory with '
      '%s' % PDFIUM_TEST)
  parser.add_argument(
      '--profiler',
      default=CALLGRIND_PROFILER,
      help='which profiler to use. Supports callgrind, '
      'perfstat, and none.')
  parser.add_argument(
      '--interesting-section',
      action='store_true',
      help='whether to measure just the interesting section or '
      'the whole test harness. The interesting section is '
      'pdfium reading a pdf from memory and rendering '
      'it, which omits loading the time to load the file, '
      'initialize the library, terminate it, etc. '
      'Limiting to only the interesting section does not '
      'work on Release since the delimiters are optimized '
      'out. Callgrind only.')
  parser.add_argument(
      '--png',
      action='store_true',
      help='outputs a png image on the same location as the '
      'pdf file')
  parser.add_argument(
      '--pages',
      help='selects some pages to be rendered. Page numbers '
      'are 0-based. "--pages A" will render only page A. '
      '"--pages A-B" will render pages A to B '
      '(inclusive).')
  parser.add_argument(
      '--output-path', help='where to write the profile data output file')
  args = parser.parse_args()

  if args.interesting_section and args.profiler != CALLGRIND_PROFILER:
    PrintErr('--interesting-section requires profiler to be callgrind.')
    return 1

  run = PerformanceRun(args)
  return run.Run()


if __name__ == '__main__':
  sys.exit(main())
