Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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 | |
| 20 | #include <stdio.h> |
| 21 | #include <unistd.h> |
| 22 | #include <math.h> |
| 23 | |
| 24 | #include "config.h" |
| 25 | #include "system.h" |
| 26 | #include "benchmark.h" |
| 27 | |
| 28 | /* Print out progress if we log into a file */ |
| 29 | #define show_progress(total_time, progress_time) \ |
| 30 | if (config->output != stdout) { \ |
| 31 | fprintf(stdout, "Progress: %02lu %%\r", \ |
| 32 | (progress_time * 100) / total_time); \ |
| 33 | fflush(stdout); \ |
| 34 | } |
| 35 | |
| 36 | /** |
| 37 | * compute how many rounds of calculation we should do |
| 38 | * to get the given load time |
| 39 | * |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 40 | * @param load aimed load time in µs |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 41 | * |
| 42 | * @retval rounds of calculation |
| 43 | **/ |
| 44 | |
| 45 | unsigned int calculate_timespace(long load, struct config *config) |
| 46 | { |
| 47 | int i; |
| 48 | long long now, then; |
| 49 | unsigned int estimated = GAUGECOUNT; |
| 50 | unsigned int rounds = 0; |
| 51 | unsigned int timed = 0; |
| 52 | |
| 53 | if (config->verbose) |
| 54 | printf("calibrating load of %lius, please wait...\n", load); |
| 55 | |
| 56 | /* get the initial calculation time for a specific number of rounds */ |
| 57 | now = get_time(); |
| 58 | ROUNDS(estimated); |
| 59 | then = get_time(); |
| 60 | |
| 61 | timed = (unsigned int)(then - now); |
| 62 | |
| 63 | /* approximation of the wanted load time by comparing with the |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 64 | * initial calculation time */ |
| 65 | for (i = 0; i < 4; i++) { |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 66 | rounds = (unsigned int)(load * estimated / timed); |
| 67 | dprintf("calibrating with %u rounds\n", rounds); |
| 68 | now = get_time(); |
| 69 | ROUNDS(rounds); |
| 70 | then = get_time(); |
| 71 | |
| 72 | timed = (unsigned int)(then - now); |
| 73 | estimated = rounds; |
| 74 | } |
| 75 | if (config->verbose) |
| 76 | printf("calibration done\n"); |
| 77 | |
| 78 | return estimated; |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * benchmark |
| 83 | * generates a specific sleep an load time with the performance |
| 84 | * governor and compares the used time for same calculations done |
| 85 | * with the configured powersave governor |
| 86 | * |
| 87 | * @param config config values for the benchmark |
| 88 | * |
| 89 | **/ |
| 90 | |
| 91 | void start_benchmark(struct config *config) |
| 92 | { |
| 93 | unsigned int _round, cycle; |
| 94 | long long now, then; |
| 95 | long sleep_time = 0, load_time = 0; |
| 96 | long performance_time = 0, powersave_time = 0; |
| 97 | unsigned int calculations; |
| 98 | unsigned long total_time = 0, progress_time = 0; |
| 99 | |
| 100 | sleep_time = config->sleep; |
| 101 | load_time = config->load; |
| 102 | |
| 103 | /* For the progress bar */ |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 104 | for (_round = 1; _round <= config->rounds; _round++) |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 105 | total_time += _round * (config->sleep + config->load); |
| 106 | total_time *= 2; /* powersave and performance cycles */ |
| 107 | |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 108 | for (_round = 0; _round < config->rounds; _round++) { |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 109 | performance_time = 0LL; |
| 110 | powersave_time = 0LL; |
| 111 | |
| 112 | show_progress(total_time, progress_time); |
| 113 | |
| 114 | /* set the cpufreq governor to "performance" which disables |
| 115 | * P-State switching. */ |
| 116 | if (set_cpufreq_governor("performance", config->cpu) != 0) |
| 117 | return; |
| 118 | |
| 119 | /* calibrate the calculation time. the resulting calculation |
| 120 | * _rounds should produce a load which matches the configured |
| 121 | * load time */ |
| 122 | calculations = calculate_timespace(load_time, config); |
| 123 | |
| 124 | if (config->verbose) |
| 125 | printf("_round %i: doing %u cycles with %u calculations" |
| 126 | " for %lius\n", _round + 1, config->cycles, |
| 127 | calculations, load_time); |
| 128 | |
| 129 | fprintf(config->output, "%u %li %li ", |
| 130 | _round, load_time, sleep_time); |
| 131 | |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 132 | if (config->verbose) |
| 133 | printf("avarage: %lius, rps:%li\n", |
| 134 | load_time / calculations, |
| 135 | 1000000 * calculations / load_time); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 136 | |
| 137 | /* do some sleep/load cycles with the performance 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 | performance_time += then - now - sleep_time; |
| 144 | if (config->verbose) |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 145 | printf("performance cycle took %lius, " |
| 146 | "sleep: %lius, " |
| 147 | "load: %lius, rounds: %u\n", |
| 148 | (long)(then - now), sleep_time, |
| 149 | load_time, calculations); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 150 | } |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 151 | fprintf(config->output, "%li ", |
| 152 | performance_time / config->cycles); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 153 | |
| 154 | progress_time += sleep_time + load_time; |
| 155 | show_progress(total_time, progress_time); |
| 156 | |
| 157 | /* set the powersave governor which activates P-State switching |
| 158 | * again */ |
| 159 | if (set_cpufreq_governor(config->governor, config->cpu) != 0) |
| 160 | return; |
| 161 | |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 162 | /* again, do some sleep/load cycles with the |
| 163 | * powersave governor */ |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 164 | for (cycle = 0; cycle < config->cycles; cycle++) { |
| 165 | now = get_time(); |
| 166 | usleep(sleep_time); |
| 167 | ROUNDS(calculations); |
| 168 | then = get_time(); |
| 169 | powersave_time += then - now - sleep_time; |
| 170 | if (config->verbose) |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 171 | printf("powersave cycle took %lius, " |
| 172 | "sleep: %lius, " |
| 173 | "load: %lius, rounds: %u\n", |
| 174 | (long)(then - now), sleep_time, |
| 175 | load_time, calculations); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | progress_time += sleep_time + load_time; |
| 179 | |
| 180 | /* compare the avarage sleep/load cycles */ |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 181 | fprintf(config->output, "%li ", |
| 182 | powersave_time / config->cycles); |
| 183 | fprintf(config->output, "%.3f\n", |
| 184 | performance_time * 100.0 / powersave_time); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 185 | fflush(config->output); |
| 186 | |
| 187 | if (config->verbose) |
Dominik Brodowski | 02af3cb | 2011-04-19 19:20:12 +0200 | [diff] [blame] | 188 | printf("performance is at %.2f%%\n", |
| 189 | performance_time * 100.0 / powersave_time); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 190 | |
| 191 | sleep_time += config->sleep_step; |
| 192 | load_time += config->load_step; |
| 193 | } |
| 194 | } |