diff options
author | Yabin Cui <yabinc@google.com> | 2017-08-14 20:51:47 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-14 20:51:47 +0000 |
commit | 78b3cc838795ec468721f896e92bba1a9967dd53 (patch) | |
tree | 3f3395d8b95c15cb731703c28fdd49f9122411af | |
parent | 504d6530084c9424abe4c0e44109b9e76995480d (diff) | |
parent | 80a1e12868bed96aaef78ce5d4abac42e56625ba (diff) | |
download | extras-o-iot-preview-5.tar.gz |
Merge "simpleperf: export more info through report_lib_interface."android-o-iot-preview-5o-iot-preview-5
-rw-r--r-- | simpleperf/cmd_dumprecord.cpp | 37 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 9 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 3 | ||||
-rw-r--r-- | simpleperf/cmd_report_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cpu_hotplug_test.cpp | 13 | ||||
-rw-r--r-- | simpleperf/environment.cpp | 14 | ||||
-rw-r--r-- | simpleperf/gtest_main.cpp | 14 | ||||
-rw-r--r-- | simpleperf/record_file_format.h | 5 | ||||
-rw-r--r-- | simpleperf/record_file_reader.cpp | 54 | ||||
-rw-r--r-- | simpleperf/report_lib_interface.cpp | 47 | ||||
-rw-r--r-- | simpleperf/scripts/simpleperf_report_lib.py | 59 | ||||
-rw-r--r-- | simpleperf/scripts/test.py | 10 | ||||
-rw-r--r-- | simpleperf/testdata/perf_with_trace_offcpu.data | bin | 197611 -> 365681 bytes |
13 files changed, 174 insertions, 93 deletions
diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index dcd7bf47..919b62a4 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -92,7 +92,10 @@ bool DumpRecordCommand::ParseOptions(const std::vector<std::string>& args) { return true; } -static const std::string GetFeatureName(int feature); +static const std::string GetFeatureNameOrUnknown(int feature) { + std::string name = GetFeatureName(feature); + return name.empty() ? android::base::StringPrintf("unknown_feature(%d)", feature) : name; +} void DumpRecordCommand::DumpFileHeader() { const FileHeader& header = record_file_reader_->FileHeader(); @@ -127,38 +130,10 @@ void DumpRecordCommand::DumpFileHeader() { } } for (auto& feature : features) { - printf("feature: %s\n", GetFeatureName(feature).c_str()); + printf("feature: %s\n", GetFeatureNameOrUnknown(feature).c_str()); } } -static const std::string GetFeatureName(int feature) { - static std::map<int, std::string> feature_name_map = { - {FEAT_TRACING_DATA, "tracing_data"}, - {FEAT_BUILD_ID, "build_id"}, - {FEAT_HOSTNAME, "hostname"}, - {FEAT_OSRELEASE, "osrelease"}, - {FEAT_VERSION, "version"}, - {FEAT_ARCH, "arch"}, - {FEAT_NRCPUS, "nrcpus"}, - {FEAT_CPUDESC, "cpudesc"}, - {FEAT_CPUID, "cpuid"}, - {FEAT_TOTAL_MEM, "total_mem"}, - {FEAT_CMDLINE, "cmdline"}, - {FEAT_EVENT_DESC, "event_desc"}, - {FEAT_CPU_TOPOLOGY, "cpu_topology"}, - {FEAT_NUMA_TOPOLOGY, "numa_topology"}, - {FEAT_BRANCH_STACK, "branch_stack"}, - {FEAT_PMU_MAPPINGS, "pmu_mappings"}, - {FEAT_GROUP_DESC, "group_desc"}, - {FEAT_FILE, "file"}, - {FEAT_META_INFO, "meta_info"}, - }; - auto it = feature_name_map.find(feature); - if (it != feature_name_map.end()) { - return it->second; - } - return android::base::StringPrintf("unknown_feature(%d)", feature); -} void DumpRecordCommand::DumpAttrSection() { std::vector<EventAttrWithId> attrs = record_file_reader_->AttrSection(); @@ -189,7 +164,7 @@ bool DumpRecordCommand::DumpFeatureSection() { int feature = pair.first; const auto& section = pair.second; printf("feature section for %s: offset %" PRId64 ", size %" PRId64 "\n", - GetFeatureName(feature).c_str(), section.offset, section.size); + GetFeatureNameOrUnknown(feature).c_str(), section.offset, section.size); if (feature == FEAT_BUILD_ID) { std::vector<BuildIdRecord> records = record_file_reader_->ReadBuildIdFeature(); for (auto& r : records) { diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 6b2be764..c22129a3 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -31,6 +31,9 @@ #include <android-base/parseint.h> #include <android-base/strings.h> #include <android-base/test_utils.h> +#if defined(__ANDROID__) +#include <android-base/properties.h> +#endif #include "command.h" #include "dwarf_unwind.h" @@ -1182,6 +1185,12 @@ bool RecordCommand::DumpMetaInfoFeature() { // By storing event types information in perf.data, the readers of perf.data have the same // understanding of event types, even if they are on another machine. info_map["event_type_info"] = ScopedEventTypes::BuildString(event_selection_set_.GetEvents()); +#if defined(__ANDROID__) + info_map["product_props"] = android::base::StringPrintf("%s:%s:%s", + android::base::GetProperty("ro.product.manufacturer", "").c_str(), + android::base::GetProperty("ro.product.model", "").c_str(), + android::base::GetProperty("ro.product.name", "").c_str()); +#endif return record_file_writer_->WriteMetaInfoFeature(info_map); } diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 56e1b225..47186a55 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -454,6 +454,9 @@ TEST(record_cmd, record_meta_info_feature) { std::unordered_map<std::string, std::string> info_map; ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map)); ASSERT_NE(info_map.find("simpleperf_version"), info_map.end()); +#if defined(__ANDROID__) + ASSERT_NE(info_map.find("product_props"), info_map.end()); +#endif } // See http://b/63135835. diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp index f2741144..05ffc184 100644 --- a/simpleperf/cmd_report_test.cpp +++ b/simpleperf/cmd_report_test.cpp @@ -478,7 +478,7 @@ TEST_F(ReportCommandTest, report_offcpu_time) { bool found = false; for (auto& line : lines) { if (line.find("SleepFunction") != std::string::npos) { - ASSERT_NE(line.find("46.29%"), std::string::npos); + ASSERT_NE(line.find("38.77%"), std::string::npos); found = true; break; } diff --git a/simpleperf/cpu_hotplug_test.cpp b/simpleperf/cpu_hotplug_test.cpp index 16e0e5ce..aca7caa0 100644 --- a/simpleperf/cpu_hotplug_test.cpp +++ b/simpleperf/cpu_hotplug_test.cpp @@ -19,7 +19,7 @@ #include <sys/stat.h> #include <unistd.h> #if defined(__BIONIC__) -#include <sys/system_properties.h> +#include <android-base/properties.h> #endif #include <atomic> @@ -59,25 +59,22 @@ class ScopedMpdecisionKiller { private: bool IsMpdecisionRunning() { - char value[PROP_VALUE_MAX]; - int len = __system_property_get("init.svc.mpdecision", value); - if (len == 0 || (len > 0 && strstr(value, "stopped") != nullptr)) { + std::string value = android::base::GetProperty("init.svc.mpdecision", ""); + if (value.empty() || value.find("stopped") != std::string::npos) { return false; } return true; } void DisableMpdecision() { - int ret = __system_property_set("ctl.stop", "mpdecision"); - CHECK_EQ(0, ret); + CHECK(android::base::SetProperty("ctl.stop", "mpdecision")); // Need to wait until mpdecision is actually stopped. std::this_thread::sleep_for(std::chrono::milliseconds(500)); CHECK(!IsMpdecisionRunning()); } void EnableMpdecision() { - int ret = __system_property_set("ctl.start", "mpdecision"); - CHECK_EQ(0, ret); + CHECK(android::base::SetProperty("ctl.start", "mpdecision")); std::this_thread::sleep_for(std::chrono::milliseconds(500)); CHECK(IsMpdecisionRunning()); } diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp index 79280d10..c936ac80 100644 --- a/simpleperf/environment.cpp +++ b/simpleperf/environment.cpp @@ -35,7 +35,7 @@ #include <procinfo/process.h> #if defined(__ANDROID__) -#include <sys/system_properties.h> +#include <android-base/properties.h> #endif #include "event_type.h" @@ -383,22 +383,22 @@ bool CheckPerfEventLimit() { return true; } #if defined(__ANDROID__) - const char* prop_name = "security.perf_harden"; - char prop_value[PROP_VALUE_MAX]; - if (__system_property_get(prop_name, prop_value) <= 0) { + const std::string prop_name = "security.perf_harden"; + std::string prop_value = android::base::GetProperty(prop_name, ""); + if (prop_value.empty()) { // can't do anything if there is no such property. return true; } - if (strcmp(prop_value, "0") == 0) { + if (prop_value == "0") { return true; } // Try to enable perf_event_paranoid by setprop security.perf_harden=0. - if (__system_property_set(prop_name, "0") == 0) { + if (android::base::SetProperty(prop_name, "0")) { sleep(1); if (can_read_paranoid && ReadPerfEventParanoid(&limit_level) && limit_level <= 1) { return true; } - if (__system_property_get(prop_name, prop_value) > 0 && strcmp(prop_value, "0") == 0) { + if (android::base::GetProperty(prop_name, "") == "0") { return true; } } diff --git a/simpleperf/gtest_main.cpp b/simpleperf/gtest_main.cpp index 42519d52..599bb423 100644 --- a/simpleperf/gtest_main.cpp +++ b/simpleperf/gtest_main.cpp @@ -26,7 +26,7 @@ #include <ziparchive/zip_archive.h> #if defined(__ANDROID__) -#include <sys/system_properties.h> +#include <android-base/properties.h> #endif #include "command.h" @@ -106,26 +106,26 @@ static bool ExtractTestDataFromElfSection() { class ScopedEnablingPerf { public: ScopedEnablingPerf() { - memset(prop_value_, '\0', sizeof(prop_value_)); - __system_property_get("security.perf_harden", prop_value_); + prop_value_ = android::base::GetProperty("security.perf_harden", ""); SetProp("0"); } ~ScopedEnablingPerf() { - if (strlen(prop_value_) != 0) { + if (!prop_value_.empty()) { SetProp(prop_value_); } } private: - void SetProp(const char* value) { - __system_property_set("security.perf_harden", value); + void SetProp(const std::string& value) { + android::base::SetProperty("security.perf_harden", value); + // Sleep one second to wait for security.perf_harden changing // /proc/sys/kernel/perf_event_paranoid. sleep(1); } - char prop_value_[PROP_VALUE_MAX]; + std::string prop_value_; }; class ScopedWorkloadExecutable { diff --git a/simpleperf/record_file_format.h b/simpleperf/record_file_format.h index f9ed6f32..1ddaf002 100644 --- a/simpleperf/record_file_format.h +++ b/simpleperf/record_file_format.h @@ -17,6 +17,8 @@ #ifndef SIMPLE_PERF_RECORD_FILE_FORMAT_H_ #define SIMPLE_PERF_RECORD_FILE_FORMAT_H_ +#include <string> + #include "perf_event.h" /* @@ -91,6 +93,9 @@ enum { FEAT_MAX_NUM = 256, }; +std::string GetFeatureName(int feature_id); +int GetFeatureId(const std::string& feature_name); + struct SectionDesc { uint64_t offset; uint64_t size; diff --git a/simpleperf/record_file_reader.cpp b/simpleperf/record_file_reader.cpp index 67f35bea..38a4b2d6 100644 --- a/simpleperf/record_file_reader.cpp +++ b/simpleperf/record_file_reader.cpp @@ -29,6 +29,46 @@ using namespace PerfFileFormat; +namespace PerfFileFormat { + +static const std::map<int, std::string> feature_name_map = { + {FEAT_TRACING_DATA, "tracing_data"}, + {FEAT_BUILD_ID, "build_id"}, + {FEAT_HOSTNAME, "hostname"}, + {FEAT_OSRELEASE, "osrelease"}, + {FEAT_VERSION, "version"}, + {FEAT_ARCH, "arch"}, + {FEAT_NRCPUS, "nrcpus"}, + {FEAT_CPUDESC, "cpudesc"}, + {FEAT_CPUID, "cpuid"}, + {FEAT_TOTAL_MEM, "total_mem"}, + {FEAT_CMDLINE, "cmdline"}, + {FEAT_EVENT_DESC, "event_desc"}, + {FEAT_CPU_TOPOLOGY, "cpu_topology"}, + {FEAT_NUMA_TOPOLOGY, "numa_topology"}, + {FEAT_BRANCH_STACK, "branch_stack"}, + {FEAT_PMU_MAPPINGS, "pmu_mappings"}, + {FEAT_GROUP_DESC, "group_desc"}, + {FEAT_FILE, "file"}, + {FEAT_META_INFO, "meta_info"}, +}; + +std::string GetFeatureName(int feature_id) { + auto it = feature_name_map.find(feature_id); + return it == feature_name_map.end() ? "" : it->second; +} + +int GetFeatureId(const std::string& feature_name) { + for (auto& pair : feature_name_map) { + if (pair.second == feature_name) { + return pair.first; + } + } + return -1; +} + +} // namespace PerfFileFormat + std::unique_ptr<RecordFileReader> RecordFileReader::CreateInstance(const std::string& filename) { std::string mode = std::string("rb") + CLOSE_ON_EXEC_MODE; FILE* fp = fopen(filename.c_str(), mode.c_str()); @@ -203,6 +243,20 @@ bool RecordFileReader::ReadRecord(std::unique_ptr<Record>& record, } if (record->type() == SIMPLE_PERF_RECORD_EVENT_ID) { ProcessEventIdRecord(*static_cast<EventIdRecord*>(record.get())); + } else if (record->type() == PERF_RECORD_SAMPLE) { + SampleRecord* r = static_cast<SampleRecord*>(record.get()); + // Although we have removed ip == 0 callchains when recording dwarf based callgraph, + // stack frame based callgraph can also generate ip == 0 callchains. Remove them here + // to avoid caller's effort. + if (r->sample_type & PERF_SAMPLE_CALLCHAIN) { + size_t i; + for (i = 0; i < r->callchain_data.ip_nr; ++i) { + if (r->callchain_data.ips[i] == 0) { + break; + } + } + r->callchain_data.ip_nr = i; + } } if (sorted) { record_cache_->Push(std::move(record)); diff --git a/simpleperf/report_lib_interface.cpp b/simpleperf/report_lib_interface.cpp index 79a2103c..88bb4d7e 100644 --- a/simpleperf/report_lib_interface.cpp +++ b/simpleperf/report_lib_interface.cpp @@ -72,9 +72,9 @@ struct CallChain { CallChainEntry* entries; }; -struct MetaInfoEntry { - const char* key; - const char* value; +struct FeatureSection { + const char* data; + uint32_t data_size; }; // Create a new instance, @@ -96,7 +96,7 @@ SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT; CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT; const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT; -MetaInfoEntry* GetNextMetaInfo(ReportLib* report_lib) EXPORT; +FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT; } struct EventAttrWithName { @@ -120,7 +120,6 @@ class ReportLib { current_thread_(nullptr), update_flag_(0), trace_offcpu_(false) { - current_meta_info_.key = current_meta_info_.value = nullptr; } bool SetLogSeverity(const char* log_level); @@ -142,7 +141,7 @@ class ReportLib { CallChain* GetCallChainOfCurrentSample(); const char* GetBuildIdForPath(const char* path); - MetaInfoEntry* GetNextMetaInfo(); + FeatureSection* GetFeatureSection(const char* feature_name); private: Sample* GetCurrentSample(); @@ -164,12 +163,11 @@ class ReportLib { std::string build_id_string_; int update_flag_; std::vector<EventAttrWithName> event_attrs_; - - std::unordered_map<std::string, std::string> meta_info_map_; - MetaInfoEntry current_meta_info_; std::unique_ptr<ScopedEventTypes> scoped_event_types_; bool trace_offcpu_; std::unordered_map<pid_t, std::unique_ptr<SampleRecord>> next_sample_cache_; + FeatureSection feature_section_; + std::vector<char> feature_section_data_; }; bool ReportLib::SetLogSeverity(const char* log_level) { @@ -200,16 +198,17 @@ bool ReportLib::OpenRecordFileIfNecessary() { return false; } record_file_reader_->LoadBuildIdAndFileFeatures(thread_tree_); + std::unordered_map<std::string, std::string> meta_info_map; if (record_file_reader_->HasFeature(PerfFileFormat::FEAT_META_INFO) && - !record_file_reader_->ReadMetaInfoFeature(&meta_info_map_)) { + !record_file_reader_->ReadMetaInfoFeature(&meta_info_map)) { return false; } - auto it = meta_info_map_.find("event_type_info"); - if (it != meta_info_map_.end()) { + auto it = meta_info_map.find("event_type_info"); + if (it != meta_info_map.end()) { scoped_event_types_.reset(new ScopedEventTypes(it->second)); } - it = meta_info_map_.find("trace_offcpu"); - if (it != meta_info_map_.end()) { + it = meta_info_map.find("trace_offcpu"); + if (it != meta_info_map.end()) { trace_offcpu_ = it->second == "true"; } } @@ -387,21 +386,17 @@ const char* ReportLib::GetBuildIdForPath(const char* path) { return build_id_string_.c_str(); } -MetaInfoEntry* ReportLib::GetNextMetaInfo() { +FeatureSection* ReportLib::GetFeatureSection(const char* feature_name) { if (!OpenRecordFileIfNecessary()) { return nullptr; } - auto it = meta_info_map_.begin(); - if (current_meta_info_.key != nullptr) { - it = meta_info_map_.find(current_meta_info_.key); - ++it; - } - if (it == meta_info_map_.end()) { + int feature = PerfFileFormat::GetFeatureId(feature_name); + if (feature == -1 || !record_file_reader_->ReadFeatureSection(feature, &feature_section_data_)) { return nullptr; } - current_meta_info_.key = it->first.c_str(); - current_meta_info_.value = it->second.c_str(); - return ¤t_meta_info_; + feature_section_.data = feature_section_data_.data(); + feature_section_.data_size = feature_section_data_.size(); + return &feature_section_; } // Exported methods working with a client created instance @@ -453,6 +448,6 @@ const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) { return report_lib->GetBuildIdForPath(path); } -MetaInfoEntry* GetNextMetaInfo(ReportLib* report_lib) { - return report_lib->GetNextMetaInfo(); +FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) { + return report_lib->GetFeatureSection(feature_name); } diff --git a/simpleperf/scripts/simpleperf_report_lib.py b/simpleperf/scripts/simpleperf_report_lib.py index 67fdfa3e..385df2f5 100644 --- a/simpleperf/scripts/simpleperf_report_lib.py +++ b/simpleperf/scripts/simpleperf_report_lib.py @@ -83,9 +83,9 @@ class CallChainStructure(ct.Structure): ('entries', ct.POINTER(CallChainEntryStructure))] -class MetaInfoEntryStructure(ct.Structure): - _fields_ = [('key', ct.c_char_p), - ('value', ct.c_char_p)] +class FeatureSectionStructure(ct.Structure): + _fields_ = [('data', ct.POINTER(ct.c_char)), + ('data_size', ct.c_uint32)] # convert char_p to str for python3. @@ -160,8 +160,8 @@ class ReportLib(object): CallChainStructure) self._GetBuildIdForPathFunc = self._lib.GetBuildIdForPath self._GetBuildIdForPathFunc.restype = ct.c_char_p - self._GetNextMetaInfoFunc = self._lib.GetNextMetaInfo - self._GetNextMetaInfoFunc.restype = ct.POINTER(MetaInfoEntryStructure) + self._GetFeatureSection = self._lib.GetFeatureSection + self._GetFeatureSection.restype = ct.POINTER(FeatureSectionStructure) self._instance = self._CreateReportLibFunc() assert(not _is_null(self._instance)) @@ -241,15 +241,52 @@ class ReportLib(object): assert(not _is_null(build_id)) return _char_pt_to_str(build_id) + def GetRecordCmd(self): + if hasattr(self, "record_cmd"): + return self.record_cmd + self.record_cmd = None + feature_data = self._GetFeatureSection(self.getInstance(), _char_pt("cmdline")) + if not _is_null(feature_data): + void_p = ct.cast(feature_data[0].data, ct.c_void_p) + data_size = feature_data[0].data_size + arg_count = ct.cast(void_p, ct.POINTER(ct.c_uint32)).contents.value + void_p.value += 4 + args = [] + for i in range(arg_count): + str_len = ct.cast(void_p, ct.POINTER(ct.c_uint32)).contents.value + void_p.value += 4 + char_p = ct.cast(void_p, ct.POINTER(ct.c_char)) + current_str = "" + for j in range(str_len): + c = bytes_to_str(char_p[j]) + if c != '\0': + current_str += c + if ' ' in current_str: + current_str = '"' + current_str + '"' + args.append(current_str) + void_p.value += str_len + self.record_cmd = " ".join(args) + return self.record_cmd + + def MetaInfo(self): if self.meta_info is None: self.meta_info = {} - while True: - entry = self._GetNextMetaInfoFunc(self.getInstance()) - if _is_null(entry): break - key = _char_pt_to_str(entry[0].key) - value = _char_pt_to_str(entry[0].value) - self.meta_info[key] = value + feature_data = self._GetFeatureSection(self.getInstance(), _char_pt("meta_info")) + if not _is_null(feature_data): + str_list = [] + data = feature_data[0].data + data_size = feature_data[0].data_size + current_str = "" + for i in range(data_size): + c = bytes_to_str(data[i]) + if c != '\0': + current_str += c + else: + str_list.append(current_str) + current_str = "" + for i in range(0, len(str_list), 2): + self.meta_info[str_list[i]] = str_list[i + 1] return self.meta_info def getInstance(self): diff --git a/simpleperf/scripts/test.py b/simpleperf/scripts/test.py index 1a97ab1b..3456af44 100644 --- a/simpleperf/scripts/test.py +++ b/simpleperf/scripts/test.py @@ -697,10 +697,11 @@ class TestReportLib(unittest.TestCase): def test_meta_info(self): self.report_lib.SetRecordFile(os.path.join('testdata', 'perf_with_trace_offcpu.data')) meta_info = self.report_lib.MetaInfo() - self.assertEqual(meta_info["simpleperf_version"], "1.65f91c7ed862") + self.assertTrue("simpleperf_version" in meta_info) self.assertEqual(meta_info["system_wide_collection"], "false") self.assertEqual(meta_info["trace_offcpu"], "true") self.assertEqual(meta_info["event_type_info"], "cpu-cycles,0,0\nsched:sched_switch,2,47") + self.assertTrue("product_props" in meta_info) def test_event_name_from_meta_info(self): self.report_lib.SetRecordFile(os.path.join('testdata', 'perf_with_trace_offcpu.data')) @@ -710,6 +711,11 @@ class TestReportLib(unittest.TestCase): self.assertTrue('sched:sched_switch' in event_names) self.assertTrue('cpu-cycles' in event_names) + def test_record_cmd(self): + self.report_lib.SetRecordFile(os.path.join('testdata', 'perf_with_trace_offcpu.data')) + self.assertEqual(self.report_lib.GetRecordCmd(), + "/data/local/tmp/simpleperf record --trace-offcpu --duration 2 -g ./simpleperf_runtest_run_and_sleep64") + def test_offcpu(self): self.report_lib.SetRecordFile(os.path.join('testdata', 'perf_with_trace_offcpu.data')) total_period = 0 @@ -727,7 +733,7 @@ class TestReportLib(unittest.TestCase): sleep_function_period += sample.period break sleep_percentage = float(sleep_function_period) / total_period - self.assertAlmostEqual(sleep_percentage, 0.4629, delta=0.0001) + self.assertGreater(sleep_percentage, 0.30) def main(): diff --git a/simpleperf/testdata/perf_with_trace_offcpu.data b/simpleperf/testdata/perf_with_trace_offcpu.data Binary files differindex 6d0c5e0a..7d814145 100644 --- a/simpleperf/testdata/perf_with_trace_offcpu.data +++ b/simpleperf/testdata/perf_with_trace_offcpu.data |