util.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* FLAC - Free Lossless Audio Codec
  2. * Copyright (C) 2015-2023 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. #ifdef HAVE_CONFIG_H
  32. # include <config.h>
  33. #endif
  34. #include <stdlib.h>
  35. #include "util.h"
  36. #if defined _WIN32
  37. #include <windows.h>
  38. static double
  39. counter_diff (const LARGE_INTEGER * start, const LARGE_INTEGER * end)
  40. {
  41. LARGE_INTEGER diff, freq;
  42. QueryPerformanceFrequency(&freq);
  43. diff.QuadPart = end->QuadPart - start->QuadPart;
  44. return (double)diff.QuadPart/(double)freq.QuadPart;
  45. }
  46. double
  47. benchmark_function (void (*testfunc) (void), unsigned count)
  48. {
  49. LARGE_INTEGER start, end;
  50. unsigned k;
  51. QueryPerformanceCounter (&start) ;
  52. for (k = 0 ; k < count ; k++)
  53. testfunc();
  54. QueryPerformanceCounter (&end) ;
  55. return counter_diff (&start, &end) / count ;
  56. } /* benchmark_function */
  57. #elif defined FLAC__SYS_DARWIN
  58. #include <mach/mach_time.h>
  59. static double
  60. counter_diff (const uint64_t * start, const uint64_t * end)
  61. {
  62. mach_timebase_info_data_t t_info;
  63. mach_timebase_info(&t_info);
  64. uint64_t duration = *end - *start;
  65. return duration * ((double)t_info.numer/(double)t_info.denom);
  66. }
  67. double
  68. benchmark_function (void (*testfunc) (void), unsigned count)
  69. {
  70. uint64_t start, end;
  71. unsigned k;
  72. start = mach_absolute_time();
  73. for (k = 0 ; k < count ; k++)
  74. testfunc();
  75. end = mach_absolute_time();
  76. return counter_diff (&start, &end) / count ;
  77. } /* benchmark_function */
  78. #elif defined HAVE_CLOCK_GETTIME
  79. #include <time.h>
  80. #include <sys/time.h>
  81. static double
  82. timespec_diff (const struct timespec * start, const struct timespec * end)
  83. { struct timespec diff;
  84. if (end->tv_nsec - start->tv_nsec < 0)
  85. { diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
  86. diff.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec ;
  87. }
  88. else
  89. { diff.tv_sec = end->tv_sec - start->tv_sec ;
  90. diff.tv_nsec = end->tv_nsec-start->tv_nsec ;
  91. } ;
  92. return diff.tv_sec + 1e-9 * diff.tv_nsec ;
  93. }
  94. double
  95. benchmark_function (void (*testfunc) (void), unsigned count)
  96. { struct timespec start, end;
  97. unsigned k ;
  98. clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start) ;
  99. for (k = 0 ; k < count ; k++)
  100. testfunc () ;
  101. clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end) ;
  102. return timespec_diff (&start, &end) / count ;
  103. } /* benchmark_function */
  104. #else
  105. #include <time.h>
  106. #include <sys/time.h>
  107. static double
  108. timeval_diff (const struct timeval * start, const struct timeval * end)
  109. { struct timeval diff;
  110. if (end->tv_usec - start->tv_usec < 0)
  111. { diff.tv_sec = end->tv_sec - start->tv_sec - 1 ;
  112. diff.tv_usec = 1000000 + end->tv_usec - start->tv_usec ;
  113. }
  114. else
  115. { diff.tv_sec = end->tv_sec - start->tv_sec ;
  116. diff.tv_usec = end->tv_usec-start->tv_usec ;
  117. } ;
  118. return diff.tv_sec + 1e-6 * diff.tv_usec ;
  119. }
  120. double
  121. benchmark_function (void (*testfunc) (void), unsigned count)
  122. { struct timeval start, end;
  123. unsigned k ;
  124. gettimeofday(&start, NULL);
  125. for (k = 0 ; k < count ; k++)
  126. testfunc () ;
  127. gettimeofday(&end, NULL);
  128. return timeval_diff (&start, &end) / count ;
  129. } /* benchmark_function */
  130. #endif
  131. static int
  132. double_cmp (const void * a, const void * b)
  133. { const double * pa = (double *) a ;
  134. const double * pb = (double *) b ;
  135. return pa [0] < pb [0] ;
  136. } /* double_cmp */
  137. void
  138. benchmark_stats (bench_stats * stats)
  139. { double sum, times [stats->run_count] ;
  140. unsigned k ;
  141. for (k = 0 ; k < stats->run_count ; k++)
  142. times [k] = benchmark_function (stats->testfunc, stats->loop_count) ;
  143. qsort (times, stats->run_count, sizeof (times [0]), double_cmp) ;
  144. sum = 0.0 ;
  145. stats->min_time = stats->max_time = times [0] ;
  146. for (k = 0 ; k < stats->run_count ; k++)
  147. { stats->min_time = stats->min_time < times [k] ? stats->min_time : times [k] ;
  148. stats->max_time = stats->max_time > times [k] ? stats->max_time : times [k] ;
  149. sum += times [k] ;
  150. }
  151. stats->mean_time = sum / stats->run_count ;
  152. if (stats->run_count & 1)
  153. stats->median_time = times [(stats->run_count + 1) / 2] ;
  154. else
  155. stats->median_time = 0.5 * (times [stats->run_count / 2] + times [(stats->run_count / 2) + 1]) ;
  156. return ;
  157. } /* benchmark_stats */