diff --git a/perf/cairo-bench.h b/perf/cairo-bench.h new file mode 100644 index 000000000..076b7c15d --- /dev/null +++ b/perf/cairo-bench.h @@ -0,0 +1,110 @@ +/* + * Copyright © 2006 Mozilla 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 + * Mozilla Corporation not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Mozilla Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION 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. + * + * Author: Vladimir Vukicevic + */ + +#ifndef CAIRO_BENCH_H_ +#define CAIRO_BENCH_H_ + +#ifndef USE_WINAPI +#include +#endif + +#include + +#include "surface-boilerplate.h" + +extern int num_benchmarks; + +char *content_name (cairo_content_t content); +cairo_content_t content_for_name (const char *content); + +/* results */ + +typedef struct _bench_result_t bench_result_t; + +struct _bench_result_t { + cairo_test_target_t *target; + double *results; + + bench_result_t *next; +}; + +/* timers */ + +typedef struct { +#ifdef USE_WINAPI + LARGE_INTEGER start; + LARGE_INTEGER stop; +#else + struct timeval start; + struct timeval stop; +#endif + long count; +} bench_timer_t; + +extern int alarm_expired; + +void timer_start (bench_timer_t *tr); +void timer_stop (bench_timer_t *tr); +double timer_elapsed (bench_timer_t *tr); + +void set_alarm (int seconds); +void start_timing (bench_timer_t *tr, long *count); +void stop_timing (bench_timer_t *tr, long count); +double timing_result (bench_timer_t *tr); + +#ifdef USE_WINAPI +// Windows needs a SleepEx to put the thread into an alertable state, +// such that the timer expiration callback can fire. I can't figure +// out how to do an async timer. On a quiet system, this doesn't +// seem to significantly affect the results. +#define BEGIN_TIMING_LOOP(timervar,countvar) do { \ + countvar = 0; \ + start_timing(&(timervar), &(countvar)); \ + while (!alarm_expired) { \ + SleepEx(0, TRUE); + +#else + +#define BEGIN_TIMING_LOOP(timervar,countvar) do { \ + countvar = 0; \ + start_timing(&(timervar), &(countvar)); \ + while (!alarm_expired) { + +#endif + +#define END_TIMING_LOOP(timervar,countvar) \ + (countvar)++; \ + } \ + stop_timing (&(timervar), (countvar)); \ + } while (0); + +/* arg parsing */ +int parse_args (int argc, char **argv, int **tests, cairo_test_target_t ***targets); + +#ifndef CAIRO_HAS_PNG_FUNCTIONS +cairo_status_t cairo_surface_write_to_png (cairo_surface_t *surface, const char *filename); +#endif + +#endif /* CAIRO_BENCH_H_ */ diff --git a/perf/util.c b/perf/util.c new file mode 100644 index 000000000..a786df7b6 --- /dev/null +++ b/perf/util.c @@ -0,0 +1,175 @@ +/* + * Copyright © 2006 Mozilla 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 + * Mozilla Corporation not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Mozilla Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION 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. + * + * Author: Vladimir Vukicevic + */ + +#define _GNU_SOURCE + +#ifdef USE_WINAPI +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include +#include +#include +#include +#include + +#ifndef USE_WINAPI +#include +#include +#endif + +#include "cairo-bench.h" + +/* helpers */ + +char * +content_name (cairo_content_t content) +{ + if (content == CAIRO_CONTENT_COLOR) return "rgb"; + if (content == CAIRO_CONTENT_COLOR_ALPHA) return "argb"; + if (content == CAIRO_CONTENT_ALPHA) return "a8"; + assert (0); + return NULL; +} + +cairo_content_t +content_for_name (const char *content) +{ + if (strcmp(content, "rgb") == 0) return CAIRO_CONTENT_COLOR; + if (strcmp(content, "argb") == 0) return CAIRO_CONTENT_COLOR_ALPHA; + if (strcmp(content, "a8") == 0) return CAIRO_CONTENT_ALPHA; + return (cairo_content_t) -1; +} + +/* timers */ + +#ifdef USE_WINAPI +void +timer_start (bench_timer_t *tr) { + QueryPerformanceCounter(&tr->start); +} + +void +timer_stop (bench_timer_t *tr) { + QueryPerformanceCounter(&tr->stop); +} + +double +timer_elapsed (bench_timer_t *tr) { + double d; + LARGE_INTEGER freq; + + QueryPerformanceFrequency(&freq); + + d = (tr->stop.QuadPart - tr->start.QuadPart) / (double) freq.QuadPart; + return d; +} +#else +void +timer_start (bench_timer_t *tr) { + gettimeofday (&tr->start, NULL); +} + +void +timer_stop (bench_timer_t *tr) { + gettimeofday (&tr->stop, NULL); +} + +double +timer_elapsed (bench_timer_t *tr) { + double d; + + d = tr->stop.tv_sec - tr->start.tv_sec; + d += (tr->stop.tv_usec - tr->start.tv_usec) / 1000000.0; + + return d; +} +#endif + +/* alarms */ +int test_seconds = -1; + +int alarm_expired = 0; + +#ifdef USE_WINAPI +void CALLBACK +alarm_handler (void *closure, DWORD dwTimerLowValue, DWORD dwTimerHighValue) { + alarm_expired = 1; +} + +HANDLE hTimer = NULL; +void +set_alarm (int seconds) { + if (hTimer == NULL) + hTimer = CreateWaitableTimer(NULL, TRUE, NULL); + alarm_expired = 0; + + LARGE_INTEGER expTime; + expTime.QuadPart = - (seconds * 10000000); + if (!SetWaitableTimer (hTimer, &expTime, 0, alarm_handler, &alarm_expired, FALSE)) + fprintf (stderr, "SetWaitableTimer failed!\n"); +} +#else +void +alarm_handler (int signal) { + if (signal == SIGALRM) { + alarm_expired = 1; + } +} + +void +set_alarm (int seconds) { + alarm_expired = 0; + signal (SIGALRM, alarm_handler); + alarm (seconds); +} +#endif + +/* timers + alarms! */ + +void +start_timing (bench_timer_t *tr, long *count) { + if (test_seconds == -1) { + if (getenv("TEST_SECONDS")) + test_seconds = strtol(getenv("TEST_SECONDS"), NULL, 0); + else + test_seconds = 5; + } + *count = 0; + timer_start (tr); + set_alarm (test_seconds); +} + +void +stop_timing (bench_timer_t *tr, long count) { + timer_stop (tr); + tr->count = count; +} + +double +timing_result (bench_timer_t *tr) { + return tr->count / timer_elapsed (tr); +}