link lm publicly to FLAC
[flac.git] / microbench / util.c
blob66003d79404bb88f80ddf26480b0ac8404af3fe7
1 /* FLAC - Free Lossless Audio Codec
2 * Copyright (C) 2015-2016 Xiph.Org Foundation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
36 #include <stdlib.h>
37 #include "util.h"
39 #if defined _WIN32
41 #include <windows.h>
43 static double
44 counter_diff (const LARGE_INTEGER * start, const LARGE_INTEGER * end)
46 LARGE_INTEGER diff, freq;
48 QueryPerformanceFrequency(&freq);
49 diff.QuadPart = end->QuadPart - start->QuadPart;
51 return (double)diff.QuadPart/(double)freq.QuadPart;
54 double
55 benchmark_function (void (*testfunc) (void), unsigned count)
57 LARGE_INTEGER start, end;
58 unsigned k;
60 QueryPerformanceCounter (&start) ;
62 for (k = 0 ; k < count ; k++)
63 testfunc();
65 QueryPerformanceCounter (&end) ;
67 return counter_diff (&start, &end) / count ;
68 } /* benchmark_function */
70 #elif defined FLAC__SYS_DARWIN
72 #include <mach/mach_time.h>
74 static double
75 counter_diff (const uint64_t * start, const uint64_t * end)
77 mach_timebase_info_data_t t_info;
78 mach_timebase_info(&t_info);
79 uint64_t duration = *end - *start;
81 return duration * ((double)t_info.numer/(double)t_info.denom);
84 double
85 benchmark_function (void (*testfunc) (void), unsigned count)
87 uint64_t start, end;
88 unsigned k;
90 start = mach_absolute_time();
92 for (k = 0 ; k < count ; k++)
93 testfunc();
95 end = mach_absolute_time();
97 return counter_diff (&start, &end) / count ;
98 } /* benchmark_function */
100 #elif defined HAVE_CLOCK_GETTIME
102 #include <time.h>
103 #include <sys/time.h>
105 static double
106 timespec_diff (const struct timespec * start, const struct timespec * end)
107 { struct timespec diff;
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 ;
113 else
114 { diff.tv_sec = end->tv_sec - start->tv_sec ;
115 diff.tv_nsec = end->tv_nsec-start->tv_nsec ;
118 return diff.tv_sec + 1e-9 * diff.tv_nsec ;
121 double
122 benchmark_function (void (*testfunc) (void), unsigned count)
123 { struct timespec start, end;
124 unsigned k ;
126 clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start) ;
128 for (k = 0 ; k < count ; k++)
129 testfunc () ;
131 clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end) ;
133 return timespec_diff (&start, &end) / count ;
134 } /* benchmark_function */
136 #else
138 #include <time.h>
139 #include <sys/time.h>
141 static double
142 timeval_diff (const struct timeval * start, const struct timeval * end)
143 { struct timeval diff;
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 ;
149 else
150 { diff.tv_sec = end->tv_sec - start->tv_sec ;
151 diff.tv_usec = end->tv_usec-start->tv_usec ;
154 return diff.tv_sec + 1e-6 * diff.tv_usec ;
157 double
158 benchmark_function (void (*testfunc) (void), unsigned count)
159 { struct timeval start, end;
160 unsigned k ;
162 gettimeofday(&start, NULL);
164 for (k = 0 ; k < count ; k++)
165 testfunc () ;
167 gettimeofday(&end, NULL);
169 return timeval_diff (&start, &end) / count ;
170 } /* benchmark_function */
172 #endif
174 static int
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 */
181 void
182 benchmark_stats (bench_stats * stats)
183 { double sum, times [stats->run_count] ;
184 unsigned k ;
186 for (k = 0 ; k < stats->run_count ; k++)
187 times [k] = benchmark_function (stats->testfunc, stats->loop_count) ;
189 qsort (times, stats->run_count, sizeof (times [0]), double_cmp) ;
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] ;
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]) ;
204 return ;
205 } /* benchmark_stats */