• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef HAVE_CONFIG_H
33 #  include <config.h>
34 #endif
35 
36 #include <stdlib.h>
37 #include "util.h"
38 
39 #if defined _WIN32
40 
41 #include <windows.h>
42 
43 static double
counter_diff(const LARGE_INTEGER * start,const LARGE_INTEGER * end)44 counter_diff (const LARGE_INTEGER * start, const LARGE_INTEGER * end)
45 {
46 	LARGE_INTEGER diff, freq;
47 
48 	QueryPerformanceFrequency(&freq);
49 	diff.QuadPart = end->QuadPart - start->QuadPart;
50 
51 	return (double)diff.QuadPart/(double)freq.QuadPart;
52 }
53 
54 double
benchmark_function(void (* testfunc)(void),unsigned count)55 benchmark_function (void (*testfunc) (void), unsigned count)
56 {
57 	LARGE_INTEGER start, end;
58 	unsigned k;
59 
60 	QueryPerformanceCounter (&start) ;
61 
62 	for (k = 0 ; k < count ; k++)
63 		testfunc();
64 
65 	QueryPerformanceCounter (&end) ;
66 
67 	return counter_diff (&start, &end) / count ;
68 } /* benchmark_function */
69 
70 #elif defined FLAC__SYS_DARWIN
71 
72 #include <mach/mach_time.h>
73 
74 static double
counter_diff(const uint64_t * start,const uint64_t * end)75 counter_diff (const uint64_t * start, const uint64_t * end)
76 {
77 	mach_timebase_info_data_t t_info;
78 	mach_timebase_info(&t_info);
79 	uint64_t duration = *end - *start;
80 
81 	return duration * ((double)t_info.numer/(double)t_info.denom);
82 }
83 
84 double
benchmark_function(void (* testfunc)(void),unsigned count)85 benchmark_function (void (*testfunc) (void), unsigned count)
86 {
87 	uint64_t start, end;
88 	unsigned k;
89 
90 	start = mach_absolute_time();
91 
92 	for (k = 0 ; k < count ; k++)
93 		testfunc();
94 
95 	end = mach_absolute_time();
96 
97 	return counter_diff (&start, &end) / count ;
98 } /* benchmark_function */
99 
100 #elif defined HAVE_CLOCK_GETTIME
101 
102 #include <time.h>
103 #include <sys/time.h>
104 
105 static double
timespec_diff(const struct timespec * start,const struct timespec * end)106 timespec_diff (const struct timespec * start, const struct timespec * end)
107 {	struct timespec diff;
108 
109 	if (end->tv_nsec - start->tv_nsec < 0)
110 	{	diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
111 		diff.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec ;
112 		}
113 	else
114 	{	diff.tv_sec = end->tv_sec - start->tv_sec ;
115 		diff.tv_nsec = end->tv_nsec-start->tv_nsec ;
116 		} ;
117 
118 	return diff.tv_sec + 1e-9 * diff.tv_nsec ;
119 }
120 
121 double
benchmark_function(void (* testfunc)(void),unsigned count)122 benchmark_function (void (*testfunc) (void), unsigned count)
123 {	struct timespec start, end;
124 	unsigned k ;
125 
126 	clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start) ;
127 
128 	for (k = 0 ; k < count ; k++)
129 		testfunc () ;
130 
131 	clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end) ;
132 
133 	return timespec_diff (&start, &end) / count ;
134 } /* benchmark_function */
135 
136 #else
137 
138 #include <time.h>
139 #include <sys/time.h>
140 
141 static double
timeval_diff(const struct timeval * start,const struct timeval * end)142 timeval_diff (const struct timeval * start, const struct timeval * end)
143 {       struct timeval diff;
144 
145         if (end->tv_usec - start->tv_usec < 0)
146         {       diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
147                 diff.tv_usec = 1000000 + end->tv_usec - start->tv_usec ;
148                 }
149         else
150         {       diff.tv_sec = end->tv_sec - start->tv_sec ;
151                 diff.tv_usec = end->tv_usec-start->tv_usec ;
152                 } ;
153 
154         return diff.tv_sec + 1e-6 * diff.tv_usec ;
155 }
156 
157 double
benchmark_function(void (* testfunc)(void),unsigned count)158 benchmark_function (void (*testfunc) (void), unsigned count)
159 {	struct timeval start, end;
160 	unsigned k ;
161 
162 	gettimeofday(&start, NULL);
163 
164 	for (k = 0 ; k < count ; k++)
165 		testfunc () ;
166 
167 	gettimeofday(&end, NULL);
168 
169 	return timeval_diff (&start, &end) / count ;
170 } /* benchmark_function */
171 
172 #endif
173 
174 static int
double_cmp(const void * a,const void * b)175 double_cmp (const void * a, const void * b)
176 {	const double * pa = (double *) a ;
177 	const double * pb = (double *) b ;
178 	return pa [0] < pb [0] ;
179 } /* double_cmp */
180 
181 void
benchmark_stats(bench_stats * stats)182 benchmark_stats (bench_stats * stats)
183 {	double sum, times [stats->run_count] ;
184 	unsigned k ;
185 
186 	for (k = 0 ; k < stats->run_count ; k++)
187 		times [k] = benchmark_function (stats->testfunc, stats->loop_count) ;
188 
189 	qsort (times, stats->run_count, sizeof (times [0]), double_cmp) ;
190 
191 	sum = 0.0 ;
192 	stats->min_time = stats->max_time = times [0] ;
193 	for (k = 0 ; k < stats->run_count ; k++)
194 	{	stats->min_time = stats->min_time < times [k] ? stats->min_time : times [k] ;
195 		stats->max_time = stats->max_time > times [k] ? stats->max_time : times [k] ;
196 		sum += times [k] ;
197 		}
198 	stats->mean_time = sum / stats->run_count ;
199 	if (stats->run_count & 1)
200 		stats->median_time = times [(stats->run_count + 1) / 2] ;
201 	else
202 		stats->median_time = 0.5 * (times [stats->run_count / 2] + times [(stats->run_count / 2) + 1]) ;
203 
204 	return ;
205 } /* benchmark_stats */
206