[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