code: def gridsearch_timer(func_list, args_list, niters=None, **searchkw):
      import utool as ut
      timings = ut.ddict(list)
      if niters is None:
          niters = len(args_list)
      if ut.is_funclike(args_list):
          get_args = args_list
      else:
          get_args = args_list.__getitem__
      func_labels = searchkw.get('func_labels', [ut.get_funcname(func) for func in func_list])
      use_cache = searchkw.get('use_cache', not ut.get_argflag(('--nocache', '--nocache-time')))
      assert_eq = searchkw.get('assert_eq', True)
      count_list = list(range(niters))
      xlabel_list = []
      cache = ut.ShelfCacher('timeings.shelf', enabled=use_cache)
      for count in ut.ProgressIter(count_list, lbl='Testing Timeings'):
          args_ = get_args(count)
          xlabel_list.append(args_)
          if True:
              if not isinstance(args_, tuple):
                  args_ = (args_,)
          assert isinstance(args_, tuple), 'args_ should be a tuple so it can be unpacked'
          ret_list = []
          for func_ in func_list:
              try:
                  kwargs_ = {}
                  func_cachekey = ut.get_func_result_cachekey(func_, args_, kwargs_)
                  ellapsed = cache.load(func_cachekey)
              except ut.CacheMissException:
                  with ut.Timer(verbose=False) as t:
                      ret = func_(*args_)
                      ret_list.append(ret)
                  ellapsed = t.ellapsed
                  cache.save(func_cachekey, ellapsed)
              timings[func_].append(ellapsed)
          if assert_eq:
              ut.assert_all_eq(list(map(ut.cachestr_repr, ret_list)))
      cache.close()
      count_to_xtick = searchkw.get('count_to_xtick', lambda x, y: x)
      xtick_list = [count_to_xtick(count, get_args(count)) for count in count_list]
      def plot_timings():
          import plottool as pt
          ydata_list = ut.dict_take(timings, func_list)
          xdata = xtick_list
          ylabel = 'seconds'
          xlabel = 'input size'
          pt.multi_plot(
              xdata, ydata_list, label_list=func_labels,
              ylabel=ylabel, xlabel=xlabel,
              **searchkw
          )
      time_result = {
          'plot_timings': plot_timings,
          'timings': timings,
      }
      return time_result