summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2017-08-14 20:51:47 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-08-14 20:51:47 +0000
commit78b3cc838795ec468721f896e92bba1a9967dd53 (patch)
tree3f3395d8b95c15cb731703c28fdd49f9122411af
parent504d6530084c9424abe4c0e44109b9e76995480d (diff)
parent80a1e12868bed96aaef78ce5d4abac42e56625ba (diff)
downloadextras-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.cpp37
-rw-r--r--simpleperf/cmd_record.cpp9
-rw-r--r--simpleperf/cmd_record_test.cpp3
-rw-r--r--simpleperf/cmd_report_test.cpp2
-rw-r--r--simpleperf/cpu_hotplug_test.cpp13
-rw-r--r--simpleperf/environment.cpp14
-rw-r--r--simpleperf/gtest_main.cpp14
-rw-r--r--simpleperf/record_file_format.h5
-rw-r--r--simpleperf/record_file_reader.cpp54
-rw-r--r--simpleperf/report_lib_interface.cpp47
-rw-r--r--simpleperf/scripts/simpleperf_report_lib.py59
-rw-r--r--simpleperf/scripts/test.py10
-rw-r--r--simpleperf/testdata/perf_with_trace_offcpu.databin197611 -> 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 &current_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
index 6d0c5e0a..7d814145 100644
--- a/simpleperf/testdata/perf_with_trace_offcpu.data
+++ b/simpleperf/testdata/perf_with_trace_offcpu.data
Binary files differ