[cairo] Multithreaded cairo-perf
Chris Wilson
chris at chris-wilson.co.uk
Thu Mar 22 18:17:02 PDT 2007
The recently introduced solid pattern cache has triggered a fresh set of
bad reference assertion failures, which are probably due to the lack of
atomic reference counting and highlight a lack of concurrency testing
performed by the Cairo test suite. This patch allows cairo-perf to be
run across multiple threads. It introduces a -t <int> cmdline option which
causes the creation of <int> threads where each thread runs all the perf
cases sequentially. The patch is a WIP as it makes no attempt to manage
the output from multiple threads nor provide a portable threading
interface, but it does enable concurrency testing.
Comments?
--
Chris Wilson
-------------- next part --------------
diff --git a/perf/box-outline.c b/perf/box-outline.c
index 74dd19a..7eadce8 100644
--- a/perf/box-outline.c
+++ b/perf/box-outline.c
@@ -41,7 +41,7 @@
*/
static cairo_perf_ticks_t
-box_outline_stroke (cairo_t *cr, int width, int height)
+box_outline_stroke (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
cairo_paint (cr);
@@ -52,17 +52,17 @@ box_outline_stroke (cairo_t *cr, int width, int height)
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_stroke (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
static cairo_perf_ticks_t
-box_outline_fill (cairo_t *cr, int width, int height)
+box_outline_fill (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
cairo_paint (cr);
@@ -76,18 +76,18 @@ box_outline_fill (cairo_t *cr, int width, int height)
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_source_rgb (cr, 0, 1, 0); /* green */
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_fill (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke);
- cairo_perf_run (perf, "box-outline-fill", box_outline_fill);
+ cairo_perf_run (perf, cr, "box-outline-stroke", box_outline_stroke);
+ cairo_perf_run (perf, cr, "box-outline-fill", box_outline_fill);
}
diff --git a/perf/cairo-perf-cover.c b/perf/cairo-perf-cover.c
index 53dc7b7..426f872 100644
--- a/perf/cairo-perf-cover.c
+++ b/perf/cairo-perf-cover.c
@@ -197,6 +197,7 @@ typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
void
cairo_perf_cover_sources_and_operators (cairo_perf_t *perf,
+ cairo_t *cr,
const char *name,
cairo_perf_func_t perf_func)
{
@@ -222,14 +223,14 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t *perf,
};
for (i = 0; i < ARRAY_SIZE (sources); i++) {
- (sources[i].set_source) (perf->cr, perf->size, perf->size);
+ (sources[i].set_source) (cr, perf->size, perf->size);
for (j = 0; j < ARRAY_SIZE (operators); j++) {
- cairo_set_operator (perf->cr, operators[j].op);
+ cairo_set_operator (cr, operators[j].op);
xasprintf (&expanded_name, "%s_%s_%s",
name, sources[i].name, operators[j].name);
- cairo_perf_run (perf, expanded_name, perf_func);
+ cairo_perf_run (perf, cr, expanded_name, perf_func);
free (expanded_name);
}
}
diff --git a/perf/cairo-perf-posix.c b/perf/cairo-perf-posix.c
index 68637ef..b313606 100644
--- a/perf/cairo-perf-posix.c
+++ b/perf/cairo-perf-posix.c
@@ -65,11 +65,11 @@
/* timers */
#if defined(__i386__) || defined(__amd64__)
-static inline unsigned long
+static inline cairo_perf_ticks_t
oil_profile_stamp_rdtsc (void)
{
unsigned long ts;
- __asm__ __volatile__("rdtsc\n" : "=a" (ts) : : "edx");
+ __asm__ __volatile__("rdtsc\n" : "=a" (ts), :: "edx");
return ts;
}
#define OIL_STAMP oil_profile_stamp_rdtsc
@@ -98,7 +98,7 @@ oil_profile_stamp_alpha(void)
#endif
#if defined(__s390__)
-static cairo_perf_ticks_t
+static inline cairo_perf_ticks_t
oil_profile_stamp_s390(void)
{
uint64_t ts;
@@ -108,7 +108,7 @@ oil_profile_stamp_s390(void)
#define OIL_STAMP oil_profile_stamp_s390
#endif
-typedef struct _cairo_perf_timer
+struct _cairo_perf_timer
{
#ifdef OIL_STAMP
cairo_perf_ticks_t start;
@@ -117,77 +117,98 @@ typedef struct _cairo_perf_timer
struct timeval tv_start;
struct timeval tv_stop;
#endif
-} cairo_perf_timer_t;
-static cairo_perf_timer_t timer;
+ cairo_perf_timer_synchronize_t synchronize;
+ void *synchronize_closure;
+
+ cairo_perf_ticks_t tps;
+};
+
+
+cairo_perf_timer_t *
+cairo_perf_timer_create (void)
+{
+ cairo_perf_timer_t *timer = xmalloc (sizeof (cairo_perf_timer_t));
+
+ timer->synchronize = NULL;
+ timer->synchronize_closure = NULL;
+
+ timer->tps = 0;
+
+ return timer;
+}
+
+void
+cairo_perf_timer_destroy (cairo_perf_timer_t *timer)
+{
+ free (timer);
+}
-static cairo_perf_timer_synchronize_t cairo_perf_timer_synchronize = NULL;
-static void *cairo_perf_timer_synchronize_closure = NULL;
void
-cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
+cairo_perf_timer_set_synchronize (cairo_perf_timer_t *timer,
+ cairo_perf_timer_synchronize_t synchronize,
void *closure)
{
- cairo_perf_timer_synchronize = synchronize;
- cairo_perf_timer_synchronize_closure = closure;
+ timer->synchronize = synchronize;
+ timer->synchronize_closure = closure;
}
void
-cairo_perf_timer_start (void) {
- if (cairo_perf_timer_synchronize)
- cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
+cairo_perf_timer_start (cairo_perf_timer_t *timer) {
+ if (timer->synchronize)
+ timer->synchronize (timer->synchronize_closure);
#ifdef OIL_STAMP
- timer.start = OIL_STAMP ();
+ timer->start = OIL_STAMP ();
#else
- gettimeofday (&timer.tv_start, NULL);
+ gettimeofday (&timer->tv_start, NULL);
#endif
}
void
-cairo_perf_timer_stop (void) {
- if (cairo_perf_timer_synchronize)
- cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
+cairo_perf_timer_stop (cairo_perf_timer_t *timer) {
+ if (timer->synchronize)
+ timer->synchronize (timer->synchronize_closure);
#ifdef OIL_STAMP
- timer.stop = OIL_STAMP ();
+ timer->stop = OIL_STAMP ();
#else
- gettimeofday (&timer.tv_stop, NULL);
+ gettimeofday (&timer->tv_stop, NULL);
#endif
}
cairo_perf_ticks_t
-cairo_perf_timer_elapsed (void) {
+cairo_perf_timer_elapsed (cairo_perf_timer_t *timer) {
cairo_perf_ticks_t ticks;
#ifdef OIL_STAMP
/* Handle 32-bit wraparound of timer value */
- if (timer.stop < timer.start)
- timer.stop += 0x100000000ll;
- ticks = (timer.stop - timer.start);
+ if (timer->stop < timer->start)
+ timer->stop += 0x100000000ll;
+ ticks = (timer->stop - timer->start);
#else
- ticks = (timer.tv_stop.tv_sec - timer.tv_start.tv_sec) * 1000000;
- ticks += (timer.tv_stop.tv_usec - timer.tv_start.tv_usec);
+ ticks = (timer->tv_stop.tv_sec - timer->tv_start.tv_sec) * 1000000;
+ ticks += (timer->tv_stop.tv_usec - timer->tv_start.tv_usec);
#endif
return ticks;
}
cairo_perf_ticks_t
-cairo_perf_ticks_per_second (void) {
+cairo_perf_ticks_per_second (cairo_perf_timer_t *timer) {
#ifdef OIL_STAMP
- static cairo_perf_ticks_t tps = 0;
/* XXX: This is obviously not stable in light of changing CPU speed. */
- if (tps == 0) {
+ if (timer->tps == 0) {
struct timeval tv_start, tv_stop;
double tv_elapsed;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
gettimeofday (&tv_start, NULL);
usleep (20000);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
gettimeofday (&tv_stop, NULL);
tv_elapsed = ((tv_stop.tv_sec - tv_start.tv_sec) +
+ (tv_stop.tv_usec - tv_start.tv_usec) / 1000000.0);
- tps = round (cairo_perf_timer_elapsed () / tv_elapsed);
+ timer->tps = round (cairo_perf_timer_elapsed (timer) / tv_elapsed);
}
- return tps;
+ return timer->tps;
#else
/* For gettimeofday the units are micro-seconds */
return 1000000;
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 44e842b..176e346 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -33,6 +33,9 @@
#include <unistd.h>
/* For basename */
#include <libgen.h>
+/* For threading */
+#include <pthread.h>
+#include <errno.h>
#ifdef HAVE_SCHED_H
#include <sched.h>
@@ -42,13 +45,11 @@
#define CAIRO_PERF_LOW_STD_DEV 0.03
#define CAIRO_PERF_STABLE_STD_DEV_COUNT 5
-typedef struct _cairo_perf_case {
+static 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[];
+} perf_cases[];
/* Some targets just aren't that interesting for performance testing,
* (not least because many of these surface types use a meta-surface
@@ -105,6 +106,7 @@ _content_to_string (cairo_content_t content)
void
cairo_perf_run (cairo_perf_t *perf,
+ cairo_t *cr,
const char *name,
cairo_perf_func_t perf_func)
{
@@ -142,12 +144,12 @@ cairo_perf_run (cairo_perf_t *perf,
/* We run one iteration in advance to warm caches, etc. */
cairo_perf_yield ();
- (perf_func) (perf->cr, perf->size, perf->size);
+ (perf_func) (perf->timer, cr, perf->size, perf->size);
low_std_dev_count = 0;
for (i =0; i < perf->iterations; i++) {
cairo_perf_yield ();
- times[i] = (perf_func) (perf->cr, perf->size, perf->size);
+ times[i] = (perf_func) (perf->timer, cr, perf->size, perf->size);
if (perf->raw) {
if (i == 0)
@@ -155,7 +157,7 @@ cairo_perf_run (cairo_perf_t *perf,
perf->target->name,
_content_to_string (perf->target->content),
name, perf->size,
- cairo_perf_ticks_per_second () / 1000.0);
+ cairo_perf_ticks_per_second (perf->timer) / 1000.0);
printf (" %lld", times[i]);
} else {
if (i > 0) {
@@ -184,8 +186,8 @@ cairo_perf_run (cairo_perf_t *perf,
printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
stats.min_ticks,
- (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
- (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+ (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (perf->timer),
+ (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (perf->timer),
stats.std_dev * 100.0, stats.iterations);
}
@@ -228,9 +230,10 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
perf->list_only = FALSE;
perf->names = NULL;
perf->num_names = 0;
+ perf->threads = 0;
while (1) {
- c = getopt (argc, argv, "i:lr");
+ c = getopt (argc, argv, "it:lr");
if (c == -1)
break;
@@ -244,6 +247,14 @@ parse_options (cairo_perf_t *perf, int argc, char *argv[])
exit (1);
}
break;
+ case 't':
+ perf->threads = strtoul (optarg, &end, 10);
+ if (*end != '\0') {
+ fprintf (stderr, "Invalid argument for -t (not an integer): %s\n",
+ optarg);
+ exit (1);
+ }
+ break;
case 'l':
perf->list_only = TRUE;
break;
@@ -298,79 +309,129 @@ check_cpu_affinity(void)
#endif
}
-int
-main (int argc, char *argv[])
+static void *
+run_perf_case (void *arg)
{
- int i, j;
- cairo_perf_case_t *perf_case;
- cairo_perf_t perf;
- const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
- cairo_boilerplate_target_t *target;
+ cairo_perf_t *perf = arg;
+ const cairo_boilerplate_target_t *target = perf->target;
cairo_surface_t *surface;
+ cairo_t *cr;
+ void *closure = NULL;
+ void *result = NULL;
+
+ surface = (target->create_surface) (NULL,
+ target->content,
+ perf->size, perf->size,
+ CAIRO_BOILERPLATE_MODE_PERF,
+ &closure);
+ cairo_perf_timer_set_synchronize (perf->timer,
+ target->synchronize,
+ closure);
+
+ cr = cairo_create (surface);
+
+ perf->kase->run (perf, cr, perf->size, perf->size);
+
+ if (cairo_status (cr)) {
+ fprintf (stderr, "Error: Test left cairo in an error state: %s\n",
+ cairo_status_to_string (cairo_status (cr)));
+ result = (void *)0x1;
+ }
- parse_options (&perf, argc, argv);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
- if (check_cpu_affinity()) {
- fputs(
- "NOTICE: cairo-perf and the X server should be bound to CPUs (either the same\n"
- "or separate) on SMP systems. Not doing so causes random results when the X\n"
- "server is moved to or from cairo-perf's CPU during the benchmarks:\n"
- "\n"
- " $ sudo taskset -cp 0 $(pidof X)\n"
- " $ taskset -cp 1 $$\n"
- "\n"
- "See taskset(1) for information about changing CPU affinity.\n",
- stderr);
- }
+ if (target->cleanup)
+ target->cleanup (closure);
+
+ return result;
+}
+
+static void *
+run_perf_cases (void *arg)
+{
+ const cairo_perf_t *options = arg;
+ cairo_perf_t perf = *options;
+ const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
+ int i, j;
+ long err = 0;
+
+ perf.timer = cairo_perf_timer_create ();
for (i = 0; targets[i].name; i++) {
- perf.target = target = &targets[i];
+ perf.target = &targets[i];
perf.test_number = 0;
- if (! target_is_measurable (target))
+ 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;
for (j = 0; perf_cases[j].run; j++) {
+ perf.kase = &perf_cases[j];
- perf_case = &perf_cases[j];
-
- for (perf.size = perf_case->min_size;
- perf.size <= perf_case->max_size;
+ for (perf.size = perf.kase->min_size;
+ perf.size <= perf.kase->max_size;
perf.size *= 2)
{
- surface = (target->create_surface) (NULL,
- target->content,
- perf.size, perf.size,
- CAIRO_BOILERPLATE_MODE_PERF,
- &target->closure);
- cairo_perf_timer_set_synchronize (target->synchronize,
- target->closure);
-
- perf.cr = cairo_create (surface);
-
- perf_case->run (&perf, perf.cr, perf.size, perf.size);
-
- if (cairo_status (perf.cr)) {
- fprintf (stderr, "Error: Test left cairo in an error state: %s\n",
- cairo_status_to_string (cairo_status (perf.cr)));
- exit (1);
- }
+ err += !! run_perf_case (&perf);
+ }
+ }
+ }
- cairo_destroy (perf.cr);
- cairo_surface_destroy (surface);
+ cairo_perf_timer_destroy (perf.timer);
- if (target->cleanup)
- target->cleanup (target->closure);
+ return (void *) err;
+}
+
+int
+main (int argc, char *argv[])
+{
+ cairo_perf_t perf;
+ long err;
+
+ parse_options (&perf, argc, argv);
+
+ if (perf.threads) {
+ unsigned int i;
+ pthread_t *threads = xmalloc (sizeof (pthread_t) * perf.threads);
+ void *result;
+ for (i = 0; i < perf.threads; i++) {
+ if (pthread_create (&threads[i], NULL,
+ run_perf_cases, &perf) < 0) {
+ fprintf (stderr, "Unable to create thread: %s\n",
+ strerror (errno));
+ exit (1);
}
}
+ err = 0;
+ for (i = 0; i < perf.threads; i++) {
+ pthread_join (threads[i], &result);
+ err += !! result;
+ }
+ free (threads);
+ } else {
+ if (check_cpu_affinity()) {
+ fputs(
+ "NOTICE: cairo-perf and the X server should be bound to CPUs (either the same\n"
+ "or separate) on SMP systems. Not doing so causes random results when the X\n"
+ "server is moved to or from cairo-perf's CPU during the benchmarks:\n"
+ "\n"
+ " $ sudo taskset -cp 0 $(pidof X)\n"
+ " $ taskset -cp 1 $$\n"
+ "\n"
+ "See taskset(1) for information about changing CPU affinity.\n",
+ stderr);
+ }
+
+ err = (long) run_perf_cases (&perf);
}
- return 0;
+ return !! err;
}
-cairo_perf_case_t perf_cases[] = {
+static cairo_perf_case_t perf_cases[] = {
{ paint, 256, 512},
{ fill, 64, 256},
{ stroke, 64, 256},
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 1fef997..9240e81 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -35,34 +35,43 @@ typedef uint64_t cairo_perf_ticks_t;
#include "cairo-stats.h"
/* timers */
+typedef struct _cairo_perf_timer cairo_perf_timer_t;
+cairo_perf_timer_t *
+cairo_perf_timer_create (void);
void
-cairo_perf_timer_start (void);
+cairo_perf_timer_destroy (cairo_perf_timer_t *timer);
+void
+cairo_perf_timer_start (cairo_perf_timer_t *timer);
void
-cairo_perf_timer_stop (void);
+cairo_perf_timer_stop (cairo_perf_timer_t *timer);
typedef void
(*cairo_perf_timer_synchronize_t) (void *closure);
void
-cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
+cairo_perf_timer_set_synchronize (cairo_perf_timer_t *timer,
+ cairo_perf_timer_synchronize_t synchronize,
void *closure);
cairo_perf_ticks_t
-cairo_perf_timer_elapsed (void);
+cairo_perf_timer_elapsed (cairo_perf_timer_t *timer);
cairo_perf_ticks_t
-cairo_perf_ticks_per_second (void);
+cairo_perf_ticks_per_second (cairo_perf_timer_t *timer);
/* yield */
void
cairo_perf_yield (void);
+typedef struct _cairo_perf_case cairo_perf_case_t;
+
/* running a test case */
typedef struct _cairo_perf {
/* Options from command-line */
+ unsigned int threads;
unsigned int iterations;
cairo_bool_t exact_iterations;
cairo_bool_t raw;
@@ -71,22 +80,25 @@ typedef struct _cairo_perf {
unsigned int num_names;
/* Stuff used internally */
+ cairo_perf_case_t *kase;
cairo_boilerplate_target_t *target;
+ cairo_perf_timer_t *timer;
unsigned int test_number;
unsigned int size;
- cairo_t *cr;
} cairo_perf_t;
typedef cairo_perf_ticks_t
-(*cairo_perf_func_t) (cairo_t *cr, int width, int height);
+(*cairo_perf_func_t) (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height);
void
cairo_perf_run (cairo_perf_t *perf,
+ cairo_t *cr,
const char *name,
cairo_perf_func_t perf_func);
void
cairo_perf_cover_sources_and_operators (cairo_perf_t *perf,
+ cairo_t *cr,
const char *name,
cairo_perf_func_t perf_func);
diff --git a/perf/fill.c b/perf/fill.c
index 2a41355..32e0765 100644
--- a/perf/fill.c
+++ b/perf/fill.c
@@ -26,24 +26,24 @@
#include "cairo-perf.h"
static cairo_perf_ticks_t
-do_fill (cairo_t *cr, int width, int height)
+do_fill (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_arc (cr,
width/2.0, height/2.0,
width/3.0,
0, 2 * M_PI);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_fill (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_cover_sources_and_operators (perf, "fill", do_fill);
+ cairo_perf_cover_sources_and_operators (perf, cr, "fill", do_fill);
}
diff --git a/perf/long-lines.c b/perf/long-lines.c
index 62e8e16..85d1d80 100644
--- a/perf/long-lines.c
+++ b/perf/long-lines.c
@@ -40,7 +40,7 @@ typedef enum { LONG_LINES_UNCROPPED, LONG_LINES_CROPPED } long_lines_crop_t;
#define LONG_FACTOR 50.0
static cairo_perf_ticks_t
-do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
+do_long_lines (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height, long_lines_crop_t crop)
{
int i;
double x, y, dx, dy, min_x, min_y, max_x, max_y;
@@ -67,7 +67,7 @@ do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
dx = outer_width / NUM_LINES;
dy = outer_height / NUM_LINES;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
for (i = 0; i < NUM_LINES; i++) {
cairo_move_to (cr, 0, 0);
@@ -90,28 +90,28 @@ do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
y += dy;
}
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
cairo_restore (cr);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
static cairo_perf_ticks_t
-long_lines_uncropped (cairo_t *cr, int width, int height)
+long_lines_uncropped (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return do_long_lines (cr, width, height, LONG_LINES_UNCROPPED);
+ return do_long_lines (timer, cr, width, height, LONG_LINES_UNCROPPED);
}
static cairo_perf_ticks_t
-long_lines_cropped (cairo_t *cr, int width, int height)
+long_lines_cropped (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return do_long_lines (cr, width, height, LONG_LINES_CROPPED);
+ return do_long_lines (timer, cr, width, height, LONG_LINES_CROPPED);
}
void
long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
- cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
+ cairo_perf_run (perf, cr, "long-lines-uncropped", long_lines_uncropped);
+ cairo_perf_run (perf, cr, "long-lines-cropped", long_lines_cropped);
}
diff --git a/perf/mosaic.c b/perf/mosaic.c
index 7172a9d..ad6b148 100644
--- a/perf/mosaic.c
+++ b/perf/mosaic.c
@@ -93,7 +93,7 @@ mosaic_next_path (cairo_t *cr, struct mosaic_region_iter *iter)
}
static cairo_perf_ticks_t
-mosaic_perform(cairo_t *cr, unsigned flags, int width, int height)
+mosaic_perform(cairo_perf_timer_t *timer, cairo_t *cr, unsigned flags, int width, int height)
{
struct mosaic_region_iter iter;
@@ -118,7 +118,7 @@ mosaic_perform(cairo_t *cr, unsigned flags, int width, int height)
* tessellating them as dictated by the flags. */
mosaic_region_iter_init (&iter, flags & MOSAIC_CURVE_TO);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
while (mosaic_next_path (cr, &iter)) {
if (flags & MOSAIC_FILL) {
cairo_fill (cr);
@@ -129,40 +129,40 @@ mosaic_perform(cairo_t *cr, unsigned flags, int width, int height)
cairo_in_fill (cr, x, y);
}
}
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
static cairo_perf_ticks_t
-mosaic_fill_curves (cairo_t *cr, int width, int height)
+mosaic_fill_curves (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return mosaic_perform (cr, MOSAIC_FILL | MOSAIC_CURVE_TO, width, height);
+ return mosaic_perform (timer, cr, MOSAIC_FILL | MOSAIC_CURVE_TO, width, height);
}
static cairo_perf_ticks_t
-mosaic_fill_lines (cairo_t *cr, int width, int height)
+mosaic_fill_lines (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return mosaic_perform (cr, MOSAIC_FILL | MOSAIC_LINE_TO, width, height);
+ return mosaic_perform (timer, cr, MOSAIC_FILL | MOSAIC_LINE_TO, width, height);
}
static cairo_perf_ticks_t
-mosaic_tessellate_lines (cairo_t *cr, int width, int height)
+mosaic_tessellate_lines (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return mosaic_perform (cr, MOSAIC_TESSELLATE | MOSAIC_LINE_TO, width, height);
+ return mosaic_perform (timer, cr, MOSAIC_TESSELLATE | MOSAIC_LINE_TO, width, height);
}
static cairo_perf_ticks_t
-mosaic_tessellate_curves (cairo_t *cr, int width, int height)
+mosaic_tessellate_curves (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return mosaic_perform (cr, MOSAIC_TESSELLATE | MOSAIC_CURVE_TO, width, height);
+ return mosaic_perform (timer, cr, MOSAIC_TESSELLATE | MOSAIC_CURVE_TO, width, height);
}
void
mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "mosaic_fill_curves", mosaic_fill_curves);
- cairo_perf_run (perf, "mosaic_fill_lines", mosaic_fill_lines);
- cairo_perf_run (perf, "mosaic_tessellate_curves", mosaic_tessellate_curves);
- cairo_perf_run (perf, "mosaic_tessellate_lines", mosaic_tessellate_lines);
+ cairo_perf_run (perf, cr, "mosaic_fill_curves", mosaic_fill_curves);
+ cairo_perf_run (perf, cr, "mosaic_fill_lines", mosaic_fill_lines);
+ cairo_perf_run (perf, cr, "mosaic_tessellate_curves", mosaic_tessellate_curves);
+ cairo_perf_run (perf, cr, "mosaic_tessellate_lines", mosaic_tessellate_lines);
}
diff --git a/perf/paint.c b/perf/paint.c
index 6f75016..fad1743 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -26,19 +26,19 @@
#include "cairo-perf.h"
static cairo_perf_ticks_t
-do_paint (cairo_t *cr, int width, int height)
+do_paint (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_paint (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_cover_sources_and_operators (perf, "paint", do_paint);
+ cairo_perf_cover_sources_and_operators (perf, cr, "paint", do_paint);
}
diff --git a/perf/pattern_create_radial.c b/perf/pattern_create_radial.c
index 09f15a8..bc37175 100644
--- a/perf/pattern_create_radial.c
+++ b/perf/pattern_create_radial.c
@@ -56,12 +56,12 @@ generate_double_in_range (double min, double max)
}
static cairo_perf_ticks_t
-do_pattern_create_radial (cairo_t *cr, int width, int height)
+do_pattern_create_radial (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
int i;
cairo_pattern_t *pattern;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
for (i = 0; i < RADIALS_COUNT; i++)
{
@@ -72,9 +72,9 @@ do_pattern_create_radial (cairo_t *cr, int width, int height)
cairo_pattern_destroy (pattern);
}
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
@@ -93,6 +93,7 @@ pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
radials[i].radius1 = generate_double_in_range (0.0, 1000.0);
}
- cairo_perf_run (perf, "pattern_create_radial",
- do_pattern_create_radial);
+ cairo_perf_run (perf, cr,
+ "pattern_create_radial",
+ do_pattern_create_radial);
}
diff --git a/perf/rectangles.c b/perf/rectangles.c
index 9fa89f5..1933e57 100644
--- a/perf/rectangles.c
+++ b/perf/rectangles.c
@@ -35,11 +35,11 @@ static struct
} rects[RECTANGLE_COUNT];
static cairo_perf_ticks_t
-do_rectangles (cairo_t *cr, int width, int height)
+do_rectangles (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
int i;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
for (i = 0; i < RECTANGLE_COUNT; i++)
{
@@ -48,9 +48,9 @@ do_rectangles (cairo_t *cr, int width, int height)
cairo_fill (cr);
}
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
@@ -67,5 +67,5 @@ rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
rects[i].height = (rand () % (height / 10)) + 1;
}
- cairo_perf_run (perf, "rectangles", do_rectangles);
+ cairo_perf_run (perf, cr, "rectangles", do_rectangles);
}
diff --git a/perf/stroke.c b/perf/stroke.c
index 0b4ea8e..bf8b98b 100644
--- a/perf/stroke.c
+++ b/perf/stroke.c
@@ -26,7 +26,7 @@
#include "cairo-perf.h"
static cairo_perf_ticks_t
-do_stroke (cairo_t *cr, int width, int height)
+do_stroke (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_arc (cr,
width/2.0, height/2.0,
@@ -34,18 +34,18 @@ do_stroke (cairo_t *cr, int width, int height)
0, 2 * M_PI);
cairo_close_path (cr);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_set_line_width (cr, width/5.0);
cairo_stroke (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke);
+ cairo_perf_cover_sources_and_operators (perf, cr, "stroke", do_stroke);
}
diff --git a/perf/subimage_copy.c b/perf/subimage_copy.c
index 54f596f..44d2bb3 100644
--- a/perf/subimage_copy.c
+++ b/perf/subimage_copy.c
@@ -35,18 +35,18 @@
*/
static cairo_perf_ticks_t
-do_subimage_copy (cairo_t *cr, int width, int height)
+do_subimage_copy (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_rectangle (cr, 2, 2, 4, 4);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_fill (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
@@ -67,5 +67,5 @@ subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
cairo_set_source_surface (cr, image, 0, 0);
cairo_surface_destroy (image);
- cairo_perf_run (perf, "subimage_copy", do_subimage_copy);
+ cairo_perf_run (perf, cr, "subimage_copy", do_subimage_copy);
}
diff --git a/perf/tessellate.c b/perf/tessellate.c
index fc97db7..1bd6d40 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -99,14 +99,14 @@ point_t points[300] = {
};
static cairo_perf_ticks_t
-do_tessellate (cairo_t *cr, int num_points)
+do_tessellate (cairo_perf_timer_t *timer, cairo_t *cr, int num_points)
{
int i;
for (i=0; i < num_points; i++)
cairo_line_to (cr, points[i].x, points[i].y);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
/* We'd like to measure just tessellation without
* rasterization. For now, we can do that with cairo_in_fill. But
@@ -115,37 +115,37 @@ do_tessellate (cairo_t *cr, int num_points)
* include tessellation. */
cairo_in_fill (cr, 50, 50);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
cairo_new_path (cr);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
static cairo_perf_ticks_t
-tessellate_16 (cairo_t *cr, int width, int height)
+tessellate_16 (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return do_tessellate (cr, 16);
+ return do_tessellate (timer, cr, 16);
}
static cairo_perf_ticks_t
-tessellate_64 (cairo_t *cr, int width, int height)
+tessellate_64 (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return do_tessellate (cr, 64);
+ return do_tessellate (timer, cr, 64);
}
static cairo_perf_ticks_t
-tessellate_256 (cairo_t *cr, int width, int height)
+tessellate_256 (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
- return do_tessellate (cr, 256);
+ return do_tessellate (timer, cr, 256);
}
void
tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "tessellate-16", tessellate_16);
- cairo_perf_run (perf, "tessellate-64", tessellate_64);
- cairo_perf_run (perf, "tessellate-256", tessellate_256);
+ cairo_perf_run (perf, cr, "tessellate-16", tessellate_16);
+ cairo_perf_run (perf, cr, "tessellate-64", tessellate_64);
+ cairo_perf_run (perf, cr, "tessellate-256", tessellate_256);
}
#if 0
diff --git a/perf/text.c b/perf/text.c
index de5e0cd..d547b95 100644
--- a/perf/text.c
+++ b/perf/text.c
@@ -26,14 +26,14 @@
#include "cairo-perf.h"
static cairo_perf_ticks_t
-do_text (cairo_t *cr, int width, int height)
+do_text (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
const char text[] = "the jay, pig, fox, zebra and my wolves quack";
int len = strlen (text);
double x, y;
int i = 0;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_set_font_size (cr, 9);
do {
@@ -49,13 +49,13 @@ do_text (cairo_t *cr, int width, int height)
i = 0;
} while (y < height);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
text (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_cover_sources_and_operators (perf, "text", do_text);
+ cairo_perf_cover_sources_and_operators (perf, cr, "text", do_text);
}
diff --git a/perf/unaligned-clip.c b/perf/unaligned-clip.c
index c7b9d21..f2a4c1d 100644
--- a/perf/unaligned-clip.c
+++ b/perf/unaligned-clip.c
@@ -29,11 +29,11 @@
#include "cairo-perf.h"
static cairo_perf_ticks_t
-do_unaligned_clip (cairo_t *cr, int width, int height)
+do_unaligned_clip (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
cairo_save (cr);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
/* First a triangular clip that obviously isn't along device-pixel
* boundaries. */
cairo_move_to (cr, 50, 50);
@@ -52,15 +52,15 @@ do_unaligned_clip (cairo_t *cr, int width, int height)
cairo_close_path (cr);
cairo_clip (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
cairo_restore (cr);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
+ cairo_perf_run (perf, cr, "unaligned_clip", do_unaligned_clip);
}
diff --git a/perf/world-map.c b/perf/world-map.c
index eef3619..9509844 100644
--- a/perf/world-map.c
+++ b/perf/world-map.c
@@ -47,12 +47,12 @@ typedef struct _wm_element {
#include "world-map.h"
static cairo_perf_ticks_t
-do_world_map (cairo_t *cr, int width, int height)
+do_world_map (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
const wm_element_t *e;
double cx, cy;
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_set_source_rgb (cr, .68, .85, .90); /* lightblue */
cairo_rectangle (cr, 0, 0, 800, 400);
@@ -95,13 +95,13 @@ do_world_map (cairo_t *cr, int width, int height)
e++;
}
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "world_map", do_world_map);
+ cairo_perf_run (perf, cr, "world_map", do_world_map);
}
diff --git a/perf/zrusin.c b/perf/zrusin.c
index 6840775..a759764 100644
--- a/perf/zrusin.c
+++ b/perf/zrusin.c
@@ -45,11 +45,11 @@ zrusin_another_path (cairo_t *cr)
}
static cairo_perf_ticks_t
-zrusin_another_tessellate (cairo_t *cr, int width, int height)
+zrusin_another_tessellate (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
zrusin_another_path (cr);
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
/* We'd like to measure just tessellation without
* rasterization. For now, we can do that with cairo_in_fill. But
@@ -58,33 +58,37 @@ zrusin_another_tessellate (cairo_t *cr, int width, int height)
* include tessellation. */
cairo_in_fill (cr, 50, 50);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
cairo_new_path (cr);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
static cairo_perf_ticks_t
-zrusin_another_fill (cairo_t *cr, int width, int height)
+zrusin_another_fill (cairo_perf_timer_t *timer, cairo_t *cr, int width, int height)
{
zrusin_another_path (cr);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.8); /* blue */
- cairo_perf_timer_start ();
+ cairo_perf_timer_start (timer);
cairo_fill (cr);
- cairo_perf_timer_stop ();
+ cairo_perf_timer_stop (timer);
cairo_new_path (cr);
- return cairo_perf_timer_elapsed ();
+ return cairo_perf_timer_elapsed (timer);
}
void
zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
- cairo_perf_run (perf, "zrusin_another_tessellate", zrusin_another_tessellate);
- cairo_perf_run (perf, "zrusin_another_fill", zrusin_another_fill);
+ cairo_perf_run (perf, cr,
+ "zrusin_another_tessellate",
+ zrusin_another_tessellate);
+ cairo_perf_run (perf, cr,
+ "zrusin_another_fill",
+ zrusin_another_fill);
}
More information about the cairo
mailing list