blob: dbd4bc19c6e2a75019b22549b29906d83b2600ac [file] [log] [blame]
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +10001/* FLAC - Free Lossless Audio Codec
2 * Copyright (C) 2015 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
Tristan Matthewsab300d42015-09-29 19:27:48 -040032#include <config.h>
33
Erik de Castro Lopo451efca2015-09-02 16:34:22 +100034#include <stdlib.h>
35#include "util.h"
36
37#if defined _WIN32
38
39#include <windows.h>
40
41static double
42counter_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
52double
53benchmark_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
Tristan Matthewsab300d42015-09-29 19:27:48 -040068#elif defined FLAC__SYS_DARWIN
69
70#include <mach/mach_time.h>
71
72static double
73counter_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
82double
83benchmark_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
Dave Yeo50e7aea2016-02-02 20:19:59 -080098#elif defined HAVE_CLOCK_GETTIME
Erik de Castro Lopo451efca2015-09-02 16:34:22 +100099
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000100#include <time.h>
101#include <sys/time.h>
102
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000103static double
104timespec_diff (const struct timespec * start, const struct timespec * end)
Erik de Castro Lopo4288e442016-01-26 16:20:00 +1100105{ struct timespec diff;
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000106
107 if (end->tv_nsec - start->tv_nsec < 0)
Erik de Castro Lopo4288e442016-01-26 16:20:00 +1100108 { diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
109 diff.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec ;
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000110 }
111 else
Erik de Castro Lopo4288e442016-01-26 16:20:00 +1100112 { diff.tv_sec = end->tv_sec - start->tv_sec ;
113 diff.tv_nsec = end->tv_nsec-start->tv_nsec ;
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000114 } ;
115
Erik de Castro Lopo4288e442016-01-26 16:20:00 +1100116 return diff.tv_sec + 1e-9 * diff.tv_nsec ;
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000117}
118
119double
120benchmark_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
Dave Yeo50e7aea2016-02-02 20:19:59 -0800134#else
135
136#include <time.h>
137#include <sys/time.h>
138
139static double
140timeval_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
155double
156benchmark_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
Erik de Castro Lopo451efca2015-09-02 16:34:22 +1000170#endif
171
Erik de Castro Lopo95fc3bf2015-09-01 03:38:43 +1000172static int
173double_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
179void
180benchmark_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 */