From 6d4959c21b0fe3fb4b4ca1758d2a595a43965ee5 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Fri, 1 Sep 2017 15:40:41 -0700 Subject: [PATCH] simpleperf: support --clockid option in record cmd. Setting clockid is supported in kernel 4.x. Whether it is supported by the kernel can be checked via `simpleperf list --show-features`. Bug: http://b/65214671 Test: run simpleperf_unit_test. Change-Id: I6f312cc62893af0fa5092ed91434b6df46435d7f --- simpleperf/cmd_list.cpp | 3 +++ simpleperf/cmd_record.cpp | 31 +++++++++++++++++++++++++++++++ simpleperf/cmd_record_test.cpp | 14 ++++++++++++++ simpleperf/event_selection_set.cpp | 22 ++++++++++++++++++++++ simpleperf/event_selection_set.h | 2 ++ 5 files changed, 72 insertions(+) diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp index 71998146..3b22bdec 100644 --- a/simpleperf/cmd_list.cpp +++ b/simpleperf/cmd_list.cpp @@ -165,6 +165,9 @@ void ListCommand::ShowFeatures() { if (IsDumpingRegsForTracepointEventsSupported()) { printf("trace-offcpu\n"); } + if (IsSettingClockIdSupported()) { + printf("set-clockid\n"); + } } void RegisterListCommand() { diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 85e218ca..d83b2104 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -62,6 +62,13 @@ static std::unordered_map branch_sampling_type_map = { {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL}, }; +static std::unordered_map clockid_map = { + {"realtime", CLOCK_REALTIME}, + {"monotonic", CLOCK_MONOTONIC}, + {"monotonic_raw", CLOCK_MONOTONIC_RAW}, + {"boottime", CLOCK_BOOTTIME}, +}; + // The max size of records dumped by kernel is 65535, and dump stack size // should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528. constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528; @@ -122,6 +129,9 @@ class RecordCommand : public Command { " frame as the method to parse call graph in stack.\n" " Default is dwarf,65528.\n" "-g Same as '--call-graph dwarf'.\n" +"--clockid clock_id Generate timestamps of samples using selected clock.\n" +" Possible values are: realtime, monotonic,\n" +" monotonic_raw, boottime, perf. Default is perf.\n" "--cpu cpu_item1,cpu_item2,...\n" " Collect samples only on the selected cpus. cpu_item can be cpu\n" " number like 1, or cpu range like 0-3.\n" @@ -183,6 +193,7 @@ class RecordCommand : public Command { duration_in_sec_(0), can_dump_kernel_symbols_(true), dump_symbols_(true), + clockid_("perf"), event_selection_set_(false), mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)), record_filename_("perf.data"), @@ -237,6 +248,7 @@ class RecordCommand : public Command { double duration_in_sec_; bool can_dump_kernel_symbols_; bool dump_symbols_; + std::string clockid_; std::vector cpus_; EventSelectionSet event_selection_set_; @@ -498,6 +510,21 @@ bool RecordCommand::ParseOptions(const std::vector& args, << args[i]; return false; } + } else if (args[i] == "--clockid") { + if (!NextArgumentOrError(args, &i)) { + return false; + } + if (args[i] != "perf") { + if (!IsSettingClockIdSupported()) { + LOG(ERROR) << "Setting clockid is not supported by the kernel."; + return false; + } + if (clockid_map.find(args[i]) == clockid_map.end()) { + LOG(ERROR) << "Invalid clockid: " << args[i]; + return false; + } + } + clockid_ = args[i]; } else if (args[i] == "--cpu") { if (!NextArgumentOrError(args, &i)) { return false; @@ -719,6 +746,9 @@ bool RecordCommand::SetEventSelectionFlags() { } } event_selection_set_.SetInherit(child_inherit_); + if (clockid_ != "perf") { + event_selection_set_.SetClockId(clockid_map[clockid_]); + } return true; } @@ -1191,6 +1221,7 @@ bool RecordCommand::DumpMetaInfoFeature() { android::base::GetProperty("ro.product.model", "").c_str(), android::base::GetProperty("ro.product.name", "").c_str()); #endif + info_map["clockid"] = clockid_; return record_file_writer_->WriteMetaInfoFeature(info_map); } diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 47186a55..61228ac5 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -493,3 +493,17 @@ TEST(record_cmd, trace_offcpu_option) { TEST(record_cmd, exit_with_parent_option) { ASSERT_TRUE(RunRecordCmd({"--exit-with-parent"})); } + +TEST(record_cmd, clockid_option) { + if (!IsSettingClockIdSupported()) { + ASSERT_FALSE(RunRecordCmd({"--clockid", "monotonic"})); + } else { + TemporaryFile tmpfile; + ASSERT_TRUE(RunRecordCmd({"--clockid", "monotonic"}, tmpfile.path)); + std::unique_ptr reader = RecordFileReader::CreateInstance(tmpfile.path); + ASSERT_TRUE(reader); + std::unordered_map info_map; + ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map)); + ASSERT_EQ(info_map["clockid"], "monotonic"); + } +} diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index 240f9d42..ebd34773 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -103,6 +103,19 @@ bool IsDumpingRegsForTracepointEventsSupported() { return false; } +bool IsSettingClockIdSupported() { + const EventType* type = FindEventTypeByName("cpu-cycles"); + if (type == nullptr) { + return false; + } + // Check if the kernel supports setting clockid, which was added in kernel 4.0. Just check with + // one clockid is enough. Because all needed clockids were supported before kernel 4.0. + perf_event_attr attr = CreateDefaultPerfEventAttr(*type); + attr.use_clockid = 1; + attr.clockid = CLOCK_MONOTONIC; + return IsEventAttrSupported(attr); +} + bool EventSelectionSet::BuildAndCheckEventSelection( const std::string& event_name, EventSelection* selection) { std::unique_ptr event_type = ParseEventType(event_name); @@ -372,6 +385,15 @@ void EventSelectionSet::SetInherit(bool enable) { } } +void EventSelectionSet::SetClockId(int clock_id) { + for (auto& group : groups_) { + for (auto& selection : group) { + selection.event_attr.use_clockid = 1; + selection.event_attr.clockid = clock_id; + } + } +} + bool EventSelectionSet::NeedKernelSymbol() const { for (const auto& group : groups_) { for (const auto& selection : group) { diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h index cc972bea..7397c6fb 100644 --- a/simpleperf/event_selection_set.h +++ b/simpleperf/event_selection_set.h @@ -101,6 +101,7 @@ class EventSelectionSet { void EnableFpCallChainSampling(); bool EnableDwarfCallChainSampling(uint32_t dump_stack_size); void SetInherit(bool enable); + void SetClockId(int clock_id); bool NeedKernelSymbol() const; void AddMonitoredProcesses(const std::set& processes) { @@ -201,5 +202,6 @@ class EventSelectionSet { bool IsBranchSamplingSupported(); bool IsDwarfCallChainSamplingSupported(); bool IsDumpingRegsForTracepointEventsSupported(); +bool IsSettingClockIdSupported(); #endif // SIMPLE_PERF_EVENT_SELECTION_SET_H_ -- 2.11.0