[cairo-commit] 3 commits - configure.ac perf/cairo-perf.h perf/cairo-perf-print.c perf/cairo-perf-report.c perf/cairo-stats.c perf/cairo-stats.h

Chris Wilson ickle at kemper.freedesktop.org
Tue Jun 11 05:51:26 PDT 2013


 configure.ac             |    2 
 perf/cairo-perf-print.c  |   98 +++++++++++++++++++++++++++++++++++++++--------
 perf/cairo-perf-report.c |    2 
 perf/cairo-perf.h        |    9 ++++
 perf/cairo-stats.c       |   83 +++++++++++++++++++++++++++++++++++++++
 perf/cairo-stats.h       |   16 +++++++
 6 files changed, 193 insertions(+), 17 deletions(-)

New commits:
commit 2c097e6e6b8375b7d488572cdb09b80dca06d42a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 11 11:57:04 2013 +0100

    perf: Avoid vertically stretching the histogram
    
    If we have more rows than the max_count in any column, we end up
    stretching the histogram vertically, which makes it harder to read.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/perf/cairo-stats.c b/perf/cairo-stats.c
index c10c921..aee9fe8 100644
--- a/perf/cairo-stats.c
+++ b/perf/cairo-stats.c
@@ -156,10 +156,13 @@ void
 _cairo_histogram_printf (cairo_histogram_t *h,
 			 FILE *file)
 {
-    int x, y;
+    int x, y, num_rows;
 
-    for (y = 0; y < h->num_rows; y++) {
-	int min_count = (h->num_rows - y - 1) * h->max_count / h->num_rows;
+    num_rows = h->num_rows;
+    if (h->max_count < num_rows)
+	num_rows = h->max_count;
+    for (y = 0; y < num_rows; y++) {
+	int min_count = ((num_rows - y - 1) * h->max_count) / num_rows + h->max_count / (2*num_rows);
 	fprintf (file, "|");
 	for (x = 0; x < h->num_columns; x++)
 	    fprintf (file, "%c", h->columns[x] > min_count ? 'x' : ' ');
commit b9f0ef4496eca31b47296543f48078b2a7034750
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 11 11:47:24 2013 +0100

    perf: Rescale the histogram for the terminal
    
    If running ./cairo-perf-print in a terminal, query the terminal size and
    rescale the histogram to use the maximum available space.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 928a169..c08dbb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,8 @@ AC_USE_SYSTEM_EXTENSIONS
 AC_CONFIG_SRCDIR(src/cairo.h)
 AC_CONFIG_HEADERS(config.h)
 
+AC_CHECK_HEADERS([unistd.h sys/ioctl.h])
+
 AM_INIT_AUTOMAKE([1.11 foreign -Wall no-define no-dist-gzip dist-xz])
 AM_SILENT_RULES([yes])
 
diff --git a/perf/cairo-perf-print.c b/perf/cairo-perf-print.c
index b6cf4ca..1bf1b41 100644
--- a/perf/cairo-perf-print.c
+++ b/perf/cairo-perf-print.c
@@ -27,11 +27,27 @@
  *	    Chris Wilson <chris at chris-wilson.co.uk>
  */
 
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "cairo-perf.h"
 #include "cairo-stats.h"
 
 #include <stdio.h>
 
+#if HAVE_UNISTD_H && HAVE_SYS_IOCTL_H
+#define USE_TERMINAL_SIZE 1
+#else
+#define USE_TERMINAL_SIZE 0
+#error bang
+#endif
+
+#if USE_TERMINAL_SIZE
+#include <unistd.h>
+#include <sys/ioctl.h>
+#endif
+
 static void
 report_print (const cairo_perf_report_t *report,
 	      int show_histogram)
@@ -39,8 +55,25 @@ report_print (const cairo_perf_report_t *report,
     const test_report_t *test;
     cairo_histogram_t h;
 
-    if (show_histogram && !_cairo_histogram_init (&h, 80, 23))
-	show_histogram = 0;
+    if (show_histogram) {
+	int num_rows = 23;
+	int num_cols = 80;
+
+#if USE_TERMINAL_SIZE
+	int fd = fileno(stdout);
+	if (isatty(fd)) {
+	    struct winsize ws;
+
+	    if(ioctl(fd, TIOCGWINSZ, &ws) == 0 ) {
+		num_rows = ws.ws_row - 1;
+		num_cols = ws.ws_col;
+	    }
+	}
+#endif
+
+	if (!_cairo_histogram_init (&h, num_cols, num_rows))
+	    show_histogram = 0;
+    }
 
     for (test = report->tests; test->name != NULL; test++) {
 	if (test->stats.iterations == 0)
commit 9a12c2e02369f0920c1f1f578eb8d228add77ea1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 11 11:05:03 2013 +0100

    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 at chris-wilson.co.uk>

diff --git a/perf/cairo-perf-print.c b/perf/cairo-perf-print.c
index 16a3ff4..b6cf4ca 100644
--- a/perf/cairo-perf-print.c
+++ b/perf/cairo-perf-print.c
@@ -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);
+	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  %6.2f %4.2f%%\n",
-		    tests->backend, tests->name,
-		    tests->stats.median_ticks / tests->stats.ticks_per_ms,
-		    tests->stats.std_dev * 100);
+	    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;
diff --git a/perf/cairo-perf-report.c b/perf/cairo-perf-report.c
index 38bdc0c..b86bc36 100644
--- a/perf/cairo-perf-report.c
+++ b/perf/cairo-perf-report.c
@@ -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 ();
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index feab74b..4e898ac 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -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
diff --git a/perf/cairo-stats.c b/perf/cairo-stats.c
index 7a36a13..c10c921 100644
--- a/perf/cairo-stats.c
+++ b/perf/cairo-stats.c
@@ -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);
+}
diff --git a/perf/cairo-stats.h b/perf/cairo-stats.h
index 8406e65..2b32d67 100644
--- a/perf/cairo-stats.h
+++ b/perf/cairo-stats.h
@@ -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_ */


More information about the cairo-commit mailing list