Another bulk update of copyright dates
[flac.git] / microbench / util.c
1 /* FLAC - Free Lossless Audio Codec
2  * Copyright (C) 2015-2016  Xiph.Org Foundation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <config.h>
33
34 #include <stdlib.h>
35 #include "util.h"
36
37 #if defined _WIN32
38
39 #include <windows.h>
40
41 static double
42 counter_diff (const LARGE_INTEGER * start, const LARGE_INTEGER * end)
43 {
44         LARGE_INTEGER diff, freq;
45
46         QueryPerformanceFrequency(&freq);
47         diff.QuadPart = end->QuadPart - start->QuadPart;
48
49         return (double)diff.QuadPart/(double)freq.QuadPart;
50 }
51
52 double
53 benchmark_function (void (*testfunc) (void), unsigned count)
54 {
55         LARGE_INTEGER start, end;
56         unsigned k;
57
58         QueryPerformanceCounter (&start) ;
59
60         for (k = 0 ; k < count ; k++)
61                 testfunc();
62
63         QueryPerformanceCounter (&end) ;
64
65         return counter_diff (&start, &end) / count ;
66 } /* benchmark_function */
67
68 #elif defined FLAC__SYS_DARWIN
69
70 #include <mach/mach_time.h>
71
72 static double
73 counter_diff (const uint64_t * start, const uint64_t * end)
74 {
75         mach_timebase_info_data_t t_info;
76         mach_timebase_info(&t_info);
77         uint64_t duration = *end - *start;
78
79         return duration * ((double)t_info.numer/(double)t_info.denom);
80 }
81
82 double
83 benchmark_function (void (*testfunc) (void), unsigned count)
84 {
85         uint64_t start, end;
86         unsigned k;
87
88         start = mach_absolute_time();
89
90         for (k = 0 ; k < count ; k++)
91                 testfunc();
92
93         end = mach_absolute_time();
94
95         return counter_diff (&start, &end) / count ;
96 } /* benchmark_function */
97
98 #elif defined HAVE_CLOCK_GETTIME
99
100 #include <time.h>
101 #include <sys/time.h>
102
103 static double
104 timespec_diff (const struct timespec * start, const struct timespec * end)
105 {       struct timespec diff;
106
107         if (end->tv_nsec - start->tv_nsec < 0)
108         {       diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
109                 diff.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec ;
110                 }
111         else
112         {       diff.tv_sec = end->tv_sec - start->tv_sec ;
113                 diff.tv_nsec = end->tv_nsec-start->tv_nsec ;
114                 } ;
115
116         return diff.tv_sec + 1e-9 * diff.tv_nsec ;
117 }
118
119 double
120 benchmark_function (void (*testfunc) (void), unsigned count)
121 {       struct timespec start, end;
122         unsigned k ;
123
124         clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start) ;
125
126         for (k = 0 ; k < count ; k++)
127                 testfunc () ;
128
129         clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end) ;
130
131         return timespec_diff (&start, &end) / count ;
132 } /* benchmark_function */
133
134 #else
135
136 #include <time.h>
137 #include <sys/time.h>
138
139 static double
140 timeval_diff (const struct timeval * start, const struct timeval * end)
141 {       struct timeval diff;
142
143         if (end->tv_usec - start->tv_usec < 0)
144         {       diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
145                 diff.tv_usec = 1000000 + end->tv_usec - start->tv_usec ;
146                 }
147         else
148         {       diff.tv_sec = end->tv_sec - start->tv_sec ;
149                 diff.tv_usec = end->tv_usec-start->tv_usec ;
150                 } ;
151
152         return diff.tv_sec + 1e-6 * diff.tv_usec ;
153 }
154
155 double
156 benchmark_function (void (*testfunc) (void), unsigned count)
157 {       struct timeval start, end;
158         unsigned k ;
159
160         gettimeofday(&start, NULL);
161
162         for (k = 0 ; k < count ; k++)
163                 testfunc () ;
164
165         gettimeofday(&end, NULL);
166
167         return timeval_diff (&start, &end) / count ;
168 } /* benchmark_function */
169
170 #endif
171
172 static int
173 double_cmp (const void * a, const void * b)
174 {       const double * pa = (double *) a ;
175         const double * pb = (double *) b ;
176         return pa [0] < pb [0] ;
177 } /* double_cmp */
178
179 void
180 benchmark_stats (bench_stats * stats)
181 {       double sum, times [stats->run_count] ;
182         unsigned k ;
183
184         for (k = 0 ; k < stats->run_count ; k++)
185                 times [k] = benchmark_function (stats->testfunc, stats->loop_count) ;
186
187         qsort (times, stats->run_count, sizeof (times [0]), double_cmp) ;
188
189         sum = 0.0 ;
190         stats->min_time = stats->max_time = times [0] ;
191         for (k = 0 ; k < stats->run_count ; k++)
192         {       stats->min_time = stats->min_time < times [k] ? stats->min_time : times [k] ;
193                 stats->max_time = stats->max_time > times [k] ? stats->max_time : times [k] ;
194                 sum += times [k] ;
195                 }
196         stats->mean_time = sum / stats->run_count ;
197         if (stats->run_count & 1)
198                 stats->median_time = times [(stats->run_count + 1) / 2] ;
199         else
200                 stats->median_time = 0.5 * (times [stats->run_count / 2] + times [(stats->run_count / 2) + 1]) ;
201
202         return ;
203 } /* benchmark_stats */