summaryrefslogtreecommitdiff
path: root/perf/cairo-perf-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'perf/cairo-perf-trace.c')
-rw-r--r--perf/cairo-perf-trace.c1067
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;
-}