Commit c6c7faf8 authored by Gabriel Marin's avatar Gabriel Marin Committed by Commit Bot

Recognize cycles precise as a CPU cycles event

Updated the microarchitecture based unit tests for default commands to
check that the first two commands are sampling CPU cycles.

BUG=b:170056137

Change-Id: I6a1a91e4f1b35cb0c3e6ef77dc6aa8a297f831ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2450841Reviewed-by: default avatarGabriel Marin <gmx@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Commit-Queue: Gabriel Marin <gmx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814154}
parent 3410532e
...@@ -511,8 +511,11 @@ bool CommandSamplesCPUCycles(const std::vector<std::string>& args) { ...@@ -511,8 +511,11 @@ bool CommandSamplesCPUCycles(const std::vector<std::string>& args) {
// Command must start with "perf record". // Command must start with "perf record".
if (args.size() < 4 || args[0] != "perf" || args[1] != "record") if (args.size() < 4 || args[0] != "perf" || args[1] != "record")
return false; return false;
// Cycles event can be either the raw 'cycles' event, or the event name can be
// annotated with some qualifier suffix. Check for all cases.
for (size_t i = 2; i + 1 < args.size(); ++i) { for (size_t i = 2; i + 1 < args.size(); ++i) {
if (args[i] == "-e" && args[i + 1] == "cycles") if (args[i] == "-e" &&
(args[i + 1] == "cycles" || args[i + 1].rfind("cycles:", 0) == 0))
return true; return true;
} }
return false; return false;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/strings/string_split.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
...@@ -29,6 +30,8 @@ namespace metrics { ...@@ -29,6 +30,8 @@ namespace metrics {
namespace { namespace {
const char kPerfCommandDelimiter[] = " ";
const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003"; const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003";
const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037"; const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
const char kPerfLBRCallgraphCmd[] = const char kPerfLBRCallgraphCmd[] =
...@@ -206,6 +209,16 @@ const base::TimeDelta kPeriodicCollectionInterval = ...@@ -206,6 +209,16 @@ const base::TimeDelta kPeriodicCollectionInterval =
base::TimeDelta::FromHours(1); base::TimeDelta::FromHours(1);
const base::TimeDelta kCollectionDuration = base::TimeDelta::FromSeconds(2); const base::TimeDelta kCollectionDuration = base::TimeDelta::FromSeconds(2);
// A wrapper around internal::CommandSamplesCPUCycles, to test if a perf command
// samples the cycles event. The wrapper takes a command as a string, while the
// wrapped internal::CommandSamplesCPUCycles takes the command split into words.
bool DoesCommandSampleCycles(std::string command) {
std::vector<std::string> cmd_args =
base::SplitString(command, kPerfCommandDelimiter, base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
return internal::CommandSamplesCPUCycles(cmd_args);
}
} // namespace } // namespace
class PerfCollectorTest : public testing::Test { class PerfCollectorTest : public testing::Test {
...@@ -367,7 +380,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_IvyBridge) { ...@@ -367,7 +380,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_IvyBridge) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -398,7 +413,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_SandyBridge) { ...@@ -398,7 +413,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_SandyBridge) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -429,7 +446,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Haswell) { ...@@ -429,7 +446,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Haswell) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
// No LBR callstacks because the kernel is old. // No LBR callstacks because the kernel is old.
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
...@@ -468,7 +487,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Skylake) { ...@@ -468,7 +487,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Skylake) {
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
// We have both FP and LBR based callstacks. // We have both FP and LBR based callstacks.
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphCmd); EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -501,7 +522,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Tigerlake) { ...@@ -501,7 +522,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Tigerlake) {
EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
// We have both FP and LBR based callstacks. // We have both FP and LBR based callstacks.
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphPPPCmd); EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -532,7 +555,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Goldmont) { ...@@ -532,7 +555,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Goldmont) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
// No LBR callstacks because the microarchitecture doesn't support it. // No LBR callstacks because the microarchitecture doesn't support it.
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
...@@ -569,7 +594,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_GoldmontPlus) { ...@@ -569,7 +594,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_GoldmontPlus) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
// No LBR callstacks because the microarchitecture doesn't support it. // No LBR callstacks because the microarchitecture doesn't support it.
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
...@@ -605,7 +632,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Excavator) { ...@@ -605,7 +632,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Excavator) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -625,7 +654,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Arm32) { ...@@ -625,7 +654,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Arm32) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -650,7 +681,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Arm64) { ...@@ -650,7 +681,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Arm64) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -675,7 +708,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_x86_32) { ...@@ -675,7 +708,9 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_x86_32) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
ASSERT_GE(cmds.size(), 2UL); ASSERT_GE(cmds.size(), 2UL);
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd); EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
auto found = auto found =
std::find_if(cmds.begin(), cmds.end(), std::find_if(cmds.begin(), cmds.end(),
[](const RandomSelector::WeightAndValue& cmd) -> bool { [](const RandomSelector::WeightAndValue& cmd) -> bool {
...@@ -700,6 +735,7 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Unknown) { ...@@ -700,6 +735,7 @@ TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Unknown) {
internal::GetDefaultCommandsForCpu(cpuid); internal::GetDefaultCommandsForCpu(cpuid);
EXPECT_EQ(1UL, cmds.size()); EXPECT_EQ(1UL, cmds.size());
EXPECT_EQ(cmds[0].value, kPerfCyclesCmd); EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
} }
TEST_F(PerfCollectorTest, CommandMatching_Empty) { TEST_F(PerfCollectorTest, CommandMatching_Empty) {
...@@ -1083,6 +1119,13 @@ TEST(PerfCollectorInternalTest, CommandSamplesCPUCycles) { ...@@ -1083,6 +1119,13 @@ TEST(PerfCollectorInternalTest, CommandSamplesCPUCycles) {
EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e", EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
"cycles", "-c", "4000037", "cycles", "-c", "4000037",
"--call-graph", "lbr"})); "--call-graph", "lbr"}));
EXPECT_TRUE(internal::CommandSamplesCPUCycles(
{"perf", "record", "-a", "-e", "cycles:ppp", "-c", "1000003"}));
EXPECT_TRUE(internal::CommandSamplesCPUCycles(
{"perf", "record", "-a", "-e", "cycles:ppp", "-g", "-c", "4000037"}));
EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
"cycles:ppp", "-c", "4000037",
"--call-graph", "lbr"}));
EXPECT_FALSE(internal::CommandSamplesCPUCycles( EXPECT_FALSE(internal::CommandSamplesCPUCycles(
{"perf", "record", "-a", "-e", "r20c4", "-b", "-c", "200011"})); {"perf", "record", "-a", "-e", "r20c4", "-b", "-c", "200011"}));
...@@ -1102,6 +1145,9 @@ TEST(PerfCollectorInternalTest, CommandSamplesCPUCycles) { ...@@ -1102,6 +1145,9 @@ TEST(PerfCollectorInternalTest, CommandSamplesCPUCycles) {
EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e", EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
"instructions", "-e", "cycles", "instructions", "-e", "cycles",
"-c", "1000003"})); "-c", "1000003"}));
EXPECT_TRUE(internal::CommandSamplesCPUCycles(
{"perf", "record", "-a", "-e", "instructions", "-e", "cycles:ppp", "-c",
"1000003"}));
EXPECT_FALSE(internal::CommandSamplesCPUCycles( EXPECT_FALSE(internal::CommandSamplesCPUCycles(
{"perf", "stat", "-a", "-e", "cycles", "-e", "instructions"})); {"perf", "stat", "-a", "-e", "cycles", "-e", "instructions"}));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment