diff options
Diffstat (limited to 'perf/cairo-analyse-trace.c')
-rw-r--r-- | perf/cairo-analyse-trace.c | 592 |
1 files changed, 0 insertions, 592 deletions
diff --git a/perf/cairo-analyse-trace.c b/perf/cairo-analyse-trace.c deleted file mode 100644 index 994148660..000000000 --- a/perf/cairo-analyse-trace.c +++ /dev/null @@ -1,592 +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 - * Copyright © 2011 Intel Corporation - * - * 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-perf.h" -#include "cairo-stats.h" - -#include "cairo-boilerplate-getopt.h" -#include <cairo-script-interpreter.h> -#include "cairo-missing.h" - -/* rudely reuse bits of the library... */ -#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 = strchr (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 - -struct trace { - const cairo_boilerplate_target_t *target; - void *closure; - cairo_surface_t *surface; -}; - -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 = strchr (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 cairo_surface_t * -surface_create (void *closure, - cairo_content_t content, - double width, - double height, - long uid) -{ - struct trace *args = closure; - return cairo_surface_create_similar (args->surface, content, width, height); -} - -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; - - free (description); -} - -static void -execute (cairo_perf_t *perf, - struct trace *args, - const char *trace) -{ - char *trace_cpy, *name; - const cairo_script_interpreter_hooks_t hooks = { - .closure = args, - .surface_create = surface_create, - }; - - trace_cpy = xstrdup (trace); - name = basename_no_ext (trace_cpy); - - if (perf->list_only) { - printf ("%s\n", name); - free (trace_cpy); - return; - } - - describe (perf, args->closure); - - { - cairo_script_interpreter_t *csi; - cairo_status_t status; - unsigned int line_no; - - csi = cairo_script_interpreter_create (); - cairo_script_interpreter_install_hooks (csi, &hooks); - - cairo_script_interpreter_run (csi, trace); - - cairo_script_interpreter_finish (csi); - - line_no = cairo_script_interpreter_get_line_number (csi); - status = cairo_script_interpreter_destroy (csi); - if (status) { - /* XXXX cairo_status_to_string is just wrong! */ - fprintf (stderr, "Error during replay, line %d: %s\n", - line_no, cairo_status_to_string (status)); - } - } - user_interrupt = 0; - - free (trace_cpy); -} - -static void -usage (const char *argv0) -{ - fprintf (stderr, -"Usage: %s [-l] [-i iterations] [-x exclude-file] [test-names ... | traces ...]\n" -"\n" -"Run the cairo trace analysis suite over the given tests (all by default)\n" -"The command-line arguments are interpreted as follows:\n" -"\n" -" -i iterations; specify the number of iterations per test case\n" -" -l list only; just list selected test case names without executing\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[]) -{ - char *end; - int c; - - perf->list_only = FALSE; - perf->names = NULL; - perf->num_names = 0; - perf->exclude_names = NULL; - perf->num_exclude_names = 0; - - while (1) { - c = _cairo_getopt (argc, argv, "i:lx:"); - if (c == -1) - break; - - switch (c) { - 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 '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 (optind < argc) { - perf->names = &argv[optind]; - perf->num_names = argc - optind; - } -} - -static void -cairo_perf_fini (cairo_perf_t *perf) -{ - cairo_boilerplate_free_targets (perf->targets); - cairo_boilerplate_fini (); - - 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 cairo_status_t -print (void *closure, const unsigned char *data, unsigned int length) -{ - fwrite (data, length, 1, closure); - return CAIRO_STATUS_SUCCESS; -} - -static void -cairo_perf_trace (cairo_perf_t *perf, - const cairo_boilerplate_target_t *target, - const char *trace) -{ - struct trace args; - cairo_surface_t *real; - - args.target = target; - real = target->create_surface (NULL, - CAIRO_CONTENT_COLOR_ALPHA, - 1, 1, - 1, 1, - CAIRO_BOILERPLATE_MODE_PERF, - &args.closure); - args.surface = - cairo_surface_create_observer (real, - CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS); - cairo_surface_destroy (real); - if (cairo_surface_status (args.surface)) { - fprintf (stderr, - "Error: Failed to create target surface: %s\n", - target->name); - return; - } - - printf ("Observing '%s'...", trace); - fflush (stdout); - - execute (perf, &args, trace); - - printf ("\n"); - cairo_device_observer_print (cairo_surface_get_device (args.surface), - print, stdout); - fflush (stdout); - - cairo_surface_destroy (args.surface); - - if (target->cleanup) - target->cleanup (args.closure); -} - -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); - - /* 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.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; -} |