perf: Reuse cairo-time

Instead of redefining time getters, use the generic one provided by
_cairo_time_*.
This commit is contained in:
Andrea Canciani 2011-08-31 16:42:03 +02:00
parent 6d6bfbd641
commit 2855ff4666
7 changed files with 67 additions and 422 deletions

View file

@ -48,6 +48,7 @@ cairo_perf_micro_DEPENDENCIES = \
libcairoperf_la_SOURCES = \
$(libcairoperf_sources) \
$(libcairoperf_external_sources)
$(libcairoperf_headers)
cairo_analyse_trace_SOURCES = \

View file

@ -1,11 +1,10 @@
libcairoperf_sources = \
cairo-perf-os2.c \
cairo-perf-posix.c \
cairo-perf-report.c \
cairo-perf-win32.c \
cairo-perf.c \
cairo-stats.c \
$(NULL)
libcairoperf_external_sources = ../src/cairo-time.c
libcairoperf_headers = \
cairo-perf.h \
cairo-stats.h \

View file

@ -1,257 +0,0 @@
/*
* Copyright © 2006 Mozilla Corporation
* Copyright © 2006 Red Hat, Inc.
*
* 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>
*/
/* Portions of this file come from liboil:
*
* LIBOIL - Library of Optimized Inner Loops
* Copyright (c) 2003,2004 David A. Schleef <ds@schleef.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define _XOPEN_SOURCE 600 /* for round() */
#include "cairo-perf.h"
#if !CAIRO_HAS_OS2_SURFACE && !CAIRO_HAS_WIN32_SURFACE
#include "config.h"
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#ifdef _POSIX_PRIORITY_SCHEDULING
#include <sched.h>
#endif
/* timers */
#if defined(HAVE_CLOCK_GETTIME)
#if defined(CLOCK_MONOTONIC_RAW)
#define CLOCK CLOCK_MONOTONIC_RAW
#elif defined(CLOCK_MONOTONIC)
#define CLOCK CLOCK_MONOTONIC
#endif
#endif
#if ! defined(CLOCK)
#if defined(__i386__) || defined(__amd64__)
static inline cairo_perf_ticks_t
oil_profile_stamp_rdtsc (void)
{
unsigned a, d;
__asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d));
return ((uint64_t)a) | (((uint64_t)d) << 32);
}
#define OIL_STAMP oil_profile_stamp_rdtsc
#endif
#if defined(__powerpc__) || defined(__PPC__) || defined(__ppc__)
static inline cairo_perf_ticks_t
oil_profile_stamp_tb (void)
{
uint32_t junk;
uint64_t ts;
__asm__ __volatile__ (
"1: mftbu %1;"
" mftb %0+1;"
" mftbu %0;"
" cmpw %0,%1;"
" bne 1b" :
"=r" (ts), "=r" (junk));
return ts;
}
#define OIL_STAMP oil_profile_stamp_tb
#endif
#if defined(__alpha__)
static inline cairo_perf_ticks_t
oil_profile_stamp_alpha (void)
{
unsigned int ts;
__asm__ __volatile__ ("rpcc %0\n" : "=r"(ts));
return ts;
}
#define OIL_STAMP oil_profile_stamp_alpha
#endif
#if defined(__s390__)
static cairo_perf_ticks_t
oil_profile_stamp_s390 (void)
{
uint64_t ts;
__asm__ __volatile__ ("STCK %0\n" : : "m" (ts));
return ts;
}
#define OIL_STAMP oil_profile_stamp_s390
#endif
#endif
#if defined(__APPLE__)
#include <mach/mach_time.h>
#undef OIL_STAMP
#define OIL_STAMP mach_absolute_time
#endif
typedef struct _cairo_perf_timer {
#if defined(CLOCK)
struct timespec tv_start;
struct timespec tv_stop;
#elif defined(OIL_STAMP)
cairo_perf_ticks_t start;
cairo_perf_ticks_t stop;
#else
struct timeval tv_start;
struct timeval tv_stop;
#endif
} cairo_perf_timer_t;
static cairo_perf_timer_t timer;
static cairo_perf_timer_synchronize_t cairo_perf_timer_synchronize = NULL;
static void *cairo_perf_timer_synchronize_closure = NULL;
void
cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
void *closure)
{
cairo_perf_timer_synchronize = synchronize;
cairo_perf_timer_synchronize_closure = closure;
}
void
cairo_perf_timer_start (void)
{
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
#if defined(CLOCK)
clock_gettime (CLOCK, &timer.tv_start);
#elif defined(OIL_STAMP)
timer.start = OIL_STAMP ();
#else
gettimeofday (&timer.tv_start, NULL);
#endif
}
void
cairo_perf_timer_stop (void)
{
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
#if defined(CLOCK)
clock_gettime (CLOCK, &timer.tv_stop);
#elif defined(OIL_STAMP)
timer.stop = OIL_STAMP ();
#else
gettimeofday (&timer.tv_stop, NULL);
#endif
}
cairo_perf_ticks_t
cairo_perf_timer_elapsed (void)
{
cairo_perf_ticks_t ticks;
#if defined(CLOCK)
ticks = timer.tv_stop.tv_sec - timer.tv_start.tv_sec;
ticks *= 1000000000;
ticks += timer.tv_stop.tv_nsec - timer.tv_start.tv_nsec;
#elif defined(OIL_STAMP)
ticks = timer.stop - timer.start;
#else
ticks = timer.tv_stop.tv_sec - timer.tv_start.tv_sec;
ticks *= 1000000;
ticks += timer.tv_stop.tv_usec - timer.tv_start.tv_usec;
#endif
return ticks;
}
cairo_perf_ticks_t
cairo_perf_ticks_per_second (void)
{
#if defined(CLOCK)
/* For clock_gettime() the units are nano-seconds */
return 1000000000;
#elif defined(OIL_STAMP)
static cairo_perf_ticks_t tps = 0;
/* XXX: This is obviously not stable in light of changing CPU speed. */
if (tps == 0) {
struct timeval tv_start, tv_stop;
double tv_elapsed;
cairo_perf_timer_start ();
gettimeofday (&tv_start, NULL);
usleep (20000);
cairo_perf_timer_stop ();
gettimeofday (&tv_stop, NULL);
tv_elapsed = ((tv_stop.tv_sec - tv_start.tv_sec) +
+ (tv_stop.tv_usec - tv_start.tv_usec) / 1000000.0);
tps = round (cairo_perf_timer_elapsed () / tv_elapsed);
}
return tps;
#else
/* For gettimeofday() the units are micro-seconds */
return 1000000;
#endif
}
/* yield */
void
cairo_perf_yield (void)
{
#ifdef _POSIX_PRIORITY_SCHEDULING
sched_yield ();
#endif
}
#endif /* !CAIRO_HAS_OS2_SURFACE && !CAIRO_HAS_WIN32_SURFACE */

View file

@ -1,93 +0,0 @@
/*
* Copyright © 2006 Mozilla Corporation
* Copyright © 2006 Red Hat, Inc.
*
* 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>
*/
#include "cairo-perf.h"
#if CAIRO_HAS_WIN32_SURFACE
#define USE_WINAPI
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* timers */
typedef struct _cairo_perf_timer
{
LARGE_INTEGER start;
LARGE_INTEGER stop;
} cairo_perf_timer_t;
static cairo_perf_timer_t timer;
static cairo_perf_timer_synchronize_t cairo_perf_timer_synchronize = NULL;
static void *cairo_perf_timer_synchronize_closure = NULL;
void
cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
void *closure)
{
cairo_perf_timer_synchronize = synchronize;
cairo_perf_timer_synchronize_closure = closure;
}
void
cairo_perf_timer_start (void) {
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
QueryPerformanceCounter(&timer.start);
}
void
cairo_perf_timer_stop (void) {
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
QueryPerformanceCounter(&timer.stop);
}
cairo_perf_ticks_t
cairo_perf_timer_elapsed (void) {
return (timer.stop.QuadPart - timer.start.QuadPart);
}
cairo_perf_ticks_t
cairo_perf_ticks_per_second (void) {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return freq.QuadPart;
}
/* yield */
void
cairo_perf_yield (void) {
SleepEx(0, TRUE);
}
#endif /* CAIRO_HAS_WIN32_SURFACE */

View file

@ -2,6 +2,7 @@
* Copyright (c) 2007 Netlabs
* Copyright (c) 2006 Mozilla Corporation
* Copyright (c) 2006 Red Hat, Inc.
* Copyright (c) 2011 Andrea Canciani
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
@ -25,27 +26,32 @@
* Authors: Peter Weilbacher <mozilla@weilbacher.org>
* Vladimir Vukicevic <vladimir@pobox.com> (win32/linux code)
* Carl Worth <cworth@cworth.org> (win32/linux code)
* Andrea Canciani <ranma42@gmail.com>
*/
#include "cairo-perf.h"
#include "../src/cairo-time-private.h"
#if CAIRO_HAS_OS2_SURFACE
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(__OS2__)
#define INCL_BASE
#include <os2.h>
#elif defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(_POSIX_PRIORITY_SCHEDULING)
#include <sched.h>
#endif
/* timers */
typedef struct _cairo_perf_timer
{
/* make them double so that they can store the full QWORD precision */
double start;
double stop;
} cairo_perf_timer_t;
static cairo_perf_timer_t timer;
static cairo_time_t timer;
static cairo_perf_timer_synchronize_t cairo_perf_timer_synchronize = NULL;
static void *cairo_perf_timer_synchronize_closure = NULL;
void
cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
void *closure)
@ -55,45 +61,41 @@ cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
}
void
cairo_perf_timer_start (void) {
QWORD time;
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
DosTmrQueryTime(&time);
timer.start = (time.ulHi*4294967296.0 + time.ulLo);
cairo_perf_timer_start (void)
{
timer = _cairo_time_get ();
}
void
cairo_perf_timer_stop (void) {
QWORD time;
if (cairo_perf_timer_synchronize)
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
DosTmrQueryTime(&time);
timer.stop = (time.ulHi*4294967296.0 + time.ulLo);
cairo_perf_timer_stop (void)
{
timer = _cairo_time_get_delta (timer);
}
cairo_perf_ticks_t
cairo_perf_timer_elapsed (void) {
ULONG freq;
DosTmrQueryFreq(&freq);
/* return time difference in milliseconds */
return (timer.stop - timer.start) / freq * 1000;
cairo_time_t
cairo_perf_timer_elapsed (void)
{
return timer;
}
cairo_perf_ticks_t
cairo_perf_ticks_per_second (void) {
return 1000; /* in ms */
cairo_time_t
cairo_perf_ticks_per_second (void)
{
return _cairo_time_from_s (1.);
}
/* yield */
void
cairo_perf_yield (void) {
cairo_perf_yield (void)
{
/* try to deactivate this thread until the scheduler calls it again */
DosSleep (0);
}
#endif /* CAIRO_HAS_OS2_SURFACE */
#if defined(__OS2__)
DosSleep (0);
#elif defined(_WIN32)
SleepEx(0, TRUE);
#elif defined(_POSIX_PRIORITY_SCHEDULING)
sched_yield ();
#else
sleep (0);
#endif
}

View file

@ -29,9 +29,10 @@
#define _CAIRO_PERF_H_
#include "cairo-boilerplate.h"
#include "../src/cairo-time-private.h"
#include <stdio.h>
typedef uint64_t cairo_perf_ticks_t;
typedef cairo_time_t cairo_perf_ticks_t;
typedef struct _cairo_stats {
cairo_perf_ticks_t min_ticks;

View file

@ -25,26 +25,13 @@
#include "cairo-stats.h"
static int
_cairo_perf_ticks_cmp (const void *_a,
const void *_b)
{
const cairo_perf_ticks_t *a = _a;
const cairo_perf_ticks_t *b = _b;
if (*a > *b)
return 1;
if (*a < *b)
return -1;
return 0;
}
void
_cairo_stats_compute (cairo_stats_t *stats,
cairo_perf_ticks_t *values,
int num_values)
{
int i;
cairo_time_t sumtime;
double sum, mean, delta, q1, q3, iqr;
double outlier_min, outlier_max;
int min_valid, num_valid;
@ -60,41 +47,46 @@ _cairo_stats_compute (cairo_stats_t *stats,
* Q1).
*/
qsort (values, num_values,
sizeof (cairo_perf_ticks_t), _cairo_perf_ticks_cmp);
sizeof (cairo_perf_ticks_t), _cairo_time_cmp);
q1 = values[(1*num_values)/4];
q3 = values[(3*num_values)/4];
q1 = _cairo_time_to_s (values[(1*num_values)/4]);
q3 = _cairo_time_to_s (values[(3*num_values)/4]);
iqr = q3 - q1;
outlier_min = q1 - 1.5 * iqr;
outlier_max = q3 + 1.5 * iqr;
outlier_min = _cairo_time_from_s (q1 - 1.5 * iqr);
outlier_max = _cairo_time_from_s (q3 + 1.5 * iqr);
min_valid = 0;
while (min_valid < num_values && values[min_valid] < outlier_min)
while (min_valid < num_values &&
_cairo_time_to_s (values[min_valid]) < outlier_min)
{
min_valid++;
}
i = min_valid;
num_valid = 0;
while (i + num_valid < num_values && values[i+num_valid] <= outlier_max)
while (i + num_valid < num_values &&
_cairo_time_to_s (values[i+num_valid]) <= outlier_max)
{
num_valid++;
}
stats->iterations = num_valid;
stats->min_ticks = values[min_valid];
sum = 0.0;
sumtime = _cairo_time_from_s (0);
for (i = min_valid; i < min_valid + num_valid; i++) {
sum += values[i];
if (values[i] < stats->min_ticks)
stats->min_ticks = values[i];
sumtime = _cairo_time_add (sumtime, values[i]);
stats->min_ticks = _cairo_time_min (stats->min_ticks, values[i]);
}
mean = sum / num_valid;
mean = _cairo_time_to_s (sumtime) / num_valid;
stats->median_ticks = values[min_valid + num_valid / 2];
sum = 0.0;
for (i = min_valid; i < min_valid + num_valid; i++) {
delta = values[i] - mean;
delta = _cairo_time_to_s (values[i]) - mean;
sum += delta * delta;
}