benchmark.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* cpufreq-bench CPUFreq microbenchmark
  2. *
  3. * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #include <stdio.h>
  20. #include <unistd.h>
  21. #include <math.h>
  22. #include "config.h"
  23. #include "system.h"
  24. #include "benchmark.h"
  25. /* Print out progress if we log into a file */
  26. #define show_progress(total_time, progress_time) \
  27. if (config->output != stdout) { \
  28. fprintf(stdout, "Progress: %02lu %%\r", \
  29. (progress_time * 100) / total_time); \
  30. fflush(stdout); \
  31. }
  32. /**
  33. * compute how many rounds of calculation we should do
  34. * to get the given load time
  35. *
  36. * @param load aimed load time in µs
  37. *
  38. * @retval rounds of calculation
  39. **/
  40. unsigned int calculate_timespace(long load, struct config *config)
  41. {
  42. int i;
  43. long long now, then;
  44. unsigned int estimated = GAUGECOUNT;
  45. unsigned int rounds = 0;
  46. unsigned int timed = 0;
  47. if (config->verbose)
  48. printf("calibrating load of %lius, please wait...\n", load);
  49. /* get the initial calculation time for a specific number of rounds */
  50. now = get_time();
  51. ROUNDS(estimated);
  52. then = get_time();
  53. timed = (unsigned int)(then - now);
  54. /* approximation of the wanted load time by comparing with the
  55. * initial calculation time */
  56. for (i = 0; i < 4; i++) {
  57. rounds = (unsigned int)(load * estimated / timed);
  58. dprintf("calibrating with %u rounds\n", rounds);
  59. now = get_time();
  60. ROUNDS(rounds);
  61. then = get_time();
  62. timed = (unsigned int)(then - now);
  63. estimated = rounds;
  64. }
  65. if (config->verbose)
  66. printf("calibration done\n");
  67. return estimated;
  68. }
  69. /**
  70. * benchmark
  71. * generates a specific sleep an load time with the performance
  72. * governor and compares the used time for same calculations done
  73. * with the configured powersave governor
  74. *
  75. * @param config config values for the benchmark
  76. *
  77. **/
  78. void start_benchmark(struct config *config)
  79. {
  80. unsigned int _round, cycle;
  81. long long now, then;
  82. long sleep_time = 0, load_time = 0;
  83. long performance_time = 0, powersave_time = 0;
  84. unsigned int calculations;
  85. unsigned long total_time = 0, progress_time = 0;
  86. sleep_time = config->sleep;
  87. load_time = config->load;
  88. /* For the progress bar */
  89. for (_round = 1; _round <= config->rounds; _round++)
  90. total_time += _round * (config->sleep + config->load);
  91. total_time *= 2; /* powersave and performance cycles */
  92. for (_round = 0; _round < config->rounds; _round++) {
  93. performance_time = 0LL;
  94. powersave_time = 0LL;
  95. show_progress(total_time, progress_time);
  96. /* set the cpufreq governor to "performance" which disables
  97. * P-State switching. */
  98. if (set_cpufreq_governor("performance", config->cpu) != 0)
  99. return;
  100. /* calibrate the calculation time. the resulting calculation
  101. * _rounds should produce a load which matches the configured
  102. * load time */
  103. calculations = calculate_timespace(load_time, config);
  104. if (config->verbose)
  105. printf("_round %i: doing %u cycles with %u calculations"
  106. " for %lius\n", _round + 1, config->cycles,
  107. calculations, load_time);
  108. fprintf(config->output, "%u %li %li ",
  109. _round, load_time, sleep_time);
  110. if (config->verbose)
  111. printf("avarage: %lius, rps:%li\n",
  112. load_time / calculations,
  113. 1000000 * calculations / load_time);
  114. /* do some sleep/load cycles with the performance governor */
  115. for (cycle = 0; cycle < config->cycles; cycle++) {
  116. now = get_time();
  117. usleep(sleep_time);
  118. ROUNDS(calculations);
  119. then = get_time();
  120. performance_time += then - now - sleep_time;
  121. if (config->verbose)
  122. printf("performance cycle took %lius, "
  123. "sleep: %lius, "
  124. "load: %lius, rounds: %u\n",
  125. (long)(then - now), sleep_time,
  126. load_time, calculations);
  127. }
  128. fprintf(config->output, "%li ",
  129. performance_time / config->cycles);
  130. progress_time += sleep_time + load_time;
  131. show_progress(total_time, progress_time);
  132. /* set the powersave governor which activates P-State switching
  133. * again */
  134. if (set_cpufreq_governor(config->governor, config->cpu) != 0)
  135. return;
  136. /* again, do some sleep/load cycles with the
  137. * powersave governor */
  138. for (cycle = 0; cycle < config->cycles; cycle++) {
  139. now = get_time();
  140. usleep(sleep_time);
  141. ROUNDS(calculations);
  142. then = get_time();
  143. powersave_time += then - now - sleep_time;
  144. if (config->verbose)
  145. printf("powersave cycle took %lius, "
  146. "sleep: %lius, "
  147. "load: %lius, rounds: %u\n",
  148. (long)(then - now), sleep_time,
  149. load_time, calculations);
  150. }
  151. progress_time += sleep_time + load_time;
  152. /* compare the avarage sleep/load cycles */
  153. fprintf(config->output, "%li ",
  154. powersave_time / config->cycles);
  155. fprintf(config->output, "%.3f\n",
  156. performance_time * 100.0 / powersave_time);
  157. fflush(config->output);
  158. if (config->verbose)
  159. printf("performance is at %.2f%%\n",
  160. performance_time * 100.0 / powersave_time);
  161. sleep_time += config->sleep_step;
  162. load_time += config->load_step;
  163. }
  164. }