perf: Rudimentary histogram printing for cairo-perf-print

If you call ./cairo-perf-print --histogram results.txt, it will then
print a histogram of the results, one per test. Ideally, you should see
a skewed distribution (with a negative skew representing that most results
run in optimal time), but random sampling errors (scheduling,
throttling, general inefficiency etc) will push it more towards a normal
distribution.

For example,
|                                                             x                |
|                                                             x xx             |
|                                                             x xx             |
|                                                             x xx             |
|                                                             xxxx             |
|                                                             xxxx x           |
|                                                          x  xxxxxx           |
|                                                          x  xxxxxx           |
|                                                          xxxxxxxxx           |
|                                                          xxxxxxxxx           |
|                                                          xxxxxxxxx           |
|                                                         xxxxxxxxxxxx         |
|                                                         xxxxxxxxxxxx         |
|                                                         xxxxxxxxxxxx         |
|                                                        xxxxxxxxxxxxxx        |
|x                                                       xxxxxxxxxxxxxx        |
|x x                                                     xxxxxxxxxxxxxxx       |
|x x                                                     xxxxxxxxxxxxxxx       |
|x x                                                    xxxxxxxxxxxxxxxxx      |
|xxx                                                 x xxxxxxxxxxxxxxxxxxx     |
|xxx                                                xxxxxxxxxxxxxxxxxxxxxxxxx  |
|xxxxxx xxxx x x x   x xxx xx xxxxx xxx x xxx x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
.------------------------------------------------------------------------------.
 xlib           firefox-fishtank  8298.44 1.53% (829/946)

Starts off reasonably, but quickly deteriorates as the integrated CPU/GPU
overheats and is forced to throttle.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-06-11 11:05:03 +01:00
parent e519d6f986
commit 9a12c2e023
5 changed files with 156 additions and 18 deletions

View file

@ -28,45 +28,78 @@
*/
#include "cairo-perf.h"
#include "cairo-stats.h"
#include <stdio.h>
static void
report_print (const cairo_perf_report_t *report)
report_print (const cairo_perf_report_t *report,
int show_histogram)
{
const test_report_t *tests;
const test_report_t *test;
cairo_histogram_t h;
tests = report->tests;
for (tests = report->tests; tests->name != NULL; tests++) {
if (tests->stats.iterations == 0)
if (show_histogram && !_cairo_histogram_init (&h, 80, 23))
show_histogram = 0;
for (test = report->tests; test->name != NULL; test++) {
if (test->stats.iterations == 0)
continue;
if (tests->size) {
printf ("%5s-%-4s %26s-%-3d %6.2f %4.2f%%\n",
tests->backend, tests->content,
tests->name, tests->size,
tests->stats.median_ticks / tests->stats.ticks_per_ms,
tests->stats.std_dev * 100);
} else {
printf ("%5s %26s %6.2f %4.2f%%\n",
tests->backend, tests->name,
tests->stats.median_ticks / tests->stats.ticks_per_ms,
tests->stats.std_dev * 100);
if (show_histogram) {
const cairo_time_t *values;
int num_values;
if (show_histogram > 1) {
values = test->stats.values;
num_values = test->stats.iterations;
} else {
values = test->samples;
num_values = test->samples_count;
}
if (_cairo_histogram_compute (&h, values, num_values))
_cairo_histogram_printf (&h, stdout);
}
if (test->size) {
printf ("%5s-%-4s %26s-%-3d ",
test->backend, test->content,
test->name, test->size);
} else {
printf ("%5s %26s ", test->backend, test->name);
}
printf("%6.2f %4.2f%% (%d/%d)\n",
test->stats.median_ticks / test->stats.ticks_per_ms,
test->stats.std_dev * 100,
test->stats.iterations, test->samples_count);
}
_cairo_histogram_fini (&h);
}
int
main (int argc,
const char *argv[])
{
cairo_bool_t show_histogram = 0;
int i;
for (i = 1; i < argc; i++ ) {
cairo_perf_report_t report;
if (strcmp(argv[i], "--histogram") == 0) {
show_histogram = 1;
continue;
}
if (strcmp(argv[i], "--short-histogram") == 0) {
show_histogram = 2;
continue;
}
cairo_perf_report_load (&report, argv[i], i, NULL);
report_print (&report);
report_print (&report, show_histogram);
}
return 0;

View file

@ -186,7 +186,7 @@ test_report_parse (test_report_t *report,
skip_space ();
} while (*s && *s != '\n');
report->stats.iterations = 0;
skip_char ('\n');
if (*s) skip_char ('\n');
} else {
parse_double (report->stats.min_ticks);
skip_space ();

View file

@ -38,8 +38,17 @@ typedef struct _cairo_stats {
double ticks_per_ms;
double std_dev;
int iterations;
cairo_time_t *values;
} cairo_stats_t;
typedef struct _cairo_histogram {
int width, height, max_count;
int num_columns, num_rows;
cairo_time_t min_value, max_value;
int *columns;
} cairo_histogram_t;
/* timers */
void

View file

@ -43,6 +43,7 @@ _cairo_stats_compute (cairo_stats_t *stats,
stats->min_ticks = stats->median_ticks = values[0];
stats->std_dev = 0;
stats->iterations = 1;
stats->values = values;
return;
}
@ -80,6 +81,7 @@ _cairo_stats_compute (cairo_stats_t *stats,
values += min_valid;
} while (num_valid != num_values);
stats->values = values;
stats->iterations = num_valid;
stats->min_ticks = values[0];
stats->median_ticks = values[num_valid / 2];
@ -97,3 +99,81 @@ _cairo_stats_compute (cairo_stats_t *stats,
}
stats->std_dev = sqrt(s / num_valid);
}
cairo_bool_t
_cairo_histogram_init (cairo_histogram_t *h,
int width, int height)
{
h->width = width;
h->height = height;
if (h->width < 2 || h->height < 1)
return FALSE;
h->num_columns = width - 2;
h->num_rows = height - 1;
h->columns = malloc (sizeof(int)*h->num_columns);
return h->columns != NULL;
}
cairo_bool_t
_cairo_histogram_compute (cairo_histogram_t *h,
const cairo_time_t *values,
int num_values)
{
cairo_time_t delta;
int i;
if (num_values == 0)
return FALSE;
h->min_value = values[0];
h->max_value = values[0];
for (i = 1; i < num_values; i++) {
if (values[i] < h->min_value)
h->min_value = values[i];
if (values[i] > h->max_value)
h->max_value = values[i];
}
delta = h->max_value - h->min_value;
if (delta == 0)
return FALSE;
memset(h->columns, 0, sizeof(int)*h->num_columns);
h->max_count = 0;
for (i = 0; i < num_values; i++) {
int count = h->columns[(values[i] - h->min_value) * (h->num_columns - 1) / delta]++;
if (count > h->max_count)
h->max_count = count;
}
return TRUE;
}
void
_cairo_histogram_printf (cairo_histogram_t *h,
FILE *file)
{
int x, y;
for (y = 0; y < h->num_rows; y++) {
int min_count = (h->num_rows - y - 1) * h->max_count / h->num_rows;
fprintf (file, "|");
for (x = 0; x < h->num_columns; x++)
fprintf (file, "%c", h->columns[x] > min_count ? 'x' : ' ');
fprintf (file, "|\n");
}
fprintf(file, ".");
for (x = 0; x < h->num_columns; x++)
fprintf (file, "-");
fprintf (file, ".\n");
}
void
_cairo_histogram_fini (cairo_histogram_t *h)
{
free(h->columns);
}

View file

@ -33,4 +33,20 @@ _cairo_stats_compute (cairo_stats_t *stats,
cairo_time_t *values,
int num_values);
cairo_bool_t
_cairo_histogram_init (cairo_histogram_t *h,
int width, int height);
cairo_bool_t
_cairo_histogram_compute (cairo_histogram_t *h,
const cairo_time_t *values,
int num_values);
void
_cairo_histogram_printf (cairo_histogram_t *h,
FILE *file);
void
_cairo_histogram_fini (cairo_histogram_t *h);
#endif /* _CAIRO_STATS_H_ */