/* cpufreq-bench CPUFreq microbenchmark * * Copyright (C) 2008 Christian Kornacker * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "config.h" #include "system.h" #include "benchmark.h" /** * compute how many rounds of calculation we should do * to get the given load time * * @param load aimed load time in µs * * @retval rounds of calculation **/ unsigned int calculate_timespace(long load) { int i; long long now, then; unsigned int estimated = GAUGECOUNT; unsigned int rounds = 0; unsigned int timed = 0; printf("calibrating load of %lius, please wait...\n", load); /* get the initial calculation time for a specific number of rounds */ now = get_time(); ROUNDS(estimated); then = get_time(); timed = (unsigned int)(then - now); /* approximation of the wanted load time by comparing with the * initial calculation time */ for (i= 0; i < 4; i++) { rounds = (unsigned int)(load * estimated / timed); dprintf("calibrating with %u rounds\n", rounds); now = get_time(); ROUNDS(rounds); then = get_time(); timed = (unsigned int)(then - now); estimated = rounds; } printf("calibration done\n"); return estimated; } /** * benchmark * generates a specific sleep an load time with the performance * governor and compares the used time for same calculations done * with the configured powersave governor * * @param config config values for the benchmark * **/ void start_benchmark(struct config *config) { int round, cycle; long long now, then; long sleep_time = 0, load_time = 0; long performance_time = 0, powersave_time = 0; unsigned int calculations; sleep_time = config->sleep; load_time = config->load; for (round=0; round < config->rounds; round++) { performance_time = 0LL; powersave_time = 0LL; /* set the cpufreq governor to "performance" which disables * P-State switching. */ if (set_cpufreq_governor("performance", config->cpu) != 0) return; printf("round %i: doing %u cycles with %u calculations for %lius\n", round + 1, config->cycles, calculations, load_time); /* calibrate the calculation time. the resulting calculation * rounds should produce a load which matches the configured * load time */ calculations = calculate_timespace(load_time); fprintf(config->output, "%li %li %li %u ", load_time, sleep_time, load_time / calculations, calculations); if (config->verbose) { printf("avarage: %lius, rps:%li\n", load_time / calculations, 1000000 * calculations / load_time); } /* do some sleep/load cycles and determine the avarege time we need * for one cycle */ for (cycle = 0; cycle < config->cycles; cycle++) { now = get_time(); usleep(sleep_time); ROUNDS(calculations); then = get_time(); performance_time += then - now - sleep_time; if (config->verbose) printf("performance cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", (long)(then - now), sleep_time, load_time, calculations); } fprintf(config->output, "%li ", performance_time / config->cycles); /* set the powersave governor which activates P-State switching * again */ if (set_cpufreq_governor(config->governor, config->cpu) != 0) return; /* again, do some sleep/load cycles with the powersave governor */ for (cycle = 0; cycle < config->cycles; cycle++) { now = get_time(); usleep(sleep_time); ROUNDS(calculations); then = get_time(); powersave_time += then - now - sleep_time; if (config->verbose) printf("powersave cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", (long)(then - now), sleep_time, load_time, calculations); } /* compare the avarage sleep/load cycles */ fprintf(config->output, "%li ", powersave_time / config->cycles); fprintf(config->output, "%.3f\n", performance_time * 100.0 / powersave_time); if (config->verbose) printf("performance is at %.2f%%\n", performance_time * 100.0 / powersave_time); sleep_time += config->sleep_step; load_time += config->load_step; } }