void cairo_perf_run (cairo_perf_t *perf, const char *name, cairo_perf_func_t perf_func) { static cairo_bool_t first_run = TRUE; unsigned int i, similar, has_similar; cairo_perf_ticks_t *times; cairo_stats_t stats = {0.0, 0.0}; int low_std_dev_count; if (perf->list_only) { printf ("%s\n", name); return; } if (first_run) { if (perf->raw) printf ("[ # ] %s-%-s %s %s %s ...\n", "backend", "content", "test-size", "ticks-per-ms", "time(ticks)"); else printf ("[ # ] %8s-%-4s %28s %8s %8s %5s %5s %s\n", "backend", "content", "test-size", "min(ticks)", "min(ms)", "median(ms)", "stddev.", "iterations"); first_run = FALSE; } times = perf->times; has_similar = cairo_perf_has_similar (perf); for (similar = 0; similar <= has_similar; similar++) { /* We run one iteration in advance to warm caches, etc. */ cairo_perf_yield (); if (similar) cairo_push_group_with_content (perf->cr, cairo_boilerplate_content (perf->target->content)); (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) cairo_push_group_with_content (perf->cr, cairo_boilerplate_content (perf->target->content)); 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) printf ("[*] %s-%s %s-%d %g", perf->target->name, _content_to_string (perf->target->content, similar), name, perf->size, cairo_perf_ticks_per_second () / 1000.0); printf (" %lld", (long long) times[i]); } 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; } } } } if (perf->raw) { printf ("\n"); } else { _cairo_stats_compute (&stats, times, i); printf ("[%3d] %8s-%-5s %26s-%-3d ", 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", (long long) stats.min_ticks, (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); } perf->test_number++; } }
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); }
void cairo_perf_run (cairo_perf_t *perf, const char *name, cairo_perf_func_t perf_func) { 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; if (perf->num_names) { for (i = 0; i < perf->num_names; i++) if (strstr (name, perf->names[i])) goto NAME_FOUND; return; } NAME_FOUND: if (perf->list_only) { printf ("%s\n", name); return; } if (first_run) { if (perf->raw) printf ("[ # ] %s-%-s %s %s %s ...\n", "backend", "content", "test-size", "ticks-per-ms", "time(ticks)"); else printf ("[ # ] %8s-%-4s %28s %8s %8s %5s %5s %s\n", "backend", "content", "test-size", "min(ticks)", "min(ms)", "median(ms)", "stddev.", "iterations"); first_run = FALSE; } times = xmalloc (perf->iterations * sizeof (cairo_perf_ticks_t)); /* We run one iteration in advance to warm caches, etc. */ cairo_perf_yield (); (perf_func) (perf->cr, perf->size, perf->size); low_std_dev_count = 0; for (i =0; i < perf->iterations; i++) { cairo_perf_yield (); times[i] = (perf_func) (perf->cr, perf->size, perf->size); if (perf->raw) { if (i == 0) printf ("[*] %s-%s %s-%d %g", perf->target->name, _content_to_string (perf->target->content), name, perf->size, cairo_perf_ticks_per_second () / 1000.0); printf (" %lld", times[i]); } else { if (i > 0) { _cairo_stats_compute (&stats, times, i+1); if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV && ! perf->exact_iterations) { low_std_dev_count++; if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT) break; } else { low_std_dev_count = 0; } } } } if (perf->raw) { printf ("\n"); } else { printf ("[%3d] %8s-%-4s %26s-%-3d ", perf->test_number, perf->target->name, _content_to_string (perf->target->content), name, perf->size); printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n", stats.min_ticks, (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); } perf->test_number++; free (times); }