diff options
author | Yabin Cui <yabinc@google.com> | 2018-03-06 11:35:22 -0800 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2018-03-06 11:35:22 -0800 |
commit | 900ea0706e16bd2afc99f95a56b67b364800ad60 (patch) | |
tree | e8dbf7301ce48eb51299fbe8c17555e29d98620d | |
parent | 8e57dc74b071793296389d0d936f385d0949df76 (diff) | |
download | extras-900ea0706e16bd2afc99f95a56b67b364800ad60.tar.gz |
simpleperf: fix calculating cpu frequency.
When calculating cpu frequency and other frequencies, use time
running on cpu instead of total passed time. This is to be
consistent with linux-tools-perf.
This is reported in https://github.com/android-ndk/ndk/issues/644.
Bug: none
Test: run simpleperf_unit_test.
Change-Id: Ic385939c189fb86c6b3c648d2c0a4e9636c13c93
-rw-r--r-- | simpleperf/cmd_debug_unwind_test.cpp | 42 | ||||
-rw-r--r-- | simpleperf/cmd_stat.cpp | 23 | ||||
-rw-r--r-- | simpleperf/cmd_stat_test.cpp | 25 | ||||
-rw-r--r-- | simpleperf/test_util.h | 45 |
4 files changed, 91 insertions, 44 deletions
diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp index 153adb75..7b99afaa 100644 --- a/simpleperf/cmd_debug_unwind_test.cpp +++ b/simpleperf/cmd_debug_unwind_test.cpp @@ -34,48 +34,6 @@ static std::unique_ptr<Command> DebugUnwindCmd() { return CreateCommandInstance("debug-unwind"); } -class CaptureStdout { - public: - CaptureStdout() : started_(false) {} - - ~CaptureStdout() { - if (started_) { - Finish(); - } - } - - bool Start() { - fflush(stdout); - old_stdout_ = dup(STDOUT_FILENO); - if (old_stdout_ == -1) { - return false; - } - started_ = true; - tmpfile_.reset(new TemporaryFile); - if (dup2(tmpfile_->fd, STDOUT_FILENO) == -1) { - return false; - } - return true; - } - - std::string Finish() { - fflush(stdout); - started_ = false; - dup2(old_stdout_, STDOUT_FILENO); - close(old_stdout_); - std::string s; - if (!android::base::ReadFileToString(tmpfile_->path, &s)) { - return ""; - } - return s; - } - - private: - bool started_; - int old_stdout_; - std::unique_ptr<TemporaryFile> tmpfile_; -}; - TEST(cmd_debug_unwind, smoke) { std::string input_data = GetTestData(PERF_DATA_NO_UNWIND); CaptureStdout capture; diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp index 34b4436c..6872a89c 100644 --- a/simpleperf/cmd_stat.cpp +++ b/simpleperf/cmd_stat.cpp @@ -210,7 +210,11 @@ class CounterSummaries { return ""; } if (s.type_name == "cpu-cycles") { - double hz = s.count / (duration_in_sec / s.scale); + double running_time_in_sec; + if (!FindRunningTimeForSummary(s, &running_time_in_sec)) { + return ""; + } + double hz = s.count / (running_time_in_sec / s.scale); return android::base::StringPrintf("%lf%cGHz", hz / 1e9, sap_mid); } if (s.type_name == "instructions" && s.count != 0) { @@ -247,7 +251,11 @@ class CounterSummaries { return android::base::StringPrintf("%f%%%cmiss rate", miss_rate * 100, sap_mid); } } - double rate = s.count / (duration_in_sec / s.scale); + double running_time_in_sec; + if (!FindRunningTimeForSummary(s, &running_time_in_sec)) { + return ""; + } + double rate = s.count / (running_time_in_sec / s.scale); if (rate > 1e9) { return android::base::StringPrintf("%.3lf%cG/sec", rate / 1e9, sap_mid); } @@ -260,6 +268,17 @@ class CounterSummaries { return android::base::StringPrintf("%.3lf%c/sec", rate, sap_mid); } + bool FindRunningTimeForSummary(const CounterSummary& summary, double* running_time_in_sec) { + for (auto& s : summaries_) { + if ((s.type_name == "task-clock" || s.type_name == "cpu-clock") && + s.IsMonitoredAtTheSameTime(summary) && s.count != 0u) { + *running_time_in_sec = s.count / 1e9; + return true; + } + } + return false; + } + private: std::vector<CounterSummary> summaries_; bool csv_; diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp index b6896e14..ae3b0360 100644 --- a/simpleperf/cmd_stat_test.cpp +++ b/simpleperf/cmd_stat_test.cpp @@ -18,6 +18,7 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> +#include <android-base/strings.h> #include <android-base/test_utils.h> #include <thread> @@ -194,3 +195,27 @@ TEST(stat_cmd, sample_speed_should_be_zero) { ASSERT_EQ(attr.attr->freq, 0u); } } + +TEST(stat_cmd, calculating_cpu_frequency) { + CaptureStdout capture; + ASSERT_TRUE(capture.Start()); + ASSERT_TRUE(StatCmd()->Run({"--csv", "--group", "task-clock,cpu-cycles", "sleep", "1"})); + std::string output = capture.Finish(); + double task_clock_in_ms = 0; + uint64_t cpu_cycle_count = 0; + double cpu_frequency = 0; + for (auto& line : android::base::Split(output, "\n")) { + if (line.find("task-clock") != std::string::npos) { + ASSERT_EQ(sscanf(line.c_str(), "%lf(ms)", &task_clock_in_ms), 1); + } else if (line.find("cpu-cycles") != std::string::npos) { + ASSERT_EQ(sscanf(line.c_str(), "%" SCNu64 ",cpu-cycles,%lf", &cpu_cycle_count, + &cpu_frequency), 2); + } + } + ASSERT_NE(task_clock_in_ms, 0.0f); + ASSERT_NE(cpu_cycle_count, 0u); + ASSERT_NE(cpu_frequency, 0.0f); + double calculated_frequency = cpu_cycle_count / task_clock_in_ms / 1e6; + // Accept error up to 1e-3. Because the stat cmd print values with precision 1e-6. + ASSERT_NEAR(cpu_frequency, calculated_frequency, 1e-3); +} diff --git a/simpleperf/test_util.h b/simpleperf/test_util.h index f5fb590f..8768d666 100644 --- a/simpleperf/test_util.h +++ b/simpleperf/test_util.h @@ -19,6 +19,9 @@ #include <string> #include <vector> +#include <android-base/file.h> +#include <android-base/test_utils.h> + #include "read_elf.h" #include "workload.h" @@ -56,3 +59,45 @@ bool IsInNativeAbi(); return; \ } \ } while (0) + +class CaptureStdout { + public: + CaptureStdout() : started_(false) {} + + ~CaptureStdout() { + if (started_) { + Finish(); + } + } + + bool Start() { + fflush(stdout); + old_stdout_ = dup(STDOUT_FILENO); + if (old_stdout_ == -1) { + return false; + } + started_ = true; + tmpfile_.reset(new TemporaryFile); + if (dup2(tmpfile_->fd, STDOUT_FILENO) == -1) { + return false; + } + return true; + } + + std::string Finish() { + fflush(stdout); + started_ = false; + dup2(old_stdout_, STDOUT_FILENO); + close(old_stdout_); + std::string s; + if (!android::base::ReadFileToString(tmpfile_->path, &s)) { + return ""; + } + return s; + } + + private: + bool started_; + int old_stdout_; + std::unique_ptr<TemporaryFile> tmpfile_; +}; |