Example #1
0
def percentiles_by_stencil(results, percentiles):
    """Computes given percentiles of measured run times of multiple results
       and sorts them by stencil.

    Args:
        results: List of `Result` objects.
        percentils: List of percentiles, each percentile must be in the range
                    [0, 100] (inclusive).

    Returns:
        A tuple of lists (stencils, percentiles 1, percentiles 2, ...). The
        number of returned values depends on the number of input percentiles.
    """
    stencils = results[0].stencils
    if any(stencils != r.stencils for r in results):
        raise ArgumentError('All results must include the same stencils')

    qtimes = []
    for q in percentiles:

        def compute_q(times):
            return np.percentile(times, q)

        qtimes.append(by_stencils(r.mapped_times(compute_q) for r in results))

    return (stencils, *qtimes)
Example #2
0
 def get_datetime(result):
     if key == 'runtime':
         datetime = result.runtime.datetime
     elif key == 'job':
         datetime = result.datetime
     else:
         raise ArgumentError('"key" argument must be "runtime" or "job"')
     return time.local_time(datetime)
Example #3
0
def times_by_stencil(results):
    """Collects times of multiple results by stencils.

    Args:
        results: List of `Result` objects.

    Returns:
        A tuple of lists (stencils, times).
    """
    stencils = results[0].stencils
    if any(stencils != r.stencils for r in results):
        raise ArgumentError('All results must include the same stencils')

    times = by_stencils(r.times_by_stencil() for r in results)
    return stencils, times
Example #4
0
def from_timestr(timestr):
    """Converts a time string back to a `datetime.datetime` object.

    The given string must be in the format as generated by the `timestr`
    function.

    Args:
        timestr: A string representing a time in the supported format.

    Returns:
        A `datetime.datetime` object, representing the same time as `timestr`.
    """
    try:
        return datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%S.%f%z')
    except ValueError:
        raise ArgumentError(f'"{timestr}" is an invalid time string') from None
Example #5
0
def statistics_by_stencil(results):
    """Computes mean and stdev times of multiple results by stencil.

    Args:
        results: List of `Result` objects.

    Returns:
        A tuple of lists (stencils, meantimes, stdevtimes).
    """
    stencils = results[0].stencils
    if any(stencils != r.stencils for r in results):
        raise ArgumentError('All results must include the same stencils')

    meantimes = by_stencils(r.mapped_times(np.mean) for r in results)
    stdevtimes = by_stencils(r.mapped_times(np.std) for r in results)
    return stencils, meantimes, stdevtimes
Example #6
0
def timestr(time):
    """Returns the given time as a string.

    Args:
        time: The time that should be converted to a string.

    Returns:
        A string representing `time`, compatible to ISO 8601 time format.
    """
    try:
        dt_format = ('%Y-%m-%dT%H:%M:%S.%f%z', '%a %b %d %H:%M:&S %Z %Y', '%Y-%m-%d %H;%M')
        for current_format in dt_format:
            try:
                return time.strftime(timestr, current_format)
            except ValueError:
                pass
    except ValueError:
        raise ArgumentError(f'"{timestr}" is an invalid time string') from None
Example #7
0
def history(results, key='job', limit=None):
    """Plots run time history of all results. Depending on the argument `job`,
       The results are either ordered by runtime (i.e. commit/build time) or
       job time (i.e. when the job was run).

    Args:
        results: List of `result.Result` objects.
        key: Either 'job' or 'runtime'.
        limit: Optionally limits the number of plotted results to the given
               number, i.e. only displays the most recent results. If `None`,
               all given results are plotted.
    """

    # get date/time either from the runtime (commit/build) or job (when job
    # was run)
    def get_datetime(result):
        if key == 'runtime':
            datetime = result.runtime.datetime
        elif key == 'job':
            datetime = result.datetime
        else:
            raise ArgumentError('"key" argument must be "runtime" or "job"')
        return time.local_time(datetime)

    # sort results by desired reference time
    results = sorted(results, key=get_datetime)

    if limit is not None:
        if not isinstance(limit, int) or limit <= 0:
            raise ArgumentError('"limit" must be a positive integer')
        results = results[-limit:]

    data = result.percentiles_by_stencil(results, [0, 25, 50, 75, 100])
    dates = [matplotlib.dates.date2num(get_datetime(r)) for r in results]

    if len(dates) > len(set(dates)):
        logger.warning('Non-unique datetimes in history plot')

    locator = matplotlib.dates.AutoDateLocator()
    formatter = matplotlib.dates.AutoDateFormatter(locator)
    formatter.scaled[1 / 24] = '%y-%m-%d %H:%M'
    formatter.scaled[1 / (24 * 60)] = '%y-%m-%d %H:%M'
    formatter.scaled[1 / (24 * 60 * 60)] = '%y-%m-%d %H:%M:%S'

    if len(data[0]) < 8:
        q2, stencil, mint, q1, q3, maxt = zip(*sorted(zip(data[3], data[0], data[1], data[2], data[4], data[5])))
        colors = discrete_colors(len(stencil[0]))
        fig, ax = plt.subplots(1, 1, figsize=figsize(4, 2))

        for color, stencil, mint, q1, q2, q3, maxt in zip(colors, stencil, mint, q1, q2, q3, maxt):
            ax.fill_between(dates, mint, maxt, alpha=0.2, color=color)
            ax.fill_between(dates, q1, q3, alpha=0.5, color=color)
            ax.plot(dates, q2, '|-', label=stencil.title(), color=color)

        ax.legend(loc='upper left')

        ax.xaxis.set_major_locator(locator)
        ax.xaxis.set_major_formatter(formatter)

        fig.autofmt_xdate()
        fig.tight_layout()

    elif len(data[0]) < 20:
        # Sort by mean time
        three, zero, one, two, four, five = zip(*sorted(zip(data[3], data[0], data[1], data[2], data[4], data[5])))
        stencils = numpy.array_split(numpy.array(zero), 4)
        mints = numpy.array_split(numpy.array(one), 4)
        q1s = numpy.array_split(numpy.array(two), 4)
        q2s = numpy.array_split(numpy.array(three), 4)
        q3s = numpy.array_split(numpy.array(four), 4)
        maxts = numpy.array_split(numpy.array(five), 4)

        colors = discrete_colors(len(stencils[0]))

        fig, ax = plt.subplots(2, 2, figsize=figsize(4, 2))

        axes = itertools.chain(*ax)
        for cstencil, cmint, cq1, cq2, cq3, cmaxt, ax in zip(stencils, mints, q1s, q2s, q3s, maxts, axes):

            for color, stencil, mint, q1, q2, q3, maxt in zip(colors, cstencil, cmint, cq1, cq2, cq3, cmaxt):
                ax.fill_between(dates, mint, maxt, alpha=0.2, color=color)
                ax.fill_between(dates, q1, q3, alpha=0.5, color=color)
                ax.plot(dates, q2, '|-', label=stencil.title(), color=color)

            ax.legend(loc='upper left')

            ax.xaxis.set_major_locator(locator)
            ax.xaxis.set_major_formatter(formatter)

        fig.autofmt_xdate()
        fig.tight_layout()

    else:
        # Sort by mean time
        three, zero, one, two, four, five = zip(*sorted(zip(data[3], data[0], data[1], data[2], data[4], data[5])))
        stencils = numpy.array_split(numpy.array(zero), 6)
        mints = numpy.array_split(numpy.array(one), 6)
        q1s = numpy.array_split(numpy.array(two), 6)
        q2s = numpy.array_split(numpy.array(three), 6)
        q3s = numpy.array_split(numpy.array(four), 6)
        maxts = numpy.array_split(numpy.array(five), 6)

        colors = discrete_colors(len(stencils[0]))

        fig, ax = plt.subplots(3, 2, figsize=figsize(4, 2))

        axes = itertools.chain(*ax)
        for cstencil, cmint, cq1, cq2, cq3, cmaxt, ax in zip(stencils, mints, q1s, q2s, q3s, maxts, axes):

            for color, stencil, mint, q1, q2, q3, maxt in zip(colors, cstencil, cmint, cq1, cq2, cq3, cmaxt):
                ax.fill_between(dates, mint, maxt, alpha=0.2, color=color)
                ax.fill_between(dates, q1, q3, alpha=0.5, color=color)
                ax.plot(dates, q2, '|-', label=stencil.title(), color=color)

            ax.legend(loc='upper left')

            ax.xaxis.set_major_locator(locator)
            ax.xaxis.set_major_formatter(formatter)

        fig.autofmt_xdate()
        fig.tight_layout()

    return fig
Example #8
0
def history(results, key='job', limit=None):
    """Plots run time history of all results. Depending on the argument `job`,
       The results are either ordered by runtime (i.e. commit/build time) or
       job time (i.e. when the job was run).

    Args:
        results: List of `result.Result` objects.
        key: Either 'job' or 'runtime'.
        limit: Optionally limits the number of plotted results to the given
               number, i.e. only displays the most recent results. If `None`,
               all given results are plotted.
    """

    # get date/time either from the runtime (commit/build) or job (when job
    # was run)
    def get_datetime(result):
        if key == 'runtime':
            datetime = result.runtime.datetime
        elif key == 'job':
            datetime = result.datetime
        else:
            raise ArgumentError('"key" argument must be "runtime" or "job"')
        return time.local_time(datetime)

    # sort results by desired reference time
    results = sorted(results, key=get_datetime)

    #
    if limit is not None:
        if not isinstance(limit, int) or limit <= 0:
            raise ArgumentError('"limit" must be a positive integer')
        results = results[-limit:]

    data = result.percentiles_by_stencil(results, [0, 25, 50, 75, 100])

    dates = [matplotlib.dates.date2num(get_datetime(r)) for r in results]

    if len(dates) > len(set(dates)):
        logger.warning('Non-unique datetimes in history plot')

    fig, ax = plt.subplots(figsize=figsize(2, 1))

    locator = matplotlib.dates.AutoDateLocator()
    formatter = matplotlib.dates.AutoDateFormatter(locator)
    formatter.scaled[1 / 24] = '%y-%m-%d %H:%M'
    formatter.scaled[1 / (24 * 60)] = '%y-%m-%d %H:%M'
    formatter.scaled[1 / (24 * 60 * 60)] = '%y-%m-%d %H:%M:%S'

    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)

    colors = discrete_colors(len(data[0]))

    for color, stencil, mint, q1, q2, q3, maxt in zip(colors, *data):
        ax.fill_between(dates, mint, maxt, alpha=0.2, color=color)
        ax.fill_between(dates, q1, q3, alpha=0.5, color=color)
        ax.plot(dates, q2, '|-', label=stencil.title(), color=color)

    ax.legend(loc='upper left')
    fig.autofmt_xdate()
    fig.tight_layout()

    return fig