[cairo-commit] 4 commits - boilerplate/cairo-boilerplate.c perf/cairo-perf.c perf/cairo-perf.h test/dash-infinite-loop.c

M. Joonas Pihlaja joonas at kemper.freedesktop.org
Fri Sep 4 19:53:26 PDT 2009


 boilerplate/cairo-boilerplate.c |   63 +++++++++++++++++++++++++++++++++++++---
 perf/cairo-perf.c               |   59 ++++++++++++++++++++++++-------------
 perf/cairo-perf.h               |    3 +
 test/dash-infinite-loop.c       |    2 -
 4 files changed, 102 insertions(+), 25 deletions(-)

New commits:
commit 270b2f1be0e600621647f2e2486618c134217941
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Sat Sep 5 05:39:35 2009 +0300

    [perf] Add a fast-and-sloppy mode to cairo-perf.
    
    A new -f option to cairo-perf reverts to a fast run
    mode for quick performance overviews. The number of
    milliseconds each iteration of a test is run for can
    be overriden using the new CAIRO_PERF_ITERATION_MS
    environment variable. The default remains 2000 ms/iter.

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index b643615..b3afcd4 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -48,9 +48,11 @@
 #include <sched.h>
 #endif
 
-#define CAIRO_PERF_ITERATIONS_DEFAULT	100
-#define CAIRO_PERF_LOW_STD_DEV		0.03
-#define CAIRO_PERF_STABLE_STD_DEV_COUNT	5
+#define CAIRO_PERF_ITERATIONS_DEFAULT		100
+#define CAIRO_PERF_LOW_STD_DEV			0.03
+#define CAIRO_PERF_STABLE_STD_DEV_COUNT		5
+#define CAIRO_PERF_ITERATION_MS_DEFAULT		2000
+#define CAIRO_PERF_ITERATION_MS_FAST		5
 
 typedef struct _cairo_perf_case {
     CAIRO_PERF_DECL (*run);
@@ -251,26 +253,31 @@ cairo_perf_run (cairo_perf_t		*perf,
 		                           cairo_boilerplate_content (perf->target->content));
 	perf_func (perf->cr, perf->size, perf->size, 1);
 	calibration0 = perf_func (perf->cr, perf->size, perf->size, 1);
-	loops = cairo_perf_ticks_per_second () / 100 / calibration0;
-	if (loops < 3)
-	    loops = 3;
-	calibration = (calibration0 + perf_func (perf->cr, perf->size, perf->size, loops)) / (loops + 1);
-	if (similar)
-	    cairo_pattern_destroy (cairo_pop_group (perf->cr));
+	if (perf->fast_and_sloppy) {
+	    calibration = calibration0;
+	} else {
+	    loops = cairo_perf_ticks_per_second () / 100 / calibration0;
+	    if (loops < 3)
+		loops = 3;
+	    calibration = (calibration0 + perf_func (perf->cr, perf->size, perf->size, loops)) / (loops + 1);
+	    if (similar)
+		cairo_pattern_destroy (cairo_pop_group (perf->cr));
+	}
 
 	/* XXX
-	 * Compute the number of loops required for the timing interval to
-	 * be ~2 seconds. This helps to eliminate sampling variance due to
-	 * timing and other systematic errors. However, it also hides
-	 * synchronisation overhead as we attempt to process a large batch
-	 * of identical operations in a single shot. This can be considered
-	 * both good and bad... It would be good to perform a more rigorous
-	 * analysis of the synchronisation overhead, that is to estimate
-	 * the time for loop=0.
+	 * Compute the number of loops required for the timing
+	 * interval to be perf->ms_per_iteration milliseconds. This
+	 * helps to eliminate sampling variance due to timing and
+	 * other systematic errors.  However, it also hides
+	 * synchronisation overhead as we attempt to process a large
+	 * batch of identical operations in a single shot. This can be
+	 * considered both good and bad... It would be good to perform
+	 * a more rigorous analysis of the synchronisation overhead,
+	 * that is to estimate the time for loop=0.
 	 */
-	loops = 2 * cairo_perf_ticks_per_second () / calibration;
+	loops = perf->ms_per_iteration * 0.001 * cairo_perf_ticks_per_second () / calibration;
 	if (loops < 10)
-	    loops = 10;
+	    loops = perf->fast_and_sloppy ? 1 : 10;
 
 	low_std_dev_count = 0;
 	for (i =0; i < perf->iterations; i++) {
@@ -350,6 +357,7 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
 {
     int c;
     const char *iters;
+    const char *ms = NULL;
     char *end;
     int verbose = 0;
 
@@ -359,6 +367,12 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
 	perf->iterations = CAIRO_PERF_ITERATIONS_DEFAULT;
     perf->exact_iterations = 0;
 
+    perf->fast_and_sloppy = FALSE;
+    perf->ms_per_iteration = CAIRO_PERF_ITERATION_MS_DEFAULT;
+    if ((ms = getenv("CAIRO_PERF_ITERATION_MS")) && *ms) {
+	perf->ms_per_iteration = atof(ms);
+    }
+
     perf->raw = FALSE;
     perf->list_only = FALSE;
     perf->names = NULL;
@@ -366,7 +380,7 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
     perf->summary = stdout;
 
     while (1) {
-	c = _cairo_getopt (argc, argv, "i:lrv");
+	c = _cairo_getopt (argc, argv, "i:lrvf");
 	if (c == -1)
 	    break;
 
@@ -387,6 +401,11 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
 	    perf->raw = TRUE;
 	    perf->summary = NULL;
 	    break;
+	case 'f':
+	    perf->fast_and_sloppy = TRUE;
+	    if (ms == NULL)
+		perf->ms_per_iteration = CAIRO_PERF_ITERATION_MS_FAST;
+	    break;
 	case 'v':
 	    verbose = 1;
 	    break;
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 6903dbf..6d1741a 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -83,6 +83,9 @@ typedef struct _cairo_perf {
     unsigned int num_exclude_names;
     cairo_bool_t exact_names;
 
+    double ms_per_iteration;
+    cairo_bool_t fast_and_sloppy;
+
     /* Stuff used internally */
     cairo_perf_ticks_t *times;
     const cairo_boilerplate_target_t **targets;
commit 7f91c4953ccfbb96d76ecd73715fa2e524be933e
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Sat Sep 5 05:07:25 2009 +0300

    [boilerplate] Support wildcard ? in CAIRO_TEST_TARGET{,_EXCLUDE}.
    
    Useful for running tests only for a given content type.

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index e681108..46bb057 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -392,10 +392,12 @@ _cairo_boilerplate_target_matches_name (const cairo_boilerplate_target_t *target
     name_len = end - tname;
 
     /* Check name. */
-    if (0 != strncmp (target->name, tname, name_len)) /* exact match? */
-	return FALSE;
-    if (isalnum (target->name[name_len]))
-	return FALSE;
+    if (! (name_len == 1 && 0 == strncmp (tname, "?", 1))) { /* wildcard? */
+	if (0 != strncmp (target->name, tname, name_len)) /* exact match? */
+	    return FALSE;
+	if (isalnum (target->name[name_len]))
+	    return FALSE;
+    }
 
     /* Check optional content. */
     if (content_start == NULL)	/* none given? */
commit b3bafbc5f9201662702cc0c0d1c96411e31bb7d3
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Sat Sep 5 05:02:00 2009 +0300

    [boilerplate] Support giving content in CAIRO_TEST_TARGET{,_EXCLUDE}.
    
    Sometimes it's convenient to run the regression or performance tests
    against a given target with a given content.  Now we accept an optional
    content specifier as a suffix .<content> on a target name, where
    <content> is rgb or rgba.

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index ebbad45..e681108 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -88,6 +88,22 @@ cairo_boilerplate_content_name (cairo_content_t content)
     }
 }
 
+static const char *
+_cairo_boilerplate_content_visible_name (cairo_content_t content)
+{
+    switch (cairo_boilerplate_content (content)) {
+    case CAIRO_CONTENT_COLOR:
+	return "rgb";
+    case CAIRO_CONTENT_COLOR_ALPHA:
+	return "rgba";
+    case CAIRO_CONTENT_ALPHA:
+	return "a";
+    default:
+	assert (0); /* not reached */
+	return "---";
+    }
+}
+
 cairo_format_t
 cairo_boilerplate_format_from_content (cairo_content_t content)
 {
@@ -359,6 +375,43 @@ _cairo_boilerplate_register_backend (const cairo_boilerplate_target_t *targets,
     }
 }
 
+static cairo_bool_t
+_cairo_boilerplate_target_matches_name (const cairo_boilerplate_target_t *target,
+					const char                       *tname,
+					const char                       *end)
+{
+    char const *content_name;
+    const char *content_start = strpbrk (tname, ".");
+    const char *content_end = end;
+    size_t name_len;
+    size_t content_len;
+
+    if (content_start != NULL)
+	end = content_start++;
+
+    name_len = end - tname;
+
+    /* Check name. */
+    if (0 != strncmp (target->name, tname, name_len)) /* exact match? */
+	return FALSE;
+    if (isalnum (target->name[name_len]))
+	return FALSE;
+
+    /* Check optional content. */
+    if (content_start == NULL)	/* none given? */
+	return TRUE;
+
+    /* Exact content match? */
+    content_name = _cairo_boilerplate_content_visible_name (target->content);
+    content_len = content_end - content_start;
+    if (strlen(content_name) != content_len)
+	return FALSE;
+    if (0 == strncmp (content_name, content_start, content_len))
+	return TRUE;
+
+    return FALSE;
+}
+
 const cairo_boilerplate_target_t **
 cairo_boilerplate_get_targets (int *pnum_targets, cairo_bool_t *plimited_targets)
 {
@@ -394,8 +447,7 @@ cairo_boilerplate_get_targets (int *pnum_targets, cairo_bool_t *plimited_targets
 		 list = list->next)
 	    {
 		const cairo_boilerplate_target_t *target = list->target;
-		if (0 == strncmp (target->name, tname, end - tname) &&
-		    !isalnum (target->name[end - tname])) {
+		if (_cairo_boilerplate_target_matches_name (target, tname, end)) {
 		    /* realloc isn't exactly the best thing here, but meh. */
 		    targets_to_test = xrealloc (targets_to_test, sizeof(cairo_boilerplate_target_t *) * (num_targets+1));
 		    targets_to_test[num_targets++] = target;
@@ -465,8 +517,9 @@ cairo_boilerplate_get_targets (int *pnum_targets, cairo_bool_t *plimited_targets
 	    }
 
 	    for (i = j = 0; i < num_targets; i++) {
-		if (strncmp (targets_to_test[i]->name, tname, end - tname) ||
-		    isalnum (targets_to_test[i]->name[end - tname]))
+		const cairo_boilerplate_target_t *target = targets_to_test[i];
+		if (! _cairo_boilerplate_target_matches_name (target,
+							      tname, end))
 		{
 		    targets_to_test[j++] = targets_to_test[i];
 		}
commit 29432d3d32bc84ec4a2e1815a84e4ac2089138fe
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Sat Sep 5 02:25:01 2009 +0300

    [test] Reorder dash-infinite-loop to not hit a runaway allocation.
    
    This test is annoying enough as it is what with it wedging the
    test suite and all.  There's no reason why it should DOS the
    running box as well by sitting in a loop allocating like mad.

diff --git a/test/dash-infinite-loop.c b/test/dash-infinite-loop.c
index a3d7544..5476137 100644
--- a/test/dash-infinite-loop.c
+++ b/test/dash-infinite-loop.c
@@ -68,9 +68,9 @@ draw (cairo_t *cr, int width, int height)
 
     /* The following calls will wedge in various places that try
      * to advance the dashing in a loop inside the stroker. */
+    do_dash (cr, 30, 30, 1); /* _cairo_stroker_dash_start */
     do_dash (cr, 30, 30, 0); /* _cairo_stroker_line_to_dashed */
     do_dash (cr, 30,  0, 0); /* _cairo_rectilinear_stroker_line_to_dashed */
-    do_dash (cr, 30, 30, 1); /* _cairo_stroker_dash_start */
 
     return CAIRO_TEST_SUCCESS;
 }


More information about the cairo-commit mailing list