static void cairo_perf_reports_compare (struct chart *chart, cairo_bool_t print) { test_report_t **tests, *min_test; double test_time, best_time; int num_test = 0; int seen_non_null; int i; tests = xmalloc (chart->num_reports * sizeof (test_report_t *)); for (i = 0; i < chart->num_reports; i++) tests[i] = chart->reports[i].tests; if (print) { if (chart->use_html) { printf ("<table style=\"text-align:right\" cellspacing=\"4\">\n"); printf ("<tr><td></td>"); for (i = 0; i < chart->num_reports; i++) { printf ("<td>%s</td>", chart->names[i] ? chart->names[i] : ""); } printf ("</tr>\n"); } } while (1) { /* We expect iterations values of 0 when multiple raw reports * for the same test have been condensed into the stats of the * first. So we just skip these later reports that have no * stats. */ seen_non_null = 0; for (i = 0; i < chart->num_reports; i++) { while (tests[i]->name && tests[i]->stats.iterations == 0) tests[i]++; if (tests[i]->name) seen_non_null++; } if (! seen_non_null) break; /* Find the minimum of all current tests, (we have to do this * in case some reports don't have a particular test). */ for (i = 0; i < chart->num_reports; i++) { if (tests[i]->name) { min_test = tests[i]; break; } } for (++i; i < chart->num_reports; i++) { if (tests[i]->name && test_report_cmp_name (tests[i], min_test) < 0) min_test = tests[i]; } add_label (chart, num_test, min_test->name); if (print) { if (chart->use_html) { printf ("<tr><td>%s</td>", min_test->name); } else { if (min_test->size) { printf ("%16s, size %4d:\n", min_test->name, min_test->size); } else { printf ("%26s:", min_test->name); } } } test_time = 0; best_time = HUGE_VAL; for (i = 0; i < chart->num_reports; i++) { test_report_t *initial = tests[i]; double report_time = HUGE_VAL; while (tests[i]->name && test_report_cmp_name (tests[i], min_test) == 0) { double time = tests[i]->stats.min_ticks; if (time < report_time) { time /= tests[i]->stats.ticks_per_ms; if (time < report_time) report_time = time; } tests[i]++; } if (test_time == 0 && report_time != HUGE_VAL) test_time = report_time; if (report_time < best_time) best_time = report_time; tests[i] = initial; } for (i = 0; i < chart->num_reports; i++) { double report_time = HUGE_VAL; while (tests[i]->name && test_report_cmp_name (tests[i], min_test) == 0) { double time = tests[i]->stats.min_ticks; if (time > 0) { time /= tests[i]->stats.ticks_per_ms; if (time < report_time) report_time = time; } tests[i]++; } if (print) { if (chart->use_html) { if (report_time < HUGE_VAL) { if (report_time / best_time < 1.01) { printf ("<td><strong>%.1f</strong></td>", report_time/1000); } else { printf ("<td>%.1f</td>", report_time/1000); } } else { printf ("<td></td>"); } } else { if (report_time < HUGE_VAL) printf (" %6.1f", report_time/1000); else printf (" ---"); } } if (report_time < HUGE_VAL) { if (chart->relative) { add_chart (chart, num_test, i, to_factor (test_time / report_time)); } else { add_chart (chart, num_test, i, report_time); } } } if (print) { if (chart->use_html) { printf ("</tr>\n"); } else { printf ("\n"); } } num_test++; } if (chart->relative) { add_label (chart, num_test, "(geometric mean)"); for (i = 0; i < chart->num_reports; i++) add_average (chart, num_test, i, to_factor (chart->average[i])); } free (tests); if (print) { if (chart->use_html) printf ("</table>\n"); printf ("\n"); for (i = 0; i < chart->num_reports; i++) { if (chart->names[i]) { printf ("[%s] %s\n", chart->names[i], chart->reports[i].configuration); } else { printf ("[%d] %s\n", i, chart->reports[i].configuration); } } } }
static void cairo_perf_reports_compare (cairo_perf_report_t *reports, int num_reports, cairo_perf_report_options_t *options) { int i; test_report_t **tests, *min_test; test_diff_t *diff, *diffs; int num_diffs, max_diffs; double max_change; double test_time; int seen_non_null; tests = xmalloc (num_reports * sizeof (test_report_t *)); max_diffs = reports[0].tests_count; for (i = 0; i < num_reports; i++) { tests[i] = reports[i].tests; if (reports[i].tests_count > max_diffs) max_diffs = reports[i].tests_count; } diff = diffs = xmalloc (max_diffs * sizeof (test_diff_t)); num_diffs = 0; while (1) { int num_tests; /* We expect iterations values of 0 when multiple raw reports * for the same test have been condensed into the stats of the * first. So we just skip these later reports that have no * stats. */ seen_non_null = 0; for (i = 0; i < num_reports; i++) { while (tests[i]->name && tests[i]->stats.iterations == 0) tests[i]++; if (tests[i]->name) seen_non_null++; } if (! seen_non_null) break; /* Find the minimum of all current tests, (we have to do this * in case some reports don't have a particular test). */ for (i = 0; i < num_reports; i++) { if (tests[i]->name) { min_test = tests[i]; break; } } for (++i; i < num_reports; i++) { if (tests[i]->name && test_report_cmp_name (tests[i], min_test) < 0) min_test = tests[i]; } num_tests = 0; for (i = 0; i < num_reports; i++) { test_report_t *test; int n = 0; test = tests[i]; while (test[n].name && test_report_cmp_name (&test[n], min_test) == 0) { n++; } num_tests += n; } /* For each report that has the current test, record it into * the diff structure. */ diff->num_tests = 0; diff->tests = xmalloc (num_tests * sizeof (test_diff_t)); for (i = 0; i < num_reports; i++) { while (tests[i]->name && test_report_cmp_name (tests[i], min_test) == 0) { test_time = tests[i]->stats.min_ticks; if (test_time > 0) { test_time /= tests[i]->stats.ticks_per_ms; if (diff->num_tests == 0) { diff->min = test_time; diff->max = test_time; } else { if (test_time < diff->min) diff->min = test_time; if (test_time > diff->max) diff->max = test_time; } diff->tests[diff->num_tests++] = tests[i]; } tests[i]++; } } diff->change = diff->max / diff->min; diff++; num_diffs++; } if (num_diffs == 0) goto DONE; qsort (diffs, num_diffs, sizeof (test_diff_t), test_diff_cmp); max_change = 1.0; for (i = 0; i < num_diffs; i++) { if (fabs (diffs[i].change) > max_change) max_change = fabs (diffs[i].change); } for (i = 0; i < num_diffs; i++) { diff = &diffs[i]; /* Discard as uninteresting a change which is less than the * minimum change required, (default may be overridden on * command-line). */ if (fabs (diff->change) - 1.0 < options->min_change) continue; test_diff_print (diff, max_change, options); } for (i = 0; i < num_diffs; i++) free (diffs[i].tests); DONE: free (diffs); free (tests); }
static void find_ranges (struct chart *chart) { test_report_t **tests, *min_test; double *values; int num_values, size_values; double min = 0, max = 0; double test_time; int seen_non_null; int num_tests = 0; double slow_sum = 0, fast_sum = 0, sum; int slow_count = 0, fast_count = 0; int *count; int i; num_values = 0; size_values = 64; values = xmalloc (size_values * sizeof (double)); chart->average = xmalloc(chart->num_reports * sizeof(double)); count = xmalloc(chart->num_reports * sizeof(int)); for (i = 0; i < chart->num_reports; i++) { chart->average[i] = 0; count[i] = 0; } tests = xmalloc (chart->num_reports * sizeof (test_report_t *)); for (i = 0; i < chart->num_reports; i++) tests[i] = chart->reports[i].tests; while (1) { /* We expect iterations values of 0 when multiple raw reports * for the same test have been condensed into the stats of the * first. So we just skip these later reports that have no * stats. */ seen_non_null = 0; for (i = 0; i < chart->num_reports; i++) { while (tests[i]->name && tests[i]->stats.iterations == 0) tests[i]++; if (tests[i]->name) seen_non_null++; } if (! seen_non_null) break; num_tests++; /* Find the minimum of all current tests, (we have to do this * in case some reports don't have a particular test). */ for (i = 0; i < chart->num_reports; i++) { if (tests[i]->name) { min_test = tests[i]; break; } } for (++i; i < chart->num_reports; i++) { if (tests[i]->name && test_report_cmp_name (tests[i], min_test) < 0) min_test = tests[i]; } test_time = 0; for (i = 0; i < chart->num_reports; i++) { double report_time = HUGE_VAL; while (tests[i]->name && test_report_cmp_name (tests[i], min_test) == 0) { double time = tests[i]->stats.min_ticks; if (time < report_time) { time /= tests[i]->stats.ticks_per_ms; if (time < report_time) report_time = time; } tests[i]++; } if (report_time != HUGE_VAL) { if (test_time == 0) test_time = report_time; chart->average[i] += report_time / test_time; count[i]++; if (chart->relative) { if (test_time != report_time) { double v = to_factor (test_time / report_time); if (num_values == size_values) { size_values *= 2; values = xrealloc (values, size_values * sizeof (double)); } values[num_values++] = v; if (v < min) min = v; if (v > max) max = v; if (v > 0) fast_sum += v/100, fast_count++; else slow_sum += v/100, slow_count++; sum += v/100; printf ("%s %d: %f\n", min_test->name, num_values, v); } } else { if (report_time < min) min = report_time; if (report_time > max) max = report_time; } } } } for (i = 0; i < chart->num_reports; i++) { if (count[i]) chart->average[i] = count[i] / chart->average[i]; else chart->average[i] = 1.; } if (chart->relative) trim_outliers (values, num_values, &min, &max); chart->min_value = min; chart->max_value = max; chart->num_tests = num_tests + !!chart->relative; free (values); free (tests); free (count); printf ("%d: slow[%d] average: %f, fast[%d] average: %f, %f\n", num_values, slow_count, slow_sum / slow_count, fast_count, fast_sum / fast_count, sum / num_values); }