def cmdline_chart_compare()

in tools/dev/benchmarks/suite1/benchmark.py [0:0]


def cmdline_chart_compare(db, options, *args):
  import matplotlib
  matplotlib.use('Agg')
  import numpy as np
  import matplotlib.pylab as plt

  labels = []
  timing_sets = []
  command_names = None

  run_kinds = parse_timings_selections(db, *args)

  # iterate the timings selections and accumulate data
  for run_kind in run_kinds:
    query = TimingQuery(db, run_kind)
    timings = query.get_timings()
    if not timings:
      print("No timings for %s" % run_kind.label())
      continue
    labels.append(run_kind.label())
    timing_sets.append(timings)

    # it only makes sense to compare those commands that have timings
    # in the first selection, because that is the one everything else
    # is compared to. Remember the first selection's command names.
    if not command_names:
      command_names = query.get_sorted_command_names()


  if len(timing_sets) < 2:
    bail("Not enough timings")

  if options.command_names:
    command_names = [name for name in command_names
                     if name in options.command_names]

  chart_path = options.chart_path
  if not chart_path:
    chart_path = 'compare_' + '_'.join(
      [ filesystem_safe_string(l) for l in labels ]
      ) + '.svg'

  N = len(command_names)
  M = len(timing_sets) - 1
  if M < 2:
    M = 2

  group_positions = np.arange(N)  # the y locations for the groups
  dist = 1. / (1. + M)
  height = (1. - dist) / M     # the height of the bars

  fig = plt.figure(figsize=(12, 5 + 0.2*N*M))
  plot1 = fig.add_subplot(121)
  plot2 = fig.add_subplot(122)

  left = timing_sets[0]

  # Iterate timing sets. Each loop produces one bar for each command name
  # group.
  for label_i,label in enumerate(labels[1:],1):
    right = timing_sets[label_i]
    if not right:
      continue

    for cmd_i, command_name in enumerate(command_names):
      if command_name not in right:
        #skip
        continue

      left_N, left_min, left_max, left_avg = left[command_name]
      right_N, right_min, right_max, right_avg = right[command_name]

      div_avg = 100. * (do_div(left_avg, right_avg) - 1.0)
      if div_avg <= 0:
        col = '#55dd55'
      else:
        col = '#dd5555'

      diff_val = do_diff(left_avg, right_avg)

      ofs = (dist + height) / 2. + height * (label_i - 1)

      barheight = height * (1.0 - dist)

      y = float(cmd_i) + ofs

      plot1.barh((y, ),
                 (div_avg, ),
                 barheight,
                 color=col, edgecolor='white')
      plot1.text(0., y + height/2.,
                 '%s %+5.1f%%' % (label, div_avg),
                 ha='right', va='center', size='small',
                 rotation=0, family='monospace')

      plot2.barh((y, ),
                 (diff_val, ),
                 barheight,
                 color=col, edgecolor='white')
      plot2.text(0., y + height/2.,
                 '%s %+6.2fs' % (label, diff_val),
                 ha='right', va='center', size='small',
                 rotation=0, family='monospace')


  for p in (plot1, plot2):
    xlim = list(p.get_xlim())
    if xlim[1] < 10.:
      xlim[1] = 10.
    # make sure the zero line is far enough right so that the annotations
    # fit inside the chart. About half the width should suffice.
    if xlim[0] > -xlim[1]:
      xlim[0] = -xlim[1]
    p.set_xlim(*xlim)
    p.set_xticks((0,))
    p.set_yticks(group_positions + (height / 2.))
    p.set_yticklabels(())
    p.set_ylim((len(command_names), 0))
    p.grid()

  plot1.set_xticklabels(('+-0%',), rotation=0)
  plot1.set_title('Average runtime change from %s in %%' % labels[0],
                  size='medium')

  plot2.set_xticklabels(('+-0s',), rotation=0)
  plot2.set_title('Average runtime change from %s in seconds' % labels[0],
                  size='medium')

  margin = 1./(2 + N*M)
  titlemargin = 0
  if options.title:
    titlemargin = margin * 1.5

  fig.subplots_adjust(left=0.005, right=0.995, wspace=0.3, bottom=margin,
                      top=1.0-margin-titlemargin)

  ystep = (1.0 - 2.*margin - titlemargin) / len(command_names)

  for idx,command_name in enumerate(command_names):
    ylabel = '%s\nvs. %.1fs' % (
                     command_name,
                     left[command_name][3])

    ypos=1.0 - margin - titlemargin - ystep/M - ystep * idx
    plt.figtext(0.5, ypos,
                command_name,
                ha='center', va='top',
                size='medium', weight='bold')
    plt.figtext(0.5, ypos - ystep/(M+1),
                '%s\n= %.2fs' % (
                  labels[0], left[command_name][3]),
                ha='center', va='top',
                size='small')

  if options.title:
    plt.figtext(0.5, 1. - titlemargin/2, options.title, ha='center',
                va='center', weight='bold')

  plt.savefig(chart_path)
  print('wrote chart file:', chart_path)