OSDN Git Service

simpleperf: support --clockid option in record cmd.
authorYabin Cui <yabinc@google.com>
Fri, 1 Sep 2017 22:40:41 +0000 (15:40 -0700)
committerYabin Cui <yabinc@google.com>
Tue, 5 Sep 2017 19:01:42 +0000 (12:01 -0700)
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
simpleperf/cmd_record.cpp
simpleperf/cmd_record_test.cpp
simpleperf/event_selection_set.cpp
simpleperf/event_selection_set.h

index 7199814..3b22bde 100644 (file)
@@ -165,6 +165,9 @@ void ListCommand::ShowFeatures() {
   if (IsDumpingRegsForTracepointEventsSupported()) {
     printf("trace-offcpu\n");
   }
+  if (IsSettingClockIdSupported()) {
+    printf("set-clockid\n");
+  }
 }
 
 void RegisterListCommand() {
index 85e218c..d83b210 100644 (file)
@@ -62,6 +62,13 @@ static std::unordered_map<std::string, uint64_t> branch_sampling_type_map = {
     {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
 };
 
+static std::unordered_map<std::string, int> 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<int> cpus_;
   EventSelectionSet event_selection_set_;
 
@@ -498,6 +510,21 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& 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);
 }
 
index 47186a5..61228ac 100644 (file)
@@ -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<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile.path);
+    ASSERT_TRUE(reader);
+    std::unordered_map<std::string, std::string> info_map;
+    ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map));
+    ASSERT_EQ(info_map["clockid"], "monotonic");
+  }
+}
index 240f9d4..ebd3477 100644 (file)
@@ -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<EventTypeAndModifier> 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) {
index cc972be..7397c6f 100644 (file)
@@ -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<pid_t>& processes) {
@@ -201,5 +202,6 @@ class EventSelectionSet {
 bool IsBranchSamplingSupported();
 bool IsDwarfCallChainSamplingSupported();
 bool IsDumpingRegsForTracepointEventsSupported();
+bool IsSettingClockIdSupported();
 
 #endif  // SIMPLE_PERF_EVENT_SELECTION_SET_H_