[cairo-commit] 2 commits - perf/cairo-perf.c perf/cairo-perf.h perf/paint.c perf/README perf/tessellate.c src/cairo.c

Carl Worth cworth at kemper.freedesktop.org
Fri Sep 29 16:46:45 PDT 2006


 perf/README       |   66 ++++++++++++++--------
 perf/cairo-perf.c |  157 +++++++++++++++++++++++++++++-------------------------
 perf/cairo-perf.h |   23 +++----
 perf/paint.c      |   32 +++++++----
 perf/tessellate.c |   22 +++++--
 src/cairo.c       |   24 +++++---
 6 files changed, 190 insertions(+), 134 deletions(-)

New commits:
diff-tree b99d41a0b075ec405d14ea8b6bbcaa50aa35e890 (from 3c19a6413cf77d86d75501f531af08b13db1f411)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Sep 29 16:46:39 2006 -0700

    Fix typo in documentation of cairo_in_fill (thanks to Jonathan Watt) and clarify a bit.

diff --git a/src/cairo.c b/src/cairo.c
index 3d574eb..aab6705 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2007,18 +2007,21 @@ cairo_show_page (cairo_t *cr)
  * @x: X coordinate of the point to test
  * @y: Y coordinate of the point to test
  *
- * Tests whether the given point is on the area stroked by doing a
- * cairo_stroke() operation on @cr given the current path and stroking
- * parameters.
+ * Tests whether the given point is inside the area that would be
+ * stroked by doing a cairo_stroke() operation on @cr given the
+ * current path and stroking parameters.
  *
- * See cairo_stroke, cairo_set_line_width(), cairo_set_line_join(),
+ * See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
  * cairo_set_line_cap(), cairo_set_dash(), and
  * cairo_stroke_preserve().
+ *
+ * Return value: A non-zero value if the point is inside, or zero if
+ * outside.
  **/
 cairo_bool_t
 cairo_in_stroke (cairo_t *cr, double x, double y)
 {
-    int inside;
+    cairo_bool_t inside;
 
     if (cr->status)
 	return 0;
@@ -2038,16 +2041,19 @@ cairo_in_stroke (cairo_t *cr, double x, 
  * @x: X coordinate of the point to test
  * @y: Y coordinate of the point to test
  *
- * Tests whether the given point is on the area filled by doing a
- * cairo_stroke() operation on @cr given the current path and filling
- * parameters.
+ * Tests whether the given point is inside the area that would be
+ * filled by doing a cairo_fill() operation on @cr given the current
+ * path and filling parameters.
  *
  * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
+ *
+ * Return value: A non-zero value if the point is inside, or zero if
+ * outside.
  **/
 cairo_bool_t
 cairo_in_fill (cairo_t *cr, double x, double y)
 {
-    int inside;
+    cairo_bool_t inside;
 
     if (cr->status)
 	return 0;
diff-tree 3c19a6413cf77d86d75501f531af08b13db1f411 (from cd6b44e9c924d230c9647e63553198a947f53307)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Sep 29 16:42:44 2006 -0700

    perf: Rework the suite to allow multiple performance tests to be defined in one file.

diff --git a/perf/README b/perf/README
index d577cd7..31dfc2f 100644
--- a/perf/README
+++ b/perf/README
@@ -25,8 +25,8 @@ Creating a new performance test
 This is where we could use everybody's help. If you have encountered a
 sequence of cairo operations that are slower than you would like, then
 please provide a performance test. Writing a test is very simple, it
-requires you to write only a single function exercising the cairo
-calls of interest.
+requires you to write only a small C file with a couple of functions,
+one of which exercises the cairo calls of interest.
 
 Here is the basic structure of a performance test file:
 
@@ -36,42 +36,61 @@ Here is the basic structure of a perform
      * Please copy the MIT blurb as in other tests
      */
 
-     #include "cairo-perf.h"
+    #include "cairo-perf.h"
 
-     cairo_perf_ticks_t
-     my_new_test (cairo_t *cr, int width, int height)
-     {
-         /* First do any setup for which the execution time should not
-          * be measured. For example, this might include loading
-          * images from disk, creating patterns, etc. */
+    static cairo_perf_ticks_t
+    do_my_new_test (cairo_t *cr, int width, int height)
+    {
+	/* First do any setup for which the execution time should not
+	 * be measured. For example, this might include loading
+	 * images from disk, creating patterns, etc. */
+
+	cairo_perf_timer_start ();
 
-         cairo_perf_timer_start ();
+	/* Now make the real cairo calls to be measured */
 
-	 /* Now make the real cairo calls to be measured */
+	cairo_perf_timer_stop ();
 
-	 cairo_perf_timer_stop ();
+	/* Finally, any cleanup */
 
-	 /* Finally, any cleanup */
+	/* Then return the time that elapsed. */
 
-	 /* Then return the time that elapsed. */
+	return cairo_perf_timer_elapsed ();
+     }
 
-	 return cairo_perf_timer_elapsed ();
+     void
+     my_new_test (cairo_perf_t *perf)
+     {
+	cairo_perf_run (perf, "my_new_test", do_my_new_test);
      }
 
-That's really all there is to writing a new test. Then, to fully
-integrate this you just need to add your new test to three different
-lists. (TODO: We should set this up better so that the lists are
-maintained automatically---computed from the list of files in
-cairo/perf, for example). Here's what needs to be added:
+That's really all there is to writing a new test. The first function
+above is the one that does the real work and returns a timing
+number. The second function is the one that will be called by the
+performance test rig (see below for how to accomplish that), and
+allows for multiple performance cases to be written in one file,
+(simply call cairo_perf_run once for each case, passing the
+appropriate callback function to each).
+
+We go through this dance of indirectly calling your own function
+through cairo_perf_run so that cairo_perf_run can call your function
+many times and measure statistical properties over the many runs.
+
+Finally, to fully integrate your new test case you just need to add
+your new test to three different lists. (TODO: We should set this up
+better so that the lists are maintained automatically---computed from
+the list of files in cairo/perf, for example). Here's what needs to be
+added:
 
  1. Makefile.am: Add the new file name to the cairo_perf_SOURCES list
 
- 2. cairo-perf.h: Add a new CAIRO_PERF_DECL line with the name of your function
+ 2. cairo-perf.h: Add a new CAIRO_PERF_DECL line with the name of your
+    function, (my_new_test in the example above)
 
  3. cairo-perf.c: Add a new row to the list at the end of the file. A
     typical entry would look like:
 
-	{ "my_new_test", my_new_test, 16, 64 }
+	{ my_new_test, 16, 64 }
 
     The last two numbers are a minimum and a maximum image size at
     which your test should be exercised. If these values are the same,
@@ -81,6 +100,3 @@ cairo/perf, for example). Here's what ne
     64x64.
 
 Thanks for your contributions and have fun with cairo!
-
-
-
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 6519c0b..ef3ac32 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -28,16 +28,22 @@
 
 #include "cairo-perf.h"
 
-int cairo_perf_iterations = 100;
 
-typedef struct _cairo_perf {
-    const char *name;
-    cairo_perf_func_t run;
+struct _cairo_perf {
+    unsigned int iterations;
+    cairo_boilerplate_target_t *target;
     unsigned int min_size;
     unsigned int max_size;
-} cairo_perf_t;
+    unsigned int test_number;
+};
 
-cairo_perf_t perfs[];
+typedef struct _cairo_perf_case {
+    CAIRO_PERF_DECL (*run);
+    unsigned int min_size;
+    unsigned int max_size;
+} cairo_perf_case_t;
+
+cairo_perf_case_t perf_cases[];
 
 /* Some targets just aren't that interesting for performance testing,
  * (not least because many of these surface types use a meta-surface
@@ -65,6 +71,8 @@ target_is_measurable (cairo_boilerplate_
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
+    case CAIRO_SURFACE_TYPE_NQUARTZ:
+    case CAIRO_SURFACE_TYPE_OS2:
 	return TRUE;
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
@@ -131,90 +139,97 @@ _compute_stats (cairo_perf_ticks_t *valu
     stats->std_dev = sqrt(sum / num_values) / stats->mean;
 }
 
-int
-main (int argc, char *argv[])
+void
+cairo_perf_run (cairo_perf_t		*perf,
+		const char		*name,
+		cairo_perf_func_t	 perf_func)
 {
-    int i, j, k;
-    cairo_boilerplate_target_t *target;
-    cairo_perf_t *perf;
+    static cairo_bool_t first_run = TRUE;
+
+    unsigned int i;
+    unsigned int size;
     cairo_surface_t *surface;
     cairo_t *cr;
-    unsigned int size;
     cairo_perf_ticks_t *times;
     stats_t stats;
+    cairo_boilerplate_target_t *target = perf->target;
+
+    times = xmalloc (perf->iterations * sizeof (cairo_perf_ticks_t));
+
+    for (size = perf->min_size; size <= perf->max_size; size *= 2) {
+	surface = (target->create_surface) (name,
+					    target->content,
+					    size, size,
+					    CAIRO_BOILERPLATE_MODE_PERF,
+					    &target->closure);
+	cairo_perf_timer_set_finalize (target->wait_for_rendering, target->closure);
+	cr = cairo_create (surface);
+	for (i =0; i < perf->iterations; i++) {
+	    cairo_perf_yield ();
+	    times[i] = (perf_func) (cr, size, size);
+	}
+
+	qsort (times, perf->iterations,
+	       sizeof (cairo_perf_ticks_t), compare_cairo_perf_ticks);
+
+	/* Assume the slowest 15% are outliers, and ignore */
+	_compute_stats (times, .85 * perf->iterations, &stats);
+
+	if (first_run) {
+	    printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
+		    "backend", "content", "test-size", "mean ms",
+		    "std dev.", "iterations");
+	    first_run = FALSE;
+	}
+
+	printf ("[%3d] %8s-%-4s %25s-%-3d ",
+		perf->test_number, target->name,
+		_content_to_string (target->content),
+		name, size);
+
+	printf ("%#9.3f %#5.2f%% % 5d\n",
+		(stats.mean * 1000.0) / cairo_perf_ticks_per_second (),
+		stats.std_dev * 100.0, perf->iterations);
+
+	perf->test_number++;
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+    int i, j;
+    cairo_perf_case_t *perf_case;
+    cairo_perf_t perf;
     const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
-    double ms;
-    int test_number;
 
     if (getenv("CAIRO_PERF_ITERATIONS"))
-	cairo_perf_iterations = strtol(getenv("CAIRO_PERF_ITERATIONS"), NULL, 0);
-
-    times = xmalloc (cairo_perf_iterations * sizeof (cairo_perf_ticks_t));
+	perf.iterations = strtol(getenv("CAIRO_PERF_ITERATIONS"), NULL, 0);
+    else
+	perf.iterations = 100;
 
     for (i = 0; targets[i].name; i++) {
-	target = &targets[i];
-	if (! target_is_measurable (target))
+	perf.target = &targets[i];
+	if (! target_is_measurable (perf.target))
 	    continue;
-	if (cairo_test_target && ! strstr (cairo_test_target, target->name))
+	if (cairo_test_target && ! strstr (cairo_test_target, perf.target->name))
 	    continue;
 
-	test_number = 0;
-
-	for (j = 0; perfs[j].name; j++) {
-	    perf = &perfs[j];
-	    for (size = perf->min_size; size <= perf->max_size; size *= 2) {
-		surface = (target->create_surface) (perf->name,
-						    target->content,
-						    size, size,
-						    CAIRO_BOILERPLATE_MODE_PERF,
-						    &target->closure);
-		cairo_perf_timer_set_finalize (target->wait_for_rendering, target->closure);
-		cr = cairo_create (surface);
-		for (k =0; k < cairo_perf_iterations; k++) {
-		    cairo_perf_yield ();
-		    times[k] = perf->run (cr, size, size);
-		}
-
-		qsort (times, cairo_perf_iterations,
-		       sizeof (cairo_perf_ticks_t), compare_cairo_perf_ticks);
-
-		/* Assume the slowest 15% are outliers, and ignore */
-		_compute_stats (times, .85 * cairo_perf_iterations, &stats);
-
-		if (i==0 && j==0 && size == perf->min_size)
-		    printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
-			    "backend", "content", "test-size", "mean ms",
-			    "std dev.", "iterations");
-
-		printf ("[%3d] %8s-%-4s %25s-%-3d ",
-			test_number, target->name, _content_to_string (target->content),
-			perf->name, size);
-
-		printf ("%#9.3f %#5.2f%% % 5d\n",
-			(stats.mean * 1000.0) / cairo_perf_ticks_per_second (),
-			stats.std_dev * 100.0, cairo_perf_iterations);
+	perf.test_number = 0;
 
-		test_number++;
-	    }
+	for (j = 0; perf_cases[j].run; j++) {
+	    perf_case = &perf_cases[j];
+	    perf.min_size = perf_case->min_size;
+	    perf.max_size = perf_case->max_size;
+	    perf_case->run (&perf);
 	}
     }
 
     return 0;
 }
 
-cairo_perf_t perfs[] = {
-    { "paint_over_solid", paint_over_solid, 64, 512 },
-    { "paint_over_solid_alpha", paint_over_solid_alpha, 64, 512 },
-    { "paint_source_solid", paint_over_solid, 64, 512 },
-    { "paint_source_solid_alpha", paint_over_solid_alpha, 64, 512 },
-
-    { "paint_over_surf_rgb24", paint_over_solid, 64, 512 },
-    { "paint_over_surf_argb32", paint_over_solid_alpha, 64, 512 },
-    { "paint_source_surf_rgb24", paint_over_solid, 64, 512 },
-    { "paint_source_surf_argb32", paint_over_solid_alpha, 64, 512 },
-
-    { "tessellate-16",	tessellate_16,	100, 100},
-    { "tessellate-64",	tessellate_64,	100, 100},
-    { "tessellate-256", tessellate_256, 100, 100},
+cairo_perf_case_t perf_cases[] = {
+    { paint, 64, 512},
+    { tessellate, 100, 100},
     { NULL }
 };
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index f22d762..6b40ae8 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -58,24 +58,23 @@ cairo_perf_ticks_per_second (void);
 void
 cairo_perf_yield (void);
 
+/* running a test case */
+typedef struct _cairo_perf cairo_perf_t;
+
 typedef cairo_perf_ticks_t
 (*cairo_perf_func_t) (cairo_t *cr, int width, int height);
 
-#define CAIRO_PERF_DECL(func) cairo_perf_ticks_t func (cairo_t *cr, int width, int height)
+void
+cairo_perf_run (cairo_perf_t		*perf,
+		const char		*name,
+		cairo_perf_func_t	 perf_func);
+
+#define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf);
 
 /* paint.c */
-CAIRO_PERF_DECL (paint_over_solid);
-CAIRO_PERF_DECL (paint_over_solid_alpha);
-CAIRO_PERF_DECL (paint_source_solid);
-CAIRO_PERF_DECL (paint_source_solid_alpha);
-CAIRO_PERF_DECL (paint_over_surface_rgb24);
-CAIRO_PERF_DECL (paint_over_surface_argb32);
-CAIRO_PERF_DECL (paint_source_surface_rgb24);
-CAIRO_PERF_DECL (paint_source_surface_argb32);
+CAIRO_PERF_DECL (paint);
 
 /* tessellate.c */
-CAIRO_PERF_DECL (tessellate_16);
-CAIRO_PERF_DECL (tessellate_64);
-CAIRO_PERF_DECL (tessellate_256);
+CAIRO_PERF_DECL (tessellate);
 
 #endif
diff --git a/perf/paint.c b/perf/paint.c
index 1556383..10aacc0 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -58,7 +58,7 @@ do_paint (cairo_t *cr, int size)
  * paint with solid color
  */
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_over_solid (cairo_t *cr, int width, int height)
 {
     cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
@@ -66,7 +66,7 @@ paint_over_solid (cairo_t *cr, int width
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_over_solid_alpha (cairo_t *cr, int width, int height)
 {
     cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
@@ -74,7 +74,7 @@ paint_over_solid_alpha (cairo_t *cr, int
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_source_solid (cairo_t *cr, int width, int height)
 {
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
@@ -83,7 +83,7 @@ paint_source_solid (cairo_t *cr, int wid
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_source_solid_alpha (cairo_t *cr, int width, int height)
 {
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
@@ -96,13 +96,12 @@ paint_source_solid_alpha (cairo_t *cr, i
  * paint with surface
  */
 
-
 int cached_surface_width = 0;
 int cached_surface_height = 0;
 cairo_content_t cached_surface_content = 0;
 cairo_surface_t *cached_surface = NULL;
 
-void
+static void
 ensure_cached_surface (cairo_t *cr, cairo_content_t content, int w, int h)
 {
     cairo_surface_t *target_surface = cairo_get_target (cr);
@@ -143,7 +142,7 @@ ensure_cached_surface (cairo_t *cr, cair
     cairo_destroy (cr2);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_over_surface_rgb24 (cairo_t *cr, int width, int height)
 {
     ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
@@ -153,7 +152,7 @@ paint_over_surface_rgb24 (cairo_t *cr, i
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_over_surface_argb32 (cairo_t *cr, int width, int height)
 {
     ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
@@ -163,7 +162,7 @@ paint_over_surface_argb32 (cairo_t *cr, 
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_source_surface_rgb24 (cairo_t *cr, int width, int height)
 {
     ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
@@ -174,7 +173,7 @@ paint_source_surface_rgb24 (cairo_t *cr,
     return do_paint (cr, width);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 paint_source_surface_argb32 (cairo_t *cr, int width, int height)
 {
     ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
@@ -184,3 +183,16 @@ paint_source_surface_argb32 (cairo_t *cr
 
     return do_paint (cr, width);
 }
+
+void
+paint (cairo_perf_t *perf)
+{
+    cairo_perf_run (perf, "paint_over_solid", paint_over_solid);
+    cairo_perf_run (perf, "paint_over_solid_alpha", paint_over_solid_alpha);
+    cairo_perf_run (perf, "paint_source_solid", paint_source_solid);
+    cairo_perf_run (perf, "paint_source_solid_alpha", paint_source_solid_alpha);
+    cairo_perf_run (perf, "paint_over_surf_rgb24", paint_over_surface_rgb24);
+    cairo_perf_run (perf, "paint_over_surf_argb32", paint_over_surface_argb32);
+    cairo_perf_run (perf, "paint_source_surf_rgb24", paint_source_surface_rgb24);
+    cairo_perf_run (perf, "paint_source_surf_argb32", paint_source_surface_argb32);
+}
diff --git a/perf/tessellate.c b/perf/tessellate.c
index c7b64e5..e8f3dd6 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -99,7 +99,7 @@ point_t points[300] = {
 };
 
 static cairo_perf_ticks_t
-tessellate (cairo_t *cr, int num_points)
+do_tessellate (cairo_t *cr, int num_points)
 {
     int i;
 
@@ -122,22 +122,30 @@ tessellate (cairo_t *cr, int num_points)
     return cairo_perf_timer_elapsed ();
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 tessellate_16 (cairo_t *cr, int width, int height)
 {
-    return tessellate (cr, 16);
+    return do_tessellate (cr, 16);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 tessellate_64 (cairo_t *cr, int width, int height)
 {
-    return tessellate (cr, 64);
+    return do_tessellate (cr, 64);
 }
 
-cairo_perf_ticks_t
+static cairo_perf_ticks_t
 tessellate_256 (cairo_t *cr, int width, int height)
 {
-    return tessellate (cr, 256);
+    return do_tessellate (cr, 256);
+}
+
+void
+tessellate (cairo_perf_t *perf)
+{
+    cairo_perf_run (perf, "tessellate-16", tessellate_16);
+    cairo_perf_run (perf, "tessellate-64", tessellate_64);
+    cairo_perf_run (perf, "tessellate-256", tessellate_256);
 }
 
 #if 0


More information about the cairo-commit mailing list