Skip to content

Commit

Permalink
trace_processor: Add cpuidle state residences
Browse files Browse the repository at this point in the history
Introduce cpuidle states cpu_counter_tracks. Counter tracks are named
cpuidle.{state}, with the state name determined by
/sys/devices/system/cpu/cpu*/cpuidle/state*/name.

Bug: 337135369
Test: build trace_processor locally, run a trace with `cpuidle_period_ms` enabled and check counters/cpu_counter_tracks
Test: diff tests
Change-Id: Ia12f5578d6a754e6ebe7d4fea1d70ab56fddb07a
  • Loading branch information
Nancy Zhao committed Aug 5, 2024
1 parent 892a6b4 commit e8687b8
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,24 @@ TEST_F(ProtoTraceParserTest, LoadCpuFreqKHz) {
EXPECT_EQ(row->ucpu().value, 1u);
}

TEST_F(ProtoTraceParserTest, LoadCpuIdleStats) {
auto* packet = trace_->add_packet();
uint64_t ts = 1000;
packet->set_timestamp(ts);
auto* bundle = packet->set_sys_stats();
auto* cpuidle_state = bundle->add_cpuidle_state();
cpuidle_state->set_cpu_id(0);
auto* cpuidle_state_entry = cpuidle_state->add_cpuidle_state_entry();
cpuidle_state_entry->set_state("mock_state0");
cpuidle_state_entry->set_duration_us(20000);
EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts),
static_cast<double>(20000), TrackId{0u}));
Tokenize();
context_.sorter->ExtractEventsForced();

EXPECT_EQ(context_.storage->track_table().row_count(), 1u);
}

TEST_F(ProtoTraceParserTest, LoadMemInfo) {
auto* packet = trace_->add_packet();
uint64_t ts = 1000;
Expand Down
21 changes: 21 additions & 0 deletions src/trace_processor/importers/proto/system_probes_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,27 @@ void SystemProbesParser::ParseSysStats(int64_t ts, ConstBytes blob) {
context_->event_tracker->PushCounter(
ts, static_cast<double>(thermal.temp()), track);
}

for (auto it = sys_stats.cpuidle_state(); it; ++it) {
ParseCpuIdleStats(ts, *it);
}
}

void SystemProbesParser::ParseCpuIdleStats(int64_t ts, ConstBytes blob) {
protos::pbzero::SysStats::CpuIdleState::Decoder cpuidle_state(blob);
uint32_t cpu_id = cpuidle_state.cpu_id();
for (auto cpuidle_field = cpuidle_state.cpuidle_state_entry(); cpuidle_field;
++cpuidle_field) {
protos::pbzero::SysStats::CpuIdleStateEntry::Decoder idle(*cpuidle_field);
std::string state = idle.state().ToStdString();
uint64_t time = idle.duration_us();

std::string track_name = "cpuidle." + state;
StringId string_id = context_->storage->InternString(track_name.c_str());
TrackId track =
context_->track_tracker->InternCpuCounterTrack(string_id, cpu_id);
context_->event_tracker->PushCounter(ts, static_cast<double>(time), track);
}
}

void SystemProbesParser::ParseProcessTree(ConstBytes blob) {
Expand Down
1 change: 1 addition & 0 deletions src/trace_processor/importers/proto/system_probes_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SystemProbesParser {
void ParseThreadStats(int64_t timestamp, uint32_t pid, ConstBytes);
void ParseDiskStats(int64_t ts, ConstBytes blob);
void ParseProcessFds(int64_t ts, uint32_t pid, ConstBytes);
void ParseCpuIdleStats(int64_t ts, ConstBytes);

TraceProcessorContext* const context_;

Expand Down
2 changes: 2 additions & 0 deletions test/trace_processor/diff_tests/include_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
from diff_tests.parser.parsing.tests_debug_annotation import ParsingDebugAnnotation
from diff_tests.parser.parsing.tests_memory_counters import ParsingMemoryCounters
from diff_tests.parser.parsing.tests_rss_stats import ParsingRssStats
from diff_tests.parser.parsing.tests_sys_stats import ParsingSysStats
from diff_tests.parser.parsing.tests_traced_stats import ParsingTracedStats
from diff_tests.parser.power.tests_energy_breakdown import PowerEnergyBreakdown
from diff_tests.parser.power.tests_entity_state_residency import EntityStateResidency
Expand Down Expand Up @@ -228,6 +229,7 @@ def fetch_all_diff_tests(index_path: str) -> List['testing.TestCase']:
*ParsingDebugAnnotation(index_path, 'parser/parsing',
'ParsingDebugAnnotation').fetch(),
*ParsingRssStats(index_path, 'parser/parsing', 'ParsingRssStats').fetch(),
*ParsingSysStats(index_path, 'parser/parsing', 'ParsingSysStats').fetch(),
*ParsingMemoryCounters(index_path, 'parser/parsing',
'ParsingMemoryCounters').fetch(),
*FtraceCrop(index_path, 'parser/ftrace', 'FtraceCrop').fetch(),
Expand Down
103 changes: 103 additions & 0 deletions test/trace_processor/diff_tests/parser/parsing/tests_sys_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
# Copyright (C) 2024 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License a
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from python.generators.diff_tests.testing import Path, DataPath, Metric
from python.generators.diff_tests.testing import Csv, Json, TextProto
from python.generators.diff_tests.testing import DiffTestBlueprint
from python.generators.diff_tests.testing import TestSuite


class ParsingSysStats(TestSuite):

def test_cpuidle_stats(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
sys_stats {
cpuidle_state {
cpu_id: 0
cpuidle_state_entry {
state: "C8"
duration_us: 486626084
}
}
}
timestamp: 71625871363623
trusted_packet_sequence_id: 2
}
packet {
sys_stats {
cpuidle_state {
cpu_id: 0
cpuidle_state_entry {
state: "C8"
duration_us: 486636254
}
}
}
timestamp: 71626000387166
trusted_packet_sequence_id: 2
}
"""),
query="""
SELECT ts, cct.name, value, cct.cpu
FROM counter c
JOIN cpu_counter_track cct on c.track_id = cct.id
ORDER BY ts;
""",
out=Csv("""
"ts","name","value","cpu"
71625871363623,"cpuidle.C8",486626084.000000,0
71626000387166,"cpuidle.C8",486636254.000000,0
"""))

def test_thermal_zones(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
sys_stats {
thermal_zone {
name: "thermal_zone0"
temp: 29
type: "x86_pkg_temp"
}
}
timestamp: 71625871363623
trusted_packet_sequence_id: 2
}
packet {
sys_stats {
thermal_zone {
name: "thermal_zone0"
temp: 31
type: "x86_pkg_temp"
}
}
timestamp: 71626000387166
trusted_packet_sequence_id: 2
}
"""),
query="""
SELECT c.ts,
t.name,
c.value
FROM counter_track t
JOIN counter c ON t.id = c.track_id
""",
out=Csv("""
"ts","name","value"
71625871363623,"x86_pkg_temp",29.000000
71626000387166,"x86_pkg_temp",31.000000
"""))

0 comments on commit e8687b8

Please sign in to comment.