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