int main (int argc, char **argv) { cairo_surface_t *surface = NULL; const cairo_script_interpreter_hooks_t hooks = { .closure = &surface, .surface_create = _surface_create, }; cairo_script_interpreter_t *csi; FILE *in = stdin, *out = stdout; if (argc >= 2 && strcmp (argv[1], "-")) in = fopen (argv[1], "r"); if (argc >= 3 && strcmp (argv[2], "-")) out = fopen (argv[2], "w"); csi = cairo_script_interpreter_create (); cairo_script_interpreter_install_hooks (csi, &hooks); cairo_script_interpreter_feed_stream (csi, in); cairo_script_interpreter_finish (csi); cairo_script_interpreter_destroy (csi); if (surface != NULL) { cairo_device_t *xml; xml = cairo_xml_create_for_stream (stdio_write, out); cairo_xml_for_recording_surface (xml, surface); cairo_device_destroy (xml); cairo_surface_destroy (surface); } if (in != stdin) fclose (in); if (out != stdout) fclose (out); return 0; }
static void execute (cairo_perf_t *perf, void *closure, cairo_surface_t *target, const char *trace) { static cairo_bool_t first_run = TRUE; unsigned int i; cairo_perf_ticks_t *times; cairo_stats_t stats = {0.0, 0.0}; int low_std_dev_count; char *trace_cpy, *name, *dot; const cairo_script_interpreter_hooks_t hooks = { .closure = target, .surface_create = _similar_surface_create, .context_create = _context_create }; trace_cpy = xstrdup (trace); name = basename (trace_cpy); dot = strchr (name, '.'); if (dot) *dot = '\0'; 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) { fprintf (perf->summary, "[ # ] %8s %28s %8s %5s %5s %s\n", "backend", "test", "min(s)", "median(s)", "stddev.", "count"); } first_run = FALSE; } describe (perf, closure); times = perf->times; if (perf->summary) { fprintf (perf->summary, "[%3d] %8s %28s ", perf->test_number, perf->target->name, name); fflush (perf->summary); } 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; csi = cairo_script_interpreter_create (); cairo_script_interpreter_install_hooks (csi, &hooks); cairo_perf_yield (); cairo_perf_timer_start (); cairo_script_interpreter_run (csi, trace); clear_surface (target); /* queue a write to the sync'ed surface */ cairo_perf_timer_stop (); times[i] = cairo_perf_timer_elapsed (); cairo_script_interpreter_finish (csi); scache_clear (); line_no = cairo_script_interpreter_get_line_number (csi); 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_perf_ticks_per_second () / 1000.0); 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); fprintf (perf->summary, "%#8.3f %#8.3f %#6.2f%% %4d/%d", (double) stats.min_ticks / cairo_perf_ticks_per_second (), (double) stats.median_ticks / cairo_perf_ticks_per_second (), 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); } fprintf (perf->summary, "%#8.3f %#8.3f %#6.2f%% %4d/%d\n", (double) stats.min_ticks / cairo_perf_ticks_per_second (), (double) stats.median_ticks / cairo_perf_ticks_per_second (), 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 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); }