diff options
Diffstat (limited to 'perf/cairo-perf-trace.c')
-rw-r--r-- | perf/cairo-perf-trace.c | 1067 |
1 files changed, 0 insertions, 1067 deletions
diff --git a/perf/cairo-perf-trace.c b/perf/cairo-perf-trace.c deleted file mode 100644 index 02e0e29f9..000000000 --- a/perf/cairo-perf-trace.c +++ /dev/null @@ -1,1067 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* - * Copyright © 2006 Mozilla Corporation - * Copyright © 2006 Red Hat, Inc. - * Copyright © 2009 Chris Wilson - * - * 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 - * the authors not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. The authors make no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, - * 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. - * - * Authors: Vladimir Vukicevic <vladimir@pobox.com> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#define _GNU_SOURCE 1 /* for sched_getaffinity() and getline() */ - -#include "../cairo-version.h" /* for the real version */ - -#include "cairo-missing.h" -#include "cairo-perf.h" -#include "cairo-stats.h" - -#include "cairo-boilerplate-getopt.h" -#include <cairo-script-interpreter.h> -#include <cairo-types-private.h> /* for INTERNAL_SURFACE_TYPE */ - -/* rudely reuse bits of the library... */ -#include "../src/cairo-hash-private.h" -#include "../src/cairo-error-private.h" - -/* For basename */ -#ifdef HAVE_LIBGEN_H -#include <libgen.h> -#endif -#include <ctype.h> /* isspace() */ - -#include <sys/types.h> -#include <sys/stat.h> - -#ifdef _MSC_VER -#include "dirent-win32.h" - -static char * -basename_no_ext (char *path) -{ - static char name[_MAX_FNAME + 1]; - - _splitpath (path, NULL, NULL, name, NULL); - - name[_MAX_FNAME] = '\0'; - - return name; -} - - -#else -#include <dirent.h> - -static char * -basename_no_ext (char *path) -{ - char *dot, *name; - - name = basename (path); - - dot = strrchr (name, '.'); - if (dot) - *dot = '\0'; - - return name; -} - -#endif - -#if HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <signal.h> - -#if HAVE_FCFINI -#include <fontconfig/fontconfig.h> -#endif - -#define CAIRO_PERF_ITERATIONS_DEFAULT 15 -#define CAIRO_PERF_LOW_STD_DEV 0.05 -#define CAIRO_PERF_MIN_STD_DEV_COUNT 3 -#define CAIRO_PERF_STABLE_STD_DEV_COUNT 3 - -struct trace { - const cairo_boilerplate_target_t *target; - void *closure; - cairo_surface_t *surface; - cairo_bool_t observe; - int tile_size; -}; - -cairo_bool_t -cairo_perf_can_run (cairo_perf_t *perf, - const char *name, - cairo_bool_t *is_explicit) -{ - unsigned int i; - char *copy, *dot; - cairo_bool_t ret; - - if (is_explicit) - *is_explicit = FALSE; - - if (perf->exact_names) { - if (is_explicit) - *is_explicit = TRUE; - return TRUE; - } - - if (perf->num_names == 0 && perf->num_exclude_names == 0) - return TRUE; - - copy = xstrdup (name); - dot = strrchr (copy, '.'); - if (dot != NULL) - *dot = '\0'; - - if (perf->num_names) { - ret = TRUE; - for (i = 0; i < perf->num_names; i++) - if (strstr (copy, perf->names[i])) { - if (is_explicit) - *is_explicit = strcmp (copy, perf->names[i]) == 0; - goto check_exclude; - } - - ret = FALSE; - goto done; - } - -check_exclude: - if (perf->num_exclude_names) { - ret = FALSE; - for (i = 0; i < perf->num_exclude_names; i++) - if (strstr (copy, perf->exclude_names[i])) { - if (is_explicit) - *is_explicit = strcmp (copy, perf->exclude_names[i]) == 0; - goto done; - } - - ret = TRUE; - goto done; - } - -done: - free (copy); - - return ret; -} - -static void -fill_surface (cairo_surface_t *surface) -{ - cairo_t *cr = cairo_create (surface); - /* This needs to be an operation that the backends can't optimise away */ - cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.5); - cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - cairo_paint (cr); - cairo_destroy (cr); -} - -struct scache { - cairo_hash_entry_t entry; - cairo_content_t content; - int width, height; - cairo_surface_t *surface; -}; - -static cairo_hash_table_t *surface_cache; -static cairo_surface_t *surface_holdovers[16]; - -static cairo_bool_t -scache_equal (const void *A, - const void *B) -{ - const struct scache *a = A, *b = B; - return a->entry.hash == b->entry.hash; -} - -static void -scache_mark_active (cairo_surface_t *surface) -{ - cairo_surface_t *t0, *t1; - unsigned n; - - if (surface_cache == NULL) - return; - - t0 = cairo_surface_reference (surface); - for (n = 0; n < ARRAY_LENGTH (surface_holdovers); n++) { - if (surface_holdovers[n] == surface) { - surface_holdovers[n] = t0; - t0 = surface; - break; - } - - t1 = surface_holdovers[n]; - surface_holdovers[n] = t0; - t0 = t1; - } - cairo_surface_destroy (t0); -} - -static void -scache_clear (void) -{ - unsigned n; - - if (surface_cache == NULL) - return; - - for (n = 0; n < ARRAY_LENGTH (surface_holdovers); n++) { - cairo_surface_destroy (surface_holdovers[n]); - surface_holdovers[n] = NULL; - } -} - -static void -scache_remove (void *closure) -{ - _cairo_hash_table_remove (surface_cache, closure); - free (closure); -} - -static cairo_surface_t * -_similar_surface_create (void *closure, - cairo_content_t content, - double width, - double height, - long uid) -{ - struct trace *args = closure; - cairo_surface_t *surface; - struct scache skey, *s; - - if (args->observe) - return cairo_surface_create_similar (args->surface, - content, width, height); - - if (uid == 0 || surface_cache == NULL) - return args->target->create_similar (args->surface, content, width, height); - - skey.entry.hash = uid; - s = _cairo_hash_table_lookup (surface_cache, &skey.entry); - if (s != NULL) { - if (s->content == content && - s->width == width && - s->height == height) - { - return cairo_surface_reference (s->surface); - } - - /* The surface has been resized, allow the original entry to expire - * as it becomes inactive. - */ - } - - surface = args->target->create_similar (args->surface, content, width, height); - s = malloc (sizeof (struct scache)); - if (s == NULL) - return surface; - - s->entry.hash = uid; - s->content = content; - s->width = width; - s->height = height; - s->surface = surface; - if (_cairo_hash_table_insert (surface_cache, &s->entry)) { - free (s); - } else if (cairo_surface_set_user_data - (surface, - (const cairo_user_data_key_t *) &surface_cache, - s, scache_remove)) - { - scache_remove (s); - } - - return surface; -} - -static cairo_surface_t * -_source_image_create (void *closure, - cairo_format_t format, - int width, - int height, - long uid) -{ - struct trace *args = closure; - - return cairo_surface_create_similar_image (args->surface, - format, width, height); -} - -static cairo_t * -_context_create (void *closure, - cairo_surface_t *surface) -{ - scache_mark_active (surface); - return cairo_create (surface); -} - -static int user_interrupt; - -static void -interrupt (int sig) -{ - if (user_interrupt) { - signal (sig, SIG_DFL); - raise (sig); - } - - user_interrupt = 1; -} - -static void -describe (cairo_perf_t *perf, - void *closure) -{ - char *description = NULL; - - if (perf->has_described_backend) - return; - perf->has_described_backend = TRUE; - - if (perf->target->describe) - description = perf->target->describe (closure); - - if (description == NULL) - return; - - if (perf->raw) { - printf ("[ # ] %s: %s\n", perf->target->name, description); - } - - if (perf->summary) { - fprintf (perf->summary, - "[ # ] %8s: %s\n", - perf->target->name, - description); - } - - free (description); -} - -static void -usage (const char *argv0) -{ - fprintf (stderr, -"Usage: %s [-clrsv] [-i iterations] [-t tile-size] [-x exclude-file] [test-names ... | traces ...]\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" -" -c use surface cache; keep a cache of surfaces to be reused\n" -" -i iterations; specify the number of iterations per test case\n" -" -l list only; just list selected test case names without executing\n" -" -r raw; display each time measurement instead of summary statistics\n" -" -s sync; only sum the elapsed time of the indiviual operations\n" -" -t tile size; draw to tiled surfaces\n" -" -v verbose; in raw mode also show the summaries\n" -" -x exclude; specify a file to read a list of traces to exclude\n" -"\n" -"If test names are given they are used as sub-string matches so a command\n" -"such as \"%s firefox\" can be used to run all firefox traces.\n" -"Alternatively, you can specify a list of filenames to execute.\n", - argv0, argv0); -} - -static cairo_bool_t -read_excludes (cairo_perf_t *perf, - const char *filename) -{ - FILE *file; - char *line = NULL; - size_t line_size = 0; - char *s, *t; - - file = fopen (filename, "r"); - if (file == NULL) - return FALSE; - - while (getline (&line, &line_size, file) != -1) { - /* terminate the line at a comment marker '#' */ - s = strchr (line, '#'); - if (s) - *s = '\0'; - - /* whitespace delimits */ - s = line; - while (*s != '\0' && isspace (*s)) - s++; - - t = s; - while (*t != '\0' && ! isspace (*t)) - t++; - - if (s != t) { - int i = perf->num_exclude_names; - perf->exclude_names = xrealloc (perf->exclude_names, - sizeof (char *) * (i+1)); - perf->exclude_names[i] = strndup (s, t-s); - perf->num_exclude_names++; - } - } - free (line); - - fclose (file); - - return TRUE; -} - -static void -parse_options (cairo_perf_t *perf, - int argc, - char *argv[]) -{ - int c; - const char *iters; - char *end; - int verbose = 0; - int use_surface_cache = 0; - - if ((iters = getenv ("CAIRO_PERF_ITERATIONS")) && *iters) - perf->iterations = strtol (iters, NULL, 0); - else - perf->iterations = CAIRO_PERF_ITERATIONS_DEFAULT; - perf->exact_iterations = 0; - - perf->raw = FALSE; - perf->observe = FALSE; - perf->list_only = FALSE; - perf->tile_size = 0; - perf->names = NULL; - perf->num_names = 0; - perf->summary = stdout; - perf->summary_continuous = FALSE; - perf->exclude_names = NULL; - perf->num_exclude_names = 0; - - while (1) { - c = _cairo_getopt (argc, argv, "ci:lrst:vx:"); - if (c == -1) - break; - - switch (c) { - case 'c': - use_surface_cache = 1; - break; - case 'i': - perf->exact_iterations = TRUE; - 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; - perf->summary = NULL; - break; - case 's': - perf->observe = TRUE; - break; - case 't': - perf->tile_size = strtoul (optarg, &end, 10); - if (*end != '\0') { - fprintf (stderr, "Invalid argument for -t (not an integer): %s\n", - optarg); - exit (1); - } - break; - case 'v': - verbose = 1; - break; - case 'x': - if (! read_excludes (perf, optarg)) { - fprintf (stderr, "Invalid argument for -x (not readable file): %s\n", - optarg); - exit (1); - } - break; - default: - fprintf (stderr, "Internal error: unhandled option: %c\n", c); - /* fall-through */ - case '?': - usage (argv[0]); - exit (1); - } - } - - if (perf->observe && perf->tile_size) { - fprintf (stderr, "Can't mix observer and tiling. Sorry.\n"); - exit (1); - } - - if (verbose && perf->summary == NULL) - perf->summary = stderr; -#if HAVE_UNISTD_H - if (perf->summary && isatty (fileno (perf->summary))) - perf->summary_continuous = TRUE; -#endif - - if (optind < argc) { - perf->names = &argv[optind]; - perf->num_names = argc - optind; - } - - if (use_surface_cache) - surface_cache = _cairo_hash_table_create (scache_equal); -} - -static void -cairo_perf_fini (cairo_perf_t *perf) -{ - cairo_boilerplate_free_targets (perf->targets); - cairo_boilerplate_fini (); - - free (perf->times); - cairo_debug_reset_static_data (); -#if HAVE_FCFINI - FcFini (); -#endif -} - -static cairo_bool_t -have_trace_filenames (cairo_perf_t *perf) -{ - unsigned int i; - - if (perf->num_names == 0) - return FALSE; - -#if HAVE_UNISTD_H - for (i = 0; i < perf->num_names; i++) - if (access (perf->names[i], R_OK) == 0) - return TRUE; -#endif - - return FALSE; -} - -static void -_tiling_surface_finish (cairo_surface_t *observer, - cairo_surface_t *target, - void *closure) -{ - struct trace *args = closure; - cairo_surface_t *surface; - cairo_content_t content; - cairo_rectangle_t r; - int width, height; - int x, y, w, h; - - cairo_recording_surface_get_extents (target, &r); - w = r.width; - h = r.height; - - content = cairo_surface_get_content (target); - - for (y = 0; y < h; y += args->tile_size) { - height = args->tile_size; - if (y + height > h) - height = h - y; - - for (x = 0; x < w; x += args->tile_size) { - cairo_t *cr; - - width = args->tile_size; - if (x + width > w) - width = w - x; - - /* XXX to correctly observe the playback we would need - * to replay the target onto the observer directly. - */ - surface = args->target->create_similar (args->surface, - content, width, height); - - cr = cairo_create (surface); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (cr, target, -x, -y); - cairo_paint (cr); - cairo_destroy (cr); - - cairo_surface_destroy (surface); - } - } -} - -static cairo_surface_t * -_tiling_surface_create (void *closure, - cairo_content_t content, - double width, - double height, - long uid) -{ - cairo_rectangle_t r; - cairo_surface_t *surface, *observer; - - r.x = r.y = 0; - r.width = width; - r.height = height; - - surface = cairo_recording_surface_create (content, &r); - observer = cairo_surface_create_observer (surface, - CAIRO_SURFACE_OBSERVER_NORMAL); - cairo_surface_destroy (surface); - - cairo_surface_observer_add_finish_callback (observer, - _tiling_surface_finish, - closure); - - return observer; -} - -static void -cairo_perf_trace (cairo_perf_t *perf, - const cairo_boilerplate_target_t *target, - const char *trace) -{ - static cairo_bool_t first_run = TRUE; - unsigned int i; - cairo_time_t *times, *paint, *mask, *fill, *stroke, *glyphs; - cairo_stats_t stats = {0.0, 0.0}; - struct trace args = { target }; - int low_std_dev_count; - char *trace_cpy, *name; - const cairo_script_interpreter_hooks_t hooks = { - &args, - perf->tile_size ? _tiling_surface_create : _similar_surface_create, - NULL, /* surface_destroy */ - _context_create, - NULL, /* context_destroy */ - NULL, /* show_page */ - NULL, /* copy_page */ - _source_image_create, - }; - - args.tile_size = perf->tile_size; - args.observe = perf->observe; - - trace_cpy = xstrdup (trace); - name = basename_no_ext (trace_cpy); - - if (perf->list_only) { - printf ("%s\n", name); - free (trace_cpy); - return; - } - - if (first_run) { - if (perf->raw) { - printf ("[ # ] %s.%-s %s %s %s ...\n", - "backend", "content", "test-size", "ticks-per-ms", "time(ticks)"); - } - - if (perf->summary) { - if (perf->observe) { - fprintf (perf->summary, - "[ # ] %8s %28s %9s %9s %9s %9s %9s %9s %5s\n", - "backend", "test", - "total(s)", "paint(s)", "mask(s)", "fill(s)", "stroke(s)", "glyphs(s)", - "count"); - } else { - fprintf (perf->summary, - "[ # ] %8s %28s %8s %5s %5s %s\n", - "backend", "test", "min(s)", "median(s)", - "stddev.", "count"); - } - } - first_run = FALSE; - } - - times = perf->times; - paint = times + perf->iterations; - mask = paint + perf->iterations; - stroke = mask + perf->iterations; - fill = stroke + perf->iterations; - glyphs = fill + perf->iterations; - - low_std_dev_count = 0; - for (i = 0; i < perf->iterations && ! user_interrupt; i++) { - cairo_script_interpreter_t *csi; - cairo_status_t status; - unsigned int line_no; - - args.surface = target->create_surface (NULL, - CAIRO_CONTENT_COLOR_ALPHA, - 1, 1, - 1, 1, - CAIRO_BOILERPLATE_MODE_PERF, - &args.closure); - fill_surface(args.surface); /* remove any clear flags */ - - if (perf->observe) { - cairo_surface_t *obs; - obs = cairo_surface_create_observer (args.surface, - CAIRO_SURFACE_OBSERVER_NORMAL); - cairo_surface_destroy (args.surface); - args.surface = obs; - } - if (cairo_surface_status (args.surface)) { - fprintf (stderr, - "Error: Failed to create target surface: %s\n", - target->name); - return; - } - - cairo_perf_timer_set_synchronize (target->synchronize, args.closure); - - if (i == 0) { - describe (perf, args.closure); - if (perf->summary) { - fprintf (perf->summary, - "[%3d] %8s %28s ", - perf->test_number, - perf->target->name, - name); - fflush (perf->summary); - } - } - - csi = cairo_script_interpreter_create (); - cairo_script_interpreter_install_hooks (csi, &hooks); - - if (! perf->observe) { - cairo_perf_yield (); - cairo_perf_timer_start (); - } - - cairo_script_interpreter_run (csi, trace); - line_no = cairo_script_interpreter_get_line_number (csi); - - /* Finish before querying timings in case we are using an intermediate - * target and so need to destroy all surfaces before rendering - * commences. - */ - cairo_script_interpreter_finish (csi); - - if (perf->observe) { - cairo_device_t *observer = cairo_surface_get_device (args.surface); - times[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_elapsed (observer)); - paint[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_paint_elapsed (observer)); - mask[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_mask_elapsed (observer)); - stroke[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_stroke_elapsed (observer)); - fill[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_fill_elapsed (observer)); - glyphs[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_glyphs_elapsed (observer)); - } else { - fill_surface (args.surface); /* queue a write to the sync'ed surface */ - cairo_perf_timer_stop (); - times[i] = cairo_perf_timer_elapsed (); - } - - scache_clear (); - - cairo_surface_destroy (args.surface); - - if (target->cleanup) - target->cleanup (args.closure); - - status = cairo_script_interpreter_destroy (csi); - if (status) { - if (perf->summary) { - fprintf (perf->summary, "Error during replay, line %d: %s\n", - line_no, - cairo_status_to_string (status)); - } - goto out; - } - - if (perf->raw) { - if (i == 0) - printf ("[*] %s.%s %s.%d %g", - perf->target->name, - "rgba", - name, - 0, - _cairo_time_to_double (_cairo_time_from_s (1)) / 1000.); - printf (" %lld", (long long) times[i]); - fflush (stdout); - } else if (! perf->exact_iterations) { - if (i > CAIRO_PERF_MIN_STD_DEV_COUNT) { - _cairo_stats_compute (&stats, times, i+1); - - if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV) { - if (++low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT) - break; - } else { - low_std_dev_count = 0; - } - } - } - - if (perf->summary && perf->summary_continuous) { - _cairo_stats_compute (&stats, times, i+1); - - fprintf (perf->summary, - "\r[%3d] %8s %28s ", - perf->test_number, - perf->target->name, - name); - if (perf->observe) { - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, paint, i+1); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, mask, i+1); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, fill, i+1); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, stroke, i+1); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, glyphs, i+1); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - fprintf (perf->summary, - " %5d", i+1); - } else { - fprintf (perf->summary, - "%#8.3f %#8.3f %#6.2f%% %4d/%d", - _cairo_time_to_s (stats.min_ticks), - _cairo_time_to_s (stats.median_ticks), - stats.std_dev * 100.0, - stats.iterations, i+1); - } - fflush (perf->summary); - } - } - user_interrupt = 0; - - if (perf->summary) { - _cairo_stats_compute (&stats, times, i); - if (perf->summary_continuous) { - fprintf (perf->summary, - "\r[%3d] %8s %28s ", - perf->test_number, - perf->target->name, - name); - } - if (perf->observe) { - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, paint, i); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, mask, i); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, fill, i); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, stroke, i); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - _cairo_stats_compute (&stats, glyphs, i); - fprintf (perf->summary, - " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - - fprintf (perf->summary, - " %5d\n", i); - } else { - fprintf (perf->summary, - "%#8.3f %#8.3f %#6.2f%% %4d/%d\n", - _cairo_time_to_s (stats.min_ticks), - _cairo_time_to_s (stats.median_ticks), - stats.std_dev * 100.0, - stats.iterations, i); - } - fflush (perf->summary); - } - -out: - if (perf->raw) { - printf ("\n"); - fflush (stdout); - } - - perf->test_number++; - free (trace_cpy); -} - -static void -warn_no_traces (const char *message, - const char *trace_dir) -{ - fprintf (stderr, -"Error: %s '%s'.\n" -"Have you cloned the cairo-traces repository and uncompressed the traces?\n" -" git clone git://anongit.freedesktop.org/cairo-traces\n" -" cd cairo-traces && make\n" -"Or set the env.var CAIRO_TRACE_DIR to point to your traces?\n", - message, trace_dir); -} - -static int -cairo_perf_trace_dir (cairo_perf_t *perf, - const cairo_boilerplate_target_t *target, - const char *dirname) -{ - DIR *dir; - struct dirent *de; - int num_traces = 0; - cairo_bool_t force; - cairo_bool_t is_explicit; - - dir = opendir (dirname); - if (dir == NULL) - return 0; - - force = FALSE; - if (cairo_perf_can_run (perf, dirname, &is_explicit)) - force = is_explicit; - - while ((de = readdir (dir)) != NULL) { - char *trace; - struct stat st; - - if (de->d_name[0] == '.') - continue; - - xasprintf (&trace, "%s/%s", dirname, de->d_name); - if (stat (trace, &st) != 0) - goto next; - - if (S_ISDIR(st.st_mode)) { - num_traces += cairo_perf_trace_dir (perf, target, trace); - } else { - const char *dot; - - dot = strrchr (de->d_name, '.'); - if (dot == NULL) - goto next; - if (strcmp (dot, ".trace")) - goto next; - - num_traces++; - if (!force && ! cairo_perf_can_run (perf, de->d_name, NULL)) - goto next; - - cairo_perf_trace (perf, target, trace); - } -next: - free (trace); - - } - closedir (dir); - - return num_traces; -} - -int -main (int argc, - char *argv[]) -{ - cairo_perf_t perf; - const char *trace_dir = "cairo-traces:/usr/src/cairo-traces:/usr/share/cairo-traces"; - unsigned int n; - int i; - - parse_options (&perf, argc, argv); - - signal (SIGINT, interrupt); - - if (getenv ("CAIRO_TRACE_DIR") != NULL) - trace_dir = getenv ("CAIRO_TRACE_DIR"); - - perf.targets = cairo_boilerplate_get_targets (&perf.num_targets, NULL); - perf.times = xmalloc (6 * perf.iterations * sizeof (cairo_time_t)); - - /* do we have a list of filenames? */ - perf.exact_names = have_trace_filenames (&perf); - - for (i = 0; i < perf.num_targets; i++) { - const cairo_boilerplate_target_t *target = perf.targets[i]; - - if (! perf.list_only && ! target->is_measurable) - continue; - - perf.target = target; - perf.test_number = 0; - perf.has_described_backend = FALSE; - - if (perf.exact_names) { - for (n = 0; n < perf.num_names; n++) { - struct stat st; - - if (stat (perf.names[n], &st) == 0) { - if (S_ISDIR (st.st_mode)) { - cairo_perf_trace_dir (&perf, target, perf.names[n]); - } else - cairo_perf_trace (&perf, target, perf.names[n]); - } - } - } else { - int num_traces = 0; - const char *dir; - - dir = trace_dir; - do { - char buf[1024]; - const char *end = strchr (dir, ':'); - if (end != NULL) { - memcpy (buf, dir, end-dir); - buf[end-dir] = '\0'; - end++; - - dir = buf; - } - - num_traces += cairo_perf_trace_dir (&perf, target, dir); - dir = end; - } while (dir != NULL); - - if (num_traces == 0) { - warn_no_traces ("Found no traces in", trace_dir); - return 1; - } - } - - if (perf.list_only) - break; - } - - cairo_perf_fini (&perf); - - return 0; -} |