2006-09-14 12:59:31 -07:00
|
|
|
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
2006-08-31 07:19:05 -07:00
|
|
|
/*
|
2006-08-31 10:39:24 -07:00
|
|
|
* Copyright © 2006 Mozilla Corporation
|
2006-08-31 07:19:05 -07:00
|
|
|
* Copyright © 2006 Red Hat, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
|
|
|
* and its documentation for any purpose is hereby granted without
|
|
|
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
|
|
|
* and that both that copyright notice and this permission notice
|
|
|
|
|
* appear in supporting documentation, and that the name of
|
2006-08-31 10:39:24 -07:00
|
|
|
* the authors not be used in advertising or publicity pertaining to
|
2006-08-31 07:19:05 -07:00
|
|
|
* distribution of the software without specific, written prior
|
2006-08-31 10:39:24 -07:00
|
|
|
* permission. The authors make no representations about the
|
2006-08-31 07:19:05 -07:00
|
|
|
* suitability of this software for any purpose. It is provided "as
|
|
|
|
|
* is" without express or implied warranty.
|
|
|
|
|
*
|
2006-08-31 10:39:24 -07:00
|
|
|
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
2006-08-31 07:19:05 -07:00
|
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
2006-08-31 10:39:24 -07:00
|
|
|
* FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL,
|
2006-08-31 07:19:05 -07:00
|
|
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
|
|
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
|
|
|
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*
|
2006-08-31 10:39:24 -07:00
|
|
|
* Authors: Vladimir Vukicevic <vladimir@pobox.com>
|
|
|
|
|
* Carl Worth <cworth@cworth.org>
|
2006-08-31 07:19:05 -07:00
|
|
|
*/
|
|
|
|
|
|
2008-09-02 21:50:08 -04:00
|
|
|
#define _GNU_SOURCE 1 /* for sched_getaffinity() */
|
|
|
|
|
|
2006-08-31 07:19:05 -07:00
|
|
|
#include "cairo-perf.h"
|
2008-10-16 11:56:19 +01:00
|
|
|
#include "cairo-stats.h"
|
2006-08-31 07:19:05 -07:00
|
|
|
|
2008-02-01 18:45:59 -08:00
|
|
|
#include "cairo-boilerplate-getopt.h"
|
2007-04-30 19:20:56 -04:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
/* For basename */
|
2007-04-30 19:20:56 -04:00
|
|
|
#ifdef HAVE_LIBGEN_H
|
2006-11-07 01:29:38 -08:00
|
|
|
#include <libgen.h>
|
2007-04-30 19:20:56 -04:00
|
|
|
#endif
|
2006-11-07 01:29:38 -08:00
|
|
|
|
2007-04-30 16:05:36 +01:00
|
|
|
#if HAVE_FCFINI
|
|
|
|
|
#include <fontconfig/fontconfig.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2007-03-16 20:43:29 +01:00
|
|
|
#ifdef HAVE_SCHED_H
|
|
|
|
|
#include <sched.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-10-12 15:12:01 -07:00
|
|
|
#define CAIRO_PERF_ITERATIONS_DEFAULT 100
|
|
|
|
|
#define CAIRO_PERF_LOW_STD_DEV 0.03
|
|
|
|
|
#define CAIRO_PERF_STABLE_STD_DEV_COUNT 5
|
|
|
|
|
|
2006-09-29 16:42:44 -07:00
|
|
|
typedef struct _cairo_perf_case {
|
|
|
|
|
CAIRO_PERF_DECL (*run);
|
2006-08-31 07:19:05 -07:00
|
|
|
unsigned int min_size;
|
|
|
|
|
unsigned int max_size;
|
2006-09-29 16:42:44 -07:00
|
|
|
} cairo_perf_case_t;
|
2006-08-31 07:19:05 -07:00
|
|
|
|
2008-08-19 11:52:38 +01:00
|
|
|
const cairo_perf_case_t perf_cases[];
|
2006-08-31 07:19:05 -07:00
|
|
|
|
2006-08-31 08:53:58 -07:00
|
|
|
/* Some targets just aren't that interesting for performance testing,
|
|
|
|
|
* (not least because many of these surface types use a meta-surface
|
|
|
|
|
* and as such defer the "real" rendering to later, so our timing
|
|
|
|
|
* loops wouldn't count the real work, just the recording by the
|
|
|
|
|
* meta-surface. */
|
|
|
|
|
static cairo_bool_t
|
2006-09-09 14:55:57 -07:00
|
|
|
target_is_measurable (cairo_boilerplate_target_t *target)
|
2006-08-31 08:53:58 -07:00
|
|
|
{
|
|
|
|
|
switch (target->expected_type) {
|
|
|
|
|
case CAIRO_SURFACE_TYPE_IMAGE:
|
2006-08-31 11:53:16 -07:00
|
|
|
if (strcmp (target->name, "pdf") == 0 ||
|
|
|
|
|
strcmp (target->name, "ps") == 0)
|
2006-08-31 08:53:58 -07:00
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
case CAIRO_SURFACE_TYPE_XLIB:
|
2007-08-24 14:16:43 +01:00
|
|
|
if (strcmp (target->name, "xlib-fallback") == 0)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2006-08-31 08:53:58 -07:00
|
|
|
case CAIRO_SURFACE_TYPE_XCB:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_GLITZ:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_QUARTZ:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_WIN32:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_BEOS:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_DIRECTFB:
|
2006-11-03 15:32:57 -08:00
|
|
|
#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR > 2)
|
2006-09-29 16:42:44 -07:00
|
|
|
case CAIRO_SURFACE_TYPE_OS2:
|
2006-11-03 14:58:30 -08:00
|
|
|
#endif
|
2006-08-31 08:53:58 -07:00
|
|
|
return TRUE;
|
|
|
|
|
case CAIRO_SURFACE_TYPE_PDF:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_PS:
|
|
|
|
|
case CAIRO_SURFACE_TYPE_SVG:
|
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-31 12:34:21 -07:00
|
|
|
static const char *
|
2007-10-19 23:25:57 +01:00
|
|
|
_content_to_string (cairo_content_t content, cairo_bool_t similar)
|
2006-08-31 12:34:21 -07:00
|
|
|
{
|
2007-10-19 23:25:57 +01:00
|
|
|
switch (content|similar) {
|
2006-08-31 12:34:21 -07:00
|
|
|
case CAIRO_CONTENT_COLOR:
|
|
|
|
|
return "rgb";
|
2007-10-19 23:25:57 +01:00
|
|
|
case CAIRO_CONTENT_COLOR|1:
|
|
|
|
|
return "rgb&";
|
2006-08-31 12:34:21 -07:00
|
|
|
case CAIRO_CONTENT_ALPHA:
|
|
|
|
|
return "a";
|
2007-10-19 23:25:57 +01:00
|
|
|
case CAIRO_CONTENT_ALPHA|1:
|
|
|
|
|
return "a&";
|
2006-08-31 12:34:21 -07:00
|
|
|
case CAIRO_CONTENT_COLOR_ALPHA:
|
|
|
|
|
return "rgba";
|
2007-10-19 23:25:57 +01:00
|
|
|
case CAIRO_CONTENT_COLOR_ALPHA|1:
|
|
|
|
|
return "rgba&";
|
2006-08-31 12:34:21 -07:00
|
|
|
default:
|
|
|
|
|
return "<unknown_content>";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:25:57 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
cairo_perf_has_similar (cairo_perf_t *perf)
|
|
|
|
|
{
|
2009-06-02 09:00:21 +01:00
|
|
|
cairo_surface_t *target;
|
2007-10-19 23:25:57 +01:00
|
|
|
|
2009-06-02 09:00:21 +01:00
|
|
|
if (getenv ("CAIRO_TEST_SIMILAR") == NULL)
|
2009-01-30 10:22:47 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2007-10-19 23:25:57 +01:00
|
|
|
/* exclude the image backend */
|
2009-06-02 09:00:21 +01:00
|
|
|
target = cairo_get_target (perf->cr);
|
2007-10-19 23:25:57 +01:00
|
|
|
if (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_IMAGE)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 20:11:17 +00:00
|
|
|
cairo_bool_t
|
|
|
|
|
cairo_perf_can_run (cairo_perf_t *perf,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
if (perf->num_names == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < perf->num_names; i++)
|
|
|
|
|
if (strstr (name, perf->names[i]))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-29 16:42:44 -07:00
|
|
|
void
|
|
|
|
|
cairo_perf_run (cairo_perf_t *perf,
|
|
|
|
|
const char *name,
|
|
|
|
|
cairo_perf_func_t perf_func)
|
2006-08-31 07:19:05 -07:00
|
|
|
{
|
2006-09-29 16:42:44 -07:00
|
|
|
static cairo_bool_t first_run = TRUE;
|
2007-10-19 23:25:57 +01:00
|
|
|
unsigned int i, similar, has_similar;
|
2006-09-06 00:15:49 -07:00
|
|
|
cairo_perf_ticks_t *times;
|
2006-11-07 12:57:48 -08:00
|
|
|
cairo_stats_t stats = {0.0, 0.0};
|
2006-10-12 15:12:01 -07:00
|
|
|
int low_std_dev_count;
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
if (perf->list_only) {
|
|
|
|
|
printf ("%s\n", name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (first_run) {
|
|
|
|
|
if (perf->raw)
|
2009-05-30 16:50:17 +01:00
|
|
|
printf ("[ # ] %s.%-s %s %s %s ...\n",
|
2006-11-07 12:59:57 -08:00
|
|
|
"backend", "content", "test-size", "ticks-per-ms", "time(ticks)");
|
2006-11-07 01:29:38 -08:00
|
|
|
else
|
2009-05-30 16:50:17 +01:00
|
|
|
printf ("[ # ] %8s.%-4s %28s %8s %8s %5s %5s %s\n",
|
2006-11-07 01:29:38 -08:00
|
|
|
"backend", "content", "test-size", "min(ticks)", "min(ms)", "median(ms)",
|
|
|
|
|
"stddev.", "iterations");
|
|
|
|
|
first_run = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-08 09:00:56 +01:00
|
|
|
times = perf->times;
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2007-10-19 23:25:57 +01:00
|
|
|
has_similar = cairo_perf_has_similar (perf);
|
|
|
|
|
for (similar = 0; similar <= has_similar; similar++) {
|
|
|
|
|
/* We run one iteration in advance to warm caches, etc. */
|
2006-10-04 12:55:54 -07:00
|
|
|
cairo_perf_yield ();
|
2007-10-19 23:25:57 +01:00
|
|
|
if (similar)
|
2008-04-11 11:36:24 +01:00
|
|
|
cairo_push_group_with_content (perf->cr,
|
|
|
|
|
cairo_boilerplate_content (perf->target->content));
|
2007-10-19 23:25:57 +01:00
|
|
|
(perf_func) (perf->cr, perf->size, perf->size);
|
|
|
|
|
if (similar)
|
|
|
|
|
cairo_pattern_destroy (cairo_pop_group (perf->cr));
|
|
|
|
|
|
|
|
|
|
low_std_dev_count = 0;
|
|
|
|
|
for (i =0; i < perf->iterations; i++) {
|
|
|
|
|
cairo_perf_yield ();
|
|
|
|
|
if (similar)
|
2008-04-11 11:36:24 +01:00
|
|
|
cairo_push_group_with_content (perf->cr,
|
|
|
|
|
cairo_boilerplate_content (perf->target->content));
|
2007-10-19 23:25:57 +01:00
|
|
|
times[i] = (perf_func) (perf->cr, perf->size, perf->size);
|
|
|
|
|
if (similar)
|
|
|
|
|
cairo_pattern_destroy (cairo_pop_group (perf->cr));
|
|
|
|
|
|
|
|
|
|
if (perf->raw) {
|
|
|
|
|
if (i == 0)
|
2009-05-30 16:50:17 +01:00
|
|
|
printf ("[*] %s.%s %s.%d %g",
|
2007-10-19 23:25:57 +01:00
|
|
|
perf->target->name,
|
|
|
|
|
_content_to_string (perf->target->content, similar),
|
|
|
|
|
name, perf->size,
|
|
|
|
|
cairo_perf_ticks_per_second () / 1000.0);
|
2008-05-08 09:00:56 +01:00
|
|
|
printf (" %lld", (long long) times[i]);
|
2007-10-19 23:25:57 +01:00
|
|
|
} else if (! perf->exact_iterations) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
_cairo_stats_compute (&stats, times, i+1);
|
|
|
|
|
|
|
|
|
|
if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV)
|
|
|
|
|
{
|
|
|
|
|
low_std_dev_count++;
|
|
|
|
|
if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
low_std_dev_count = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
if (perf->raw) {
|
2007-10-19 23:25:57 +01:00
|
|
|
printf ("\n");
|
2006-11-07 01:29:38 -08:00
|
|
|
} else {
|
2007-10-19 23:25:57 +01:00
|
|
|
_cairo_stats_compute (&stats, times, i);
|
2009-05-30 16:50:17 +01:00
|
|
|
printf ("[%3d] %8s.%-5s %26s.%-3d ",
|
2007-10-19 23:25:57 +01:00
|
|
|
perf->test_number, perf->target->name,
|
|
|
|
|
_content_to_string (perf->target->content, similar),
|
|
|
|
|
name, perf->size);
|
|
|
|
|
|
|
|
|
|
printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
|
2008-05-08 09:00:56 +01:00
|
|
|
(long long) stats.min_ticks,
|
2007-10-19 23:25:57 +01:00
|
|
|
(stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
|
|
|
|
|
(stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
|
|
|
|
|
stats.std_dev * 100.0, stats.iterations);
|
2006-10-12 15:12:01 -07:00
|
|
|
}
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2007-10-19 23:25:57 +01:00
|
|
|
perf->test_number++;
|
2006-10-04 12:55:54 -07:00
|
|
|
}
|
2006-11-07 01:29:38 -08:00
|
|
|
}
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
static void
|
|
|
|
|
usage (const char *argv0)
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr,
|
|
|
|
|
"Usage: %s [-l] [-r] [-i iterations] [test-names ...]\n"
|
|
|
|
|
" %s -l\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Run the cairo performance test suite over the given tests (all by default)\n"
|
|
|
|
|
"The command-line arguments are interpreted as follows:\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" -r raw; display each time measurement instead of summary statistics\n"
|
|
|
|
|
" -i iterations; specify the number of iterations per test case\n"
|
|
|
|
|
" -l list only; just list selected test case names without executing\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"If test names are given they are used as sub-string matches so a command\n"
|
|
|
|
|
"such as \"cairo-perf text\" can be used to run all text test cases.\n",
|
|
|
|
|
argv0, argv0);
|
|
|
|
|
}
|
2006-09-29 16:42:44 -07:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
static void
|
|
|
|
|
parse_options (cairo_perf_t *perf, int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
int c;
|
2007-04-18 19:09:53 -04:00
|
|
|
const char *iters;
|
2006-11-07 01:29:38 -08:00
|
|
|
char *end;
|
|
|
|
|
|
2007-04-18 19:09:53 -04:00
|
|
|
if ((iters = getenv("CAIRO_PERF_ITERATIONS")) && *iters)
|
|
|
|
|
perf->iterations = strtol(iters, NULL, 0);
|
2006-11-07 01:29:38 -08:00
|
|
|
else
|
|
|
|
|
perf->iterations = CAIRO_PERF_ITERATIONS_DEFAULT;
|
2006-11-17 17:48:39 -08:00
|
|
|
perf->exact_iterations = 0;
|
2006-11-07 01:29:38 -08:00
|
|
|
|
|
|
|
|
perf->raw = FALSE;
|
|
|
|
|
perf->list_only = FALSE;
|
|
|
|
|
perf->names = NULL;
|
|
|
|
|
perf->num_names = 0;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
2008-02-01 18:45:59 -08:00
|
|
|
c = _cairo_getopt (argc, argv, "i:lr");
|
2006-11-07 01:29:38 -08:00
|
|
|
if (c == -1)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'i':
|
2006-11-17 17:48:39 -08:00
|
|
|
perf->exact_iterations = TRUE;
|
2006-11-07 01:29:38 -08:00
|
|
|
perf->iterations = strtoul (optarg, &end, 10);
|
|
|
|
|
if (*end != '\0') {
|
|
|
|
|
fprintf (stderr, "Invalid argument for -i (not an integer): %s\n",
|
|
|
|
|
optarg);
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
perf->list_only = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
perf->raw = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf (stderr, "Internal error: unhandled option: %c\n", c);
|
|
|
|
|
/* fall-through */
|
|
|
|
|
case '?':
|
|
|
|
|
usage (argv[0]);
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (optind < argc) {
|
|
|
|
|
perf->names = &argv[optind];
|
|
|
|
|
perf->num_names = argc - optind;
|
|
|
|
|
}
|
2006-09-29 16:42:44 -07:00
|
|
|
}
|
|
|
|
|
|
2007-03-16 20:43:29 +01:00
|
|
|
static int
|
|
|
|
|
check_cpu_affinity(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SCHED_GETAFFINITY
|
|
|
|
|
|
|
|
|
|
cpu_set_t affinity;
|
|
|
|
|
int i, cpu_count;
|
|
|
|
|
|
|
|
|
|
if (sched_getaffinity(0, sizeof(affinity), &affinity)) {
|
|
|
|
|
perror("sched_getaffinity");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i = 0, cpu_count = 0; i < CPU_SETSIZE; ++i) {
|
|
|
|
|
if (CPU_ISSET(i, &affinity))
|
|
|
|
|
++cpu_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cpu_count > 1) {
|
|
|
|
|
fputs(
|
|
|
|
|
"WARNING: cairo-perf has not been bound to a single CPU.\n",
|
|
|
|
|
stderr);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
#else
|
|
|
|
|
fputs(
|
|
|
|
|
"WARNING: Cannot check CPU affinity for this platform.\n",
|
|
|
|
|
stderr);
|
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2007-04-30 16:05:36 +01:00
|
|
|
static void
|
2008-05-08 09:00:56 +01:00
|
|
|
cairo_perf_fini (cairo_perf_t *perf)
|
2007-04-30 16:05:36 +01:00
|
|
|
{
|
2008-05-08 09:00:56 +01:00
|
|
|
cairo_boilerplate_free_targets (perf->targets);
|
|
|
|
|
free (perf->times);
|
2007-04-30 16:05:36 +01:00
|
|
|
cairo_debug_reset_static_data ();
|
|
|
|
|
#if HAVE_FCFINI
|
|
|
|
|
FcFini ();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-09-29 16:42:44 -07:00
|
|
|
int
|
|
|
|
|
main (int argc, char *argv[])
|
|
|
|
|
{
|
2008-05-08 09:00:56 +01:00
|
|
|
int i, j;
|
2006-09-29 16:42:44 -07:00
|
|
|
cairo_perf_t perf;
|
2006-10-04 12:55:54 -07:00
|
|
|
cairo_surface_t *surface;
|
2006-08-31 07:19:05 -07:00
|
|
|
|
2006-11-07 01:29:38 -08:00
|
|
|
parse_options (&perf, argc, argv);
|
2006-08-31 13:22:17 -07:00
|
|
|
|
2007-03-16 20:43:29 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-08 09:00:56 +01:00
|
|
|
perf.targets = cairo_boilerplate_get_targets (&perf.num_targets, NULL);
|
|
|
|
|
perf.times = xmalloc (perf.iterations * sizeof (cairo_perf_ticks_t));
|
2007-04-18 19:09:53 -04:00
|
|
|
|
2008-05-08 09:00:56 +01:00
|
|
|
for (i = 0; i < perf.num_targets; i++) {
|
|
|
|
|
cairo_boilerplate_target_t *target = perf.targets[i];
|
2006-10-04 12:55:54 -07:00
|
|
|
|
|
|
|
|
if (! target_is_measurable (target))
|
2006-08-31 08:53:58 -07:00
|
|
|
continue;
|
2007-04-18 19:46:30 -04:00
|
|
|
|
|
|
|
|
perf.target = target;
|
|
|
|
|
perf.test_number = 0;
|
2006-09-14 12:59:31 -07:00
|
|
|
|
2006-09-29 16:42:44 -07:00
|
|
|
for (j = 0; perf_cases[j].run; j++) {
|
2008-08-19 11:52:38 +01:00
|
|
|
const cairo_perf_case_t *perf_case = &perf_cases[j];
|
2006-10-04 12:55:54 -07:00
|
|
|
|
|
|
|
|
for (perf.size = perf_case->min_size;
|
|
|
|
|
perf.size <= perf_case->max_size;
|
|
|
|
|
perf.size *= 2)
|
|
|
|
|
{
|
2008-08-11 21:12:45 +01:00
|
|
|
void *closure;
|
|
|
|
|
|
2006-10-04 12:55:54 -07:00
|
|
|
surface = (target->create_surface) (NULL,
|
|
|
|
|
target->content,
|
|
|
|
|
perf.size, perf.size,
|
2008-08-11 21:12:45 +01:00
|
|
|
perf.size, perf.size,
|
2006-10-04 12:55:54 -07:00
|
|
|
CAIRO_BOILERPLATE_MODE_PERF,
|
2008-08-11 21:12:45 +01:00
|
|
|
0,
|
|
|
|
|
&closure);
|
2007-04-18 14:12:20 +01:00
|
|
|
if (surface == NULL) {
|
|
|
|
|
fprintf (stderr,
|
2007-04-18 14:24:10 +01:00
|
|
|
"Error: Failed to create target surface: %s\n",
|
2007-04-18 14:12:20 +01:00
|
|
|
target->name);
|
2008-08-19 11:52:38 +01:00
|
|
|
continue;
|
2007-04-18 14:12:20 +01:00
|
|
|
}
|
|
|
|
|
|
2008-08-11 21:12:45 +01:00
|
|
|
cairo_perf_timer_set_synchronize (target->synchronize, closure);
|
2006-10-04 12:55:54 -07:00
|
|
|
|
|
|
|
|
perf.cr = cairo_create (surface);
|
2006-10-04 16:35:20 -07:00
|
|
|
|
2006-10-04 13:23:50 -07:00
|
|
|
perf_case->run (&perf, perf.cr, perf.size, perf.size);
|
2006-10-04 12:55:54 -07:00
|
|
|
|
2006-10-04 16:35:20 -07:00
|
|
|
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)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_destroy (perf.cr);
|
2006-10-04 12:55:54 -07:00
|
|
|
cairo_surface_destroy (surface);
|
2007-03-07 13:31:54 +00:00
|
|
|
|
|
|
|
|
if (target->cleanup)
|
2008-08-11 21:12:45 +01:00
|
|
|
target->cleanup (closure);
|
2006-10-04 12:55:54 -07:00
|
|
|
}
|
2006-08-31 07:19:05 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-08 09:00:56 +01:00
|
|
|
cairo_perf_fini (&perf);
|
2007-04-18 19:46:30 -04:00
|
|
|
|
2006-08-31 07:19:05 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-19 11:52:38 +01:00
|
|
|
const cairo_perf_case_t perf_cases[] = {
|
2009-01-30 22:12:49 +00:00
|
|
|
{ paint, 64, 512},
|
|
|
|
|
{ paint_with_alpha, 64, 512},
|
|
|
|
|
{ fill, 64, 512},
|
|
|
|
|
{ stroke, 64, 512},
|
|
|
|
|
{ text, 64, 512},
|
2009-05-28 18:05:26 +01:00
|
|
|
{ glyphs, 64, 512},
|
2009-05-30 12:28:23 +01:00
|
|
|
{ mask, 64, 512},
|
2006-09-29 16:42:44 -07:00
|
|
|
{ tessellate, 100, 100},
|
2006-10-05 12:13:48 -07:00
|
|
|
{ subimage_copy, 16, 512},
|
2006-10-31 23:47:35 -08:00
|
|
|
{ pattern_create_radial, 16, 16},
|
2006-11-06 23:56:19 -08:00
|
|
|
{ zrusin, 415, 415},
|
2006-11-08 05:45:09 -08:00
|
|
|
{ world_map, 800, 800},
|
2006-11-17 17:50:14 -08:00
|
|
|
{ box_outline, 100, 100},
|
2006-12-16 20:00:56 +02:00
|
|
|
{ mosaic, 800, 800 },
|
2007-01-03 16:27:52 -08:00
|
|
|
{ long_lines, 100, 100},
|
2007-01-09 14:27:32 -08:00
|
|
|
{ unaligned_clip, 100, 100},
|
2007-01-31 11:53:06 -08:00
|
|
|
{ rectangles, 512, 512},
|
2008-09-28 18:57:15 +01:00
|
|
|
{ rounded_rectangles, 512, 512},
|
2007-06-18 13:58:15 -07:00
|
|
|
{ long_dashed_lines, 512, 512},
|
2008-10-08 20:08:25 +01:00
|
|
|
{ composite_checker, 16, 512},
|
2008-10-30 19:14:07 +00:00
|
|
|
{ twin, 800, 800},
|
2007-12-18 10:49:23 +00:00
|
|
|
{ dragon, 1024, 1024 },
|
2007-12-18 11:23:33 +00:00
|
|
|
{ pythagoras_tree, 768, 768 },
|
2008-09-12 17:32:40 +03:00
|
|
|
{ intersections, 512, 512 },
|
2008-09-12 17:41:45 +03:00
|
|
|
{ spiral, 512, 512 },
|
2006-08-31 11:51:28 -07:00
|
|
|
{ NULL }
|
|
|
|
|
};
|