Merge "Keep raw name of power_rails"
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index 2995192..5ef78a2 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -772,6 +772,8 @@
"benchmark/src/json_reporter.cc",
"benchmark/src/log.h",
"benchmark/src/mutex.h",
+ "benchmark/src/perf_counters.cc",
+ "benchmark/src/perf_counters.h",
"benchmark/src/re.h",
"benchmark/src/reporter.cc",
"benchmark/src/sleep.cc",
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 69cc958..757157f 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -480,9 +480,11 @@
// Write the event itself.
{
+ bool on_current_thread_track =
+ (&track == &TrackEventInternal::kDefaultTrack);
auto event_ctx = TrackEventInternal::WriteEvent(
trace_writer, incr_state, tls_state, static_category,
- event_name, type, trace_timestamp);
+ event_name, type, trace_timestamp, on_current_thread_track);
// Write dynamic categories (except for events that don't require
// categories). For counter events, the counter name (and optional
// category) is stored as part of the track descriptor instead being
@@ -499,7 +501,7 @@
return true;
});
}
- if (&track != &TrackEventInternal::kDefaultTrack)
+ if (!on_current_thread_track)
event_ctx.event()->set_track_uuid(track.uuid);
WriteTrackEventArgs(std::move(event_ctx),
std::forward<Arguments>(args)...);
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index dc3a617..be2c528 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -101,10 +101,12 @@
const auto& config = locked_ds->GetConfig();
disable_incremental_timestamps = config.disable_incremental_timestamps();
filter_debug_annotations = config.filter_debug_annotations();
+ enable_thread_time_sampling = config.enable_thread_time_sampling();
}
}
bool disable_incremental_timestamps = false;
bool filter_debug_annotations = false;
+ bool enable_thread_time_sampling = false;
};
struct TrackEventIncrementalState {
@@ -157,6 +159,7 @@
// counter track. The key (uint64_t) is the uuid of counter track.
// The value is used for delta encoding of counter values.
std::unordered_map<uint64_t, int64_t> last_counter_value_per_track;
+ int64_t last_thread_time_ns = 0;
};
// The backend portion of the track event trace point implemention. Outlined to
@@ -188,7 +191,8 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type,
- const TraceTimestamp& timestamp);
+ const TraceTimestamp& timestamp,
+ bool on_current_thread_track);
static void ResetIncrementalStateIfRequired(
TraceWriterBase* trace_writer,
diff --git a/include/perfetto/tracing/track.h b/include/perfetto/tracing/track.h
index 1ddb85e..cee0be6 100644
--- a/include/perfetto/tracing/track.h
+++ b/include/perfetto/tracing/track.h
@@ -25,6 +25,7 @@
#include "perfetto/tracing/internal/compile_time_hash.h"
#include "perfetto/tracing/platform.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
#include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
@@ -199,6 +200,8 @@
public:
using Unit = perfetto::protos::pbzero::CounterDescriptor::Unit;
+ using CounterType =
+ perfetto::protos::gen::CounterDescriptor::BuiltinCounterType;
// |name| must be a string with static lifetime.
constexpr explicit CounterTrack(const char* name,
@@ -240,27 +243,32 @@
constexpr CounterTrack set_unit(Unit unit) const {
return CounterTrack(uuid, parent_uuid, name_, category_, unit, unit_name_,
- unit_multiplier_, is_incremental_);
+ unit_multiplier_, is_incremental_, type_);
+ }
+
+ constexpr CounterTrack set_type(CounterType type) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
+ unit_multiplier_, is_incremental_, type);
}
constexpr CounterTrack set_unit_name(const char* unit_name) const {
return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name,
- unit_multiplier_, is_incremental_);
+ unit_multiplier_, is_incremental_, type_);
}
constexpr CounterTrack set_unit_multiplier(int64_t unit_multiplier) const {
return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
- unit_multiplier, is_incremental_);
+ unit_multiplier, is_incremental_, type_);
}
constexpr CounterTrack set_category(const char* category) const {
return CounterTrack(uuid, parent_uuid, name_, category, unit_, unit_name_,
- unit_multiplier_, is_incremental_);
+ unit_multiplier_, is_incremental_, type_);
}
constexpr CounterTrack set_is_incremental(bool is_incremental = true) const {
return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
- unit_multiplier_, is_incremental);
+ unit_multiplier_, is_incremental, type_);
}
constexpr bool is_incremental() const { return is_incremental_; }
@@ -276,14 +284,16 @@
Unit unit,
const char* unit_name,
int64_t unit_multiplier,
- bool is_incremental)
+ bool is_incremental,
+ CounterType type)
: Track(uuid_, parent_uuid_),
name_(name),
category_(category),
unit_(unit),
unit_name_(unit_name),
unit_multiplier_(unit_multiplier),
- is_incremental_(is_incremental) {}
+ is_incremental_(is_incremental),
+ type_(type) {}
const char* const name_;
const char* const category_;
@@ -291,6 +301,8 @@
const char* const unit_name_ = nullptr;
int64_t unit_multiplier_ = 1;
const bool is_incremental_ = false;
+ CounterType type_ =
+ perfetto::protos::gen::CounterDescriptor::COUNTER_UNSPECIFIED;
};
namespace internal {
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 5c354e8..cbcc81e 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -1581,6 +1581,16 @@
// TRACE_EVENT macros are not written into the trace. Typed arguments will
// still be emitted even if set to true.
optional bool filter_debug_annotations = 7;
+
+ // Default : false (i.e. disabled)
+ // When true, the SDK samples and emits the current thread time counter value
+ // for each event on the current thread's track. This value represents the
+ // total CPU time consumed by that thread since its creation. Note that if a
+ // thread is not scheduled by OS for some duration, that time won't be
+ // included in thread_time.
+ // Learn more : "CLOCK_THREAD_CPUTIME_ID" flag at
+ // https://linux.die.net/man/3/clock_gettime
+ optional bool enable_thread_time_sampling = 8;
}
// End of protos/perfetto/config/track_event/track_event_config.proto
diff --git a/protos/perfetto/config/track_event/track_event_config.proto b/protos/perfetto/config/track_event/track_event_config.proto
index 3725cd1..983e2c9 100644
--- a/protos/perfetto/config/track_event/track_event_config.proto
+++ b/protos/perfetto/config/track_event/track_event_config.proto
@@ -81,4 +81,14 @@
// TRACE_EVENT macros are not written into the trace. Typed arguments will
// still be emitted even if set to true.
optional bool filter_debug_annotations = 7;
+
+ // Default : false (i.e. disabled)
+ // When true, the SDK samples and emits the current thread time counter value
+ // for each event on the current thread's track. This value represents the
+ // total CPU time consumed by that thread since its creation. Note that if a
+ // thread is not scheduled by OS for some duration, that time won't be
+ // included in thread_time.
+ // Learn more : "CLOCK_THREAD_CPUTIME_ID" flag at
+ // https://linux.die.net/man/3/clock_gettime
+ optional bool enable_thread_time_sampling = 8;
}
diff --git a/protos/perfetto/metrics/android/network_metric.proto b/protos/perfetto/metrics/android/network_metric.proto
index e09c571..5f10d12 100644
--- a/protos/perfetto/metrics/android/network_metric.proto
+++ b/protos/perfetto/metrics/android/network_metric.proto
@@ -92,11 +92,45 @@
optional int64 avg_freq_khz = 5;
}
+ message NetTxActionStatistic {
+ // SoftIrq NET_TX action count.
+ optional int64 count = 1;
+
+ // SoftIrq NET_TX action was running in millisecond.
+ optional double runtime_ms = 2;
+
+ // SoftIrq NET_TX action average running time.
+ optional double avg_runtime_ms = 3;
+
+ // CPU megacycles (i.e. cycles divided by 1e6).
+ optional int64 mcycles = 4;
+
+ // Average weighted CPU frequency by the time the NET_TX Action
+ // running at each frequency.
+ optional int64 avg_freq_khz = 5;
+ }
+
+ message IpiActionStatistic {
+ // SoftIrq IPI action count.
+ optional int64 count = 1;
+
+ // SoftIrq IPI action was running in millisecond.
+ optional double runtime_ms = 2;
+
+ // SoftIrq IPI action average running time.
+ optional double avg_runtime_ms = 3;
+ }
+
message CoreNetRxActionStatistic {
optional uint32 id = 1;
optional NetRxActionStatistic net_rx_action_statistic = 2;
}
+ message CoreNetTxActionStatistic {
+ optional uint32 id = 1;
+ optional NetTxActionStatistic net_tx_action_statistic = 2;
+ }
+
message NetRxAction {
// Total NET_RX action statistics.
optional NetRxActionStatistic total = 1;
@@ -108,6 +142,19 @@
optional double avg_interstack_latency_ms = 3;
}
+ message NetTxAction {
+ // Total NET_TX action statistics.
+ optional NetTxActionStatistic total = 1;
+
+ // Per core NET_TX action statistics.
+ repeated CoreNetTxActionStatistic core = 2;
+ }
+
+ message IpiAction {
+ // Total IPI action statistics.
+ optional IpiActionStatistic total = 1;
+ }
+
// Network device metrics.
repeated NetDevice net_devices = 1;
@@ -120,4 +167,10 @@
// Kfree Skb rate (i.e. kfree_skb count divided by the packet count from all
// net devices).
optional double kfree_skb_rate = 4;
+
+ // SoftIrq NET_TX action metrics.
+ optional NetTxAction net_tx_action = 5;
+
+ // SoftIrq IPI action metrics.
+ optional IpiAction ipi_action = 6;
}
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 97ee857..e7c1262 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -953,11 +953,45 @@
optional int64 avg_freq_khz = 5;
}
+ message NetTxActionStatistic {
+ // SoftIrq NET_TX action count.
+ optional int64 count = 1;
+
+ // SoftIrq NET_TX action was running in millisecond.
+ optional double runtime_ms = 2;
+
+ // SoftIrq NET_TX action average running time.
+ optional double avg_runtime_ms = 3;
+
+ // CPU megacycles (i.e. cycles divided by 1e6).
+ optional int64 mcycles = 4;
+
+ // Average weighted CPU frequency by the time the NET_TX Action
+ // running at each frequency.
+ optional int64 avg_freq_khz = 5;
+ }
+
+ message IpiActionStatistic {
+ // SoftIrq IPI action count.
+ optional int64 count = 1;
+
+ // SoftIrq IPI action was running in millisecond.
+ optional double runtime_ms = 2;
+
+ // SoftIrq IPI action average running time.
+ optional double avg_runtime_ms = 3;
+ }
+
message CoreNetRxActionStatistic {
optional uint32 id = 1;
optional NetRxActionStatistic net_rx_action_statistic = 2;
}
+ message CoreNetTxActionStatistic {
+ optional uint32 id = 1;
+ optional NetTxActionStatistic net_tx_action_statistic = 2;
+ }
+
message NetRxAction {
// Total NET_RX action statistics.
optional NetRxActionStatistic total = 1;
@@ -969,6 +1003,19 @@
optional double avg_interstack_latency_ms = 3;
}
+ message NetTxAction {
+ // Total NET_TX action statistics.
+ optional NetTxActionStatistic total = 1;
+
+ // Per core NET_TX action statistics.
+ repeated CoreNetTxActionStatistic core = 2;
+ }
+
+ message IpiAction {
+ // Total IPI action statistics.
+ optional IpiActionStatistic total = 1;
+ }
+
// Network device metrics.
repeated NetDevice net_devices = 1;
@@ -981,6 +1028,12 @@
// Kfree Skb rate (i.e. kfree_skb count divided by the packet count from all
// net devices).
optional double kfree_skb_rate = 4;
+
+ // SoftIrq NET_TX action metrics.
+ optional NetTxAction net_tx_action = 5;
+
+ // SoftIrq IPI action metrics.
+ optional IpiAction ipi_action = 6;
}
// End of protos/perfetto/metrics/android/network_metric.proto
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 63b058f..27c1e5d 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -1581,6 +1581,16 @@
// TRACE_EVENT macros are not written into the trace. Typed arguments will
// still be emitted even if set to true.
optional bool filter_debug_annotations = 7;
+
+ // Default : false (i.e. disabled)
+ // When true, the SDK samples and emits the current thread time counter value
+ // for each event on the current thread's track. This value represents the
+ // total CPU time consumed by that thread since its creation. Note that if a
+ // thread is not scheduled by OS for some duration, that time won't be
+ // included in thread_time.
+ // Learn more : "CLOCK_THREAD_CPUTIME_ID" flag at
+ // https://linux.die.net/man/3/clock_gettime
+ optional bool enable_thread_time_sampling = 8;
}
// End of protos/perfetto/config/track_event/track_event_config.proto
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index a91d7a9..9c2407b 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/containers/nullable_vector.h b/src/trace_processor/containers/nullable_vector.h
index 2fed430..537e822 100644
--- a/src/trace_processor/containers/nullable_vector.h
+++ b/src/trace_processor/containers/nullable_vector.h
@@ -152,9 +152,8 @@
} else {
valid_.Insert(idx);
- opt_row = valid_.RowOf(idx);
- PERFETTO_DCHECK(opt_row);
- data_.insert(data_.begin() + static_cast<ptrdiff_t>(*opt_row), val);
+ uint32_t inserted_row = *valid_.RowOf(idx);
+ data_.insert(data_.begin() + static_cast<ptrdiff_t>(inserted_row), val);
}
}
}
diff --git a/src/trace_processor/metrics/sql/android/android_netperf.sql b/src/trace_processor/metrics/sql/android/android_netperf.sql
index eb773ab..2f67d67 100644
--- a/src/trace_processor/metrics/sql/android/android_netperf.sql
+++ b/src/trace_processor/metrics/sql/android/android_netperf.sql
@@ -209,6 +209,28 @@
ON s.track_id = t.id
WHERE s.name = "NET_RX";
+DROP VIEW IF EXISTS net_tx_actions;
+CREATE VIEW net_tx_actions AS
+ SELECT
+ s.ts,
+ s.dur,
+ CAST(SUBSTR(t.name, 13, 1) AS int) AS cpu
+ FROM slice s
+ LEFT JOIN track t
+ ON s.track_id = t.id
+ WHERE s.name = "NET_TX";
+
+DROP VIEW IF EXISTS ipi_actions;
+CREATE VIEW ipi_actions AS
+ SELECT
+ s.ts,
+ s.dur,
+ CAST(SUBSTR(t.name, 13, 1) AS int) AS cpu
+ FROM slice s
+ LEFT JOIN track t
+ ON s.track_id = t.id
+ WHERE s.name = "IRQ (IPI)";
+
DROP VIEW IF EXISTS cpu_freq_view;
CREATE VIEW cpu_freq_view AS
SELECT
@@ -225,6 +247,10 @@
CREATE VIRTUAL TABLE cpu_freq_net_rx_action_per_core
USING SPAN_LEFT_JOIN(net_rx_actions PARTITIONED cpu, cpu_freq_view PARTITIONED cpu);
+DROP TABLE IF EXISTS cpu_freq_net_tx_action_per_core;
+CREATE VIRTUAL TABLE cpu_freq_net_tx_action_per_core
+USING SPAN_LEFT_JOIN(net_tx_actions PARTITIONED cpu, cpu_freq_view PARTITIONED cpu);
+
DROP VIEW IF EXISTS total_net_rx_action_statistic;
CREATE VIEW total_net_rx_action_statistic AS
SELECT
@@ -234,12 +260,34 @@
(SELECT COUNT(1) FROM rx_packets) AS total_packet
FROM net_rx_actions;
-DROP VIEW IF EXISTS activated_cores;
-CREATE VIEW activated_cores AS
+DROP VIEW IF EXISTS total_net_tx_action_statistic;
+CREATE VIEW total_net_tx_action_statistic AS
+ SELECT
+ COUNT(1) AS times,
+ SUM(dur) AS runtime,
+ AVG(dur) AS avg_runtime
+ FROM net_tx_actions;
+
+DROP VIEW IF EXISTS total_ipi_action_statistic;
+CREATE VIEW total_ipi_action_statistic AS
+ SELECT
+ COUNT(1) AS times,
+ SUM(dur) AS runtime,
+ AVG(dur) AS avg_runtime
+ FROM ipi_actions;
+
+DROP VIEW IF EXISTS activated_cores_net_rx;
+CREATE VIEW activated_cores_net_rx AS
SELECT
DISTINCT cpu
FROM net_rx_actions;
+DROP VIEW IF EXISTS activated_cores_net_tx;
+CREATE VIEW activated_cores_net_tx AS
+ SELECT
+ DISTINCT cpu
+ FROM net_tx_actions;
+
DROP VIEW IF EXISTS per_core_net_rx_action_statistic;
CREATE VIEW per_core_net_rx_action_statistic AS
SELECT
@@ -253,7 +301,22 @@
'mcycles', (SELECT CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) FROM cpu_freq_net_rx_action_per_core AS cc WHERE cc.cpu = ac.cpu)
)
) AS proto
- FROM activated_cores AS ac;
+ FROM activated_cores_net_rx AS ac;
+
+DROP VIEW IF EXISTS per_core_net_tx_action_statistic;
+CREATE VIEW per_core_net_tx_action_statistic AS
+ SELECT
+ AndroidNetworkMetric_CoreNetTxActionStatistic(
+ 'id', cpu,
+ 'net_tx_action_statistic', AndroidNetworkMetric_NetTxActionStatistic(
+ 'count', (SELECT COUNT(1) FROM net_tx_actions AS na WHERE na.cpu = ac.cpu),
+ 'runtime_ms', (SELECT SUM(dur)/1e6 FROM net_tx_actions AS na WHERE na.cpu = ac.cpu),
+ 'avg_runtime_ms', (SELECT AVG(dur)/1e6 FROM net_tx_actions AS na WHERE na.cpu = ac.cpu),
+ 'avg_freq_khz', (SELECT SUM(dur * freq_khz) / SUM(dur) FROM cpu_freq_net_tx_action_per_core AS cc WHERE cc.cpu = ac.cpu),
+ 'mcycles', (SELECT CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) FROM cpu_freq_net_tx_action_per_core AS cc WHERE cc.cpu = ac.cpu)
+ )
+ ) AS proto
+ FROM activated_cores_net_tx AS ac;
DROP VIEW IF EXISTS android_netperf_output;
CREATE VIEW android_netperf_output AS
@@ -291,6 +354,27 @@
SELECT
cnt * 100.0 / ((SELECT count(1) FROM rx_packets) + (SELECT count(1) FROM tx_packets))
FROM kfree_skb_count
+ ),
+ 'net_tx_action', AndroidNetworkMetric_NetTxAction(
+ 'total', AndroidNetworkMetric_NetTxActionStatistic(
+ 'count', (SELECT times FROM total_net_tx_action_statistic),
+ 'runtime_ms', (SELECT runtime/1e6 FROM total_net_tx_action_statistic),
+ 'avg_runtime_ms', (SELECT avg_runtime/1e6 FROM total_net_tx_action_statistic),
+ 'avg_freq_khz', (SELECT SUM(dur * freq_khz) / SUM(dur) FROM cpu_freq_net_tx_action_per_core),
+ 'mcycles', (SELECT CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) FROM cpu_freq_net_tx_action_per_core)
+ ),
+ 'core', (
+ SELECT
+ RepeatedField(proto)
+ FROM per_core_net_tx_action_statistic
+ )
+ ),
+ 'ipi_action', AndroidNetworkMetric_IpiAction(
+ 'total', AndroidNetworkMetric_IpiActionStatistic(
+ 'count', (SELECT times FROM total_ipi_action_statistic),
+ 'runtime_ms', (SELECT runtime/1e6 FROM total_ipi_action_statistic),
+ 'avg_runtime_ms', (SELECT avg_runtime/1e6 FROM total_ipi_action_statistic)
+ )
)
);
diff --git a/src/trace_processor/sqlite/create_view_function.cc b/src/trace_processor/sqlite/create_view_function.cc
index 211251a..12b4915 100644
--- a/src/trace_processor/sqlite/create_view_function.cc
+++ b/src/trace_processor/sqlite/create_view_function.cc
@@ -186,12 +186,14 @@
return SQLITE_ERROR;
}
- SqlValue::Type type =
- sqlite_utils::SqliteTypeToSqlValueType(sqlite3_value_type(argv[i]));
- if (type != table_->prototype_.arguments[col_to_arg_idx(cs.column)].type) {
+ const auto& arg = table_->prototype_.arguments[col_to_arg_idx(cs.column)];
+ SqlValue::Type expected_type = arg.type;
+ base::Status status = TypeCheckSqliteValue(argv[i], expected_type);
+ if (!status.ok()) {
table_->SetErrorMessage(
- sqlite3_mprintf("%s: type of input argument does not match",
- table_->prototype_.function_name.c_str()));
+ sqlite3_mprintf("%s: argument %s (index %u) %s",
+ table_->prototype_.function_name.c_str(),
+ arg.name.c_str(), i, status.c_message()));
return SQLITE_ERROR;
}
@@ -218,7 +220,9 @@
stmt.reset(stmt_);
if (ret != SQLITE_OK) {
table_->SetErrorMessage(sqlite3_mprintf(
- "%s: SQLite error when preparing statement %s",
+ "%s: Failed to prepare SQL statement for function. "
+ "Check the SQL defintion this function for syntax errors. "
+ "(SQLite error: %s).",
table_->prototype_.function_name.c_str(), sqlite3_errmsg(table_->db_)));
return SQLITE_ERROR;
}
@@ -324,7 +328,7 @@
RETURN_IF_ERROR(ParseFunctionName(prototype_str, function_name));
base::StackString<1024> sql(
- "CREATE OR REPLACE VIRTUAL TABLE %s USING "
+ "CREATE VIRTUAL TABLE IF NOT EXISTS %s USING "
"INTERNAL_VIEW_FUNCTION_IMPL('%s', '%s', '%s');",
function_name.ToStdString().c_str(), prototype_str, return_prototype_str,
sql_defn_str);
diff --git a/src/traced/probes/ftrace/proto_translation_table_unittest.cc b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
index 2748ac9..a157fad 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -379,7 +379,7 @@
std::vector<Event> events;
{
- Event event;
+ Event event{};
event.name = "foo";
event.group = "group_one";
event.ftrace_event_id = 1;
@@ -387,7 +387,7 @@
}
{
- Event event;
+ Event event{};
event.name = "bar";
event.group = "group_one";
event.ftrace_event_id = 2;
@@ -395,7 +395,7 @@
}
{
- Event event;
+ Event event{};
event.name = "baz";
event.group = "group_two";
event.ftrace_event_id = 100;
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 2d4d12a..08b491a 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -339,6 +339,10 @@
incr_state->last_timestamp_ns = sequence_timestamp.value;
auto default_track = ThreadTrack::Current();
+ auto thread_time_counter_track =
+ CounterTrack("thread_time", default_track)
+ .set_is_incremental(true)
+ .set_type(protos::gen::CounterDescriptor::COUNTER_THREAD_TIME_NS);
{
// Mark any incremental state before this point invalid. Also set up
// defaults so that we don't need to repeat constant data for each packet.
@@ -350,6 +354,10 @@
// Establish the default track for this event sequence.
auto track_defaults = defaults->set_track_event_defaults();
track_defaults->set_track_uuid(default_track.uuid);
+ if (tls_state.enable_thread_time_sampling) {
+ track_defaults->add_extra_counter_track_uuids(
+ thread_time_counter_track.uuid);
+ }
if (PERFETTO_LIKELY(!tls_state.disable_incremental_timestamps)) {
defaults->set_timestamp_clock_id(kClockIdIncremental);
@@ -382,6 +390,11 @@
WriteTrackDescriptor(ProcessTrack::Current(), trace_writer, incr_state,
tls_state, sequence_timestamp);
+
+ if (tls_state.enable_thread_time_sampling) {
+ WriteTrackDescriptor(thread_time_counter_track, trace_writer, incr_state,
+ tls_state, sequence_timestamp);
+ }
}
// static
@@ -429,7 +442,8 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type type,
- const TraceTimestamp& timestamp) {
+ const TraceTimestamp& timestamp,
+ bool on_current_thread_track) {
PERFETTO_DCHECK(g_main_thread);
PERFETTO_DCHECK(!incr_state->was_cleared);
auto packet = NewTracePacket(trace_writer, incr_state, tls_state, timestamp);
@@ -439,6 +453,14 @@
if (type != protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
track_event->set_type(type);
+ if (tls_state.enable_thread_time_sampling && on_current_thread_track) {
+ int64_t thread_time_ns = base::GetThreadCPUTimeNs().count();
+ auto thread_time_delta_ns =
+ thread_time_ns - incr_state->last_thread_time_ns;
+ incr_state->last_thread_time_ns = thread_time_ns;
+ track_event->add_extra_counter_values(thread_time_delta_ns);
+ }
+
// We assume that |category| and |name| point to strings with static lifetime.
// This means we can use their addresses as interning keys.
// TODO(skyostil): Intern categories at compile time.
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 0604d09..466c06e 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -144,6 +144,12 @@
return WriteFile(file_name, data.data(), data.size());
}
+// Returns true if the |key| is present in |container|.
+template <typename ContainerType, class KeyType>
+bool ContainsKey(const ContainerType& container, const KeyType& key) {
+ return container.find(key) != container.end();
+}
+
// Represents an opaque (from Perfetto's point of view) thread identifier (e.g.,
// base::PlatformThreadId in Chromium).
struct MyThreadId {
@@ -2144,6 +2150,86 @@
std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
}
+TEST_P(PerfettoApiTest, TrackEventThreadTime) {
+ for (auto enable_thread_time : {true, false}) {
+ perfetto::protos::gen::TrackEventConfig te_cfg;
+ te_cfg.set_enable_thread_time_sampling(enable_thread_time);
+ auto* tracing_session = NewTraceWithCategories({"foo"}, te_cfg);
+
+ tracing_session->get()->StartBlocking();
+
+ perfetto::Track custom_track(1);
+
+ TRACE_EVENT_BEGIN("foo", "event1");
+ TRACE_EVENT_BEGIN("foo", "event2");
+ TRACE_EVENT_BEGIN("foo", "event3");
+ TRACE_EVENT_BEGIN("foo", "event4", custom_track);
+ TRACE_EVENT_END("foo");
+ TRACE_EVENT_END("foo");
+ TRACE_EVENT_END("foo");
+ TRACE_EVENT_END("foo");
+
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+
+ perfetto::protos::gen::Trace parsed_trace;
+ EXPECT_TRUE(
+ parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ bool found_counter_track_descriptor = false;
+ uint64_t thread_time_counter_uuid = 0;
+ uint64_t default_counter_uuid = 0;
+ std::unordered_set<std::string> event_names;
+ for (const auto& packet : parsed_trace.packet()) {
+ if (packet.has_track_descriptor() &&
+ packet.track_descriptor().has_counter()) {
+ EXPECT_FALSE(found_counter_track_descriptor);
+ found_counter_track_descriptor = true;
+ thread_time_counter_uuid = packet.track_descriptor().uuid();
+ EXPECT_EQ("thread_time", packet.track_descriptor().name());
+ auto counter = packet.track_descriptor().counter();
+ EXPECT_EQ(
+ perfetto::protos::gen::
+ CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_TIME_NS,
+ counter.type());
+ EXPECT_TRUE(counter.is_incremental());
+ }
+ if (packet.has_trace_packet_defaults()) {
+ auto& defaults = packet.trace_packet_defaults().track_event_defaults();
+ ASSERT_EQ(enable_thread_time ? 1u : 0u,
+ defaults.extra_counter_track_uuids().size());
+ if (enable_thread_time) {
+ default_counter_uuid = defaults.extra_counter_track_uuids().at(0);
+ }
+ }
+ if (packet.has_track_event()) {
+ std::string event_name;
+ if (packet.has_interned_data()) {
+ auto& event_names_info = packet.interned_data().event_names();
+ if (event_names_info.size() > 0) {
+ event_name = event_names_info[0].name();
+ }
+ }
+ event_names.insert(event_name);
+ EXPECT_EQ((enable_thread_time && event_name != "event4") ? 1u : 0u,
+ packet.track_event().extra_counter_values().size());
+ }
+ }
+ EXPECT_TRUE(ContainsKey(event_names, "event1"));
+ EXPECT_TRUE(ContainsKey(event_names, "event2"));
+ EXPECT_TRUE(ContainsKey(event_names, "event3"));
+ EXPECT_TRUE(ContainsKey(event_names, "event4"));
+ EXPECT_EQ(enable_thread_time, found_counter_track_descriptor);
+ EXPECT_EQ(default_counter_uuid, thread_time_counter_uuid);
+ if (enable_thread_time) {
+ EXPECT_GT(thread_time_counter_uuid, 0u);
+ } else {
+ EXPECT_EQ(thread_time_counter_uuid, 0u);
+ }
+ }
+}
+
TEST_P(PerfettoApiTest, TrackEventArgs_TypedAndUntyped) {
// Create a new trace session.
auto* tracing_session = NewTraceWithCategories({"foo"});
diff --git a/src/tracing/track.cc b/src/tracing/track.cc
index 467a56b..f24138b 100644
--- a/src/tracing/track.cc
+++ b/src/tracing/track.cc
@@ -100,8 +100,16 @@
counter->add_categories(category_);
if (unit_ != perfetto::protos::pbzero::CounterDescriptor::UNIT_UNSPECIFIED)
counter->set_unit(static_cast<protos::gen::CounterDescriptor_Unit>(unit_));
- if (unit_name_)
- counter->set_unit_name(unit_name_);
+ {
+ // if |type| is set, we don't want to emit |unit_name|. Trace processor
+ // infers the track name from the type in that case.
+ if (type_ !=
+ perfetto::protos::gen::CounterDescriptor::COUNTER_UNSPECIFIED) {
+ counter->set_type(type_);
+ } else if (unit_name_) {
+ counter->set_unit_name(unit_name_);
+ }
+ }
if (unit_multiplier_ != 1)
counter->set_unit_multiplier(unit_multiplier_);
if (is_incremental_)
diff --git a/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256 b/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
index 1c1134b..035f335 100644
--- a/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
@@ -1 +1 @@
-582c5550a14de74aabcd2b0342f8295b040febc4cf6bcb4e9fb6cb155e9c8d4d
\ No newline at end of file
+e8ffe0046ea98d27b4216c8d1ff64c665392c90ab3d90e2db99069ae54d12707
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256 b/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
index ce4aadf..d7c7cb9 100644
--- a/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
@@ -1 +1 @@
-72e9695470c9067005bca54fcdee310feaeed23d58d6bf4c2e575748a992027e
\ No newline at end of file
+14e436dda252119dbe75bbe7233e8b62ade69e27bbad311181927c097adb86d0
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
index 3c99db9..b5f3a52 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
@@ -1 +1 @@
-9425ea9f775ab88ebd9d0f47946c0835191a7d4579da40d04f20c9db9d288e95
\ No newline at end of file
+77ead2d35348d988d3938b88fc66f0731f494fb77f2165d3fbddca7f37df97f6
\ No newline at end of file
diff --git a/test/trace_processor/network/netperf_metric.out b/test/trace_processor/network/netperf_metric.out
index cbb642e..14c089c 100644
--- a/test/trace_processor/network/netperf_metric.out
+++ b/test/trace_processor/network/netperf_metric.out
@@ -144,4 +144,40 @@
}
retransmission_rate: 20.0
kfree_skb_rate: 10.0
+ net_tx_action {
+ total {
+ count: 2
+ runtime_ms: 0.04
+ avg_runtime_ms: 0.02
+ mcycles: 0
+ avg_freq_khz: 2000000
+ }
+ core {
+ id: 0
+ net_tx_action_statistic {
+ count: 1
+ runtime_ms: 0.02
+ avg_runtime_ms: 0.02
+ mcycles: 0
+ avg_freq_khz: 2000000
+ }
+ }
+ core {
+ id: 1
+ net_tx_action_statistic {
+ count: 1
+ runtime_ms: 0.02
+ avg_runtime_ms: 0.02
+ mcycles: 0
+ avg_freq_khz: 2000000
+ }
+ }
+ }
+ ipi_action {
+ total {
+ count: 2
+ runtime_ms: 0.02
+ avg_runtime_ms: 0.01
+ }
+ }
}
diff --git a/test/trace_processor/network/netperf_metric.textproto b/test/trace_processor/network/netperf_metric.textproto
index 60d196e..818962d 100644
--- a/test/trace_processor/network/netperf_metric.textproto
+++ b/test/trace_processor/network/netperf_metric.textproto
@@ -88,6 +88,36 @@
vec: 3
}
}
+ event {
+ timestamp: 100505000
+ pid: 200
+ irq_handler_entry {
+ irq: 1
+ name: "IPI"
+ }
+ }
+ event {
+ timestamp: 100515000
+ pid: 200
+ irq_handler_exit {
+ irq: 1
+ ret: 1
+ }
+ }
+ event {
+ timestamp: 100520000
+ pid: 200
+ softirq_entry {
+ vec: 2
+ }
+ }
+ event {
+ timestamp: 100540000
+ pid: 200
+ softirq_exit {
+ vec: 2
+ }
+ }
}
}
@@ -163,11 +193,41 @@
}
}
event {
- timestamp: 120500000
- pid: 300
- softirq_exit {
- vec: 3
- }
+ timestamp: 120500000
+ pid: 300
+ softirq_exit {
+ vec: 3
+ }
+ }
+ event {
+ timestamp: 120505000
+ pid: 200
+ irq_handler_entry {
+ irq: 1
+ name: "IPI"
+ }
+ }
+ event {
+ timestamp: 120515000
+ pid: 200
+ irq_handler_exit {
+ irq: 1
+ ret: 1
+ }
+ }
+ event {
+ timestamp: 120520000
+ pid: 200
+ softirq_entry {
+ vec: 2
+ }
+ }
+ event {
+ timestamp: 120540000
+ pid: 200
+ softirq_exit {
+ vec: 2
+ }
}
}
}
@@ -237,11 +297,11 @@
}
}
event {
- timestamp: 140500000
- pid: 400
- softirq_exit {
- vec: 3
- }
+ timestamp: 140500000
+ pid: 400
+ softirq_exit {
+ vec: 3
+ }
}
}
}
@@ -265,19 +325,19 @@
}
}
event {
- timestamp: 140000000
- pid: 200
- cpu_frequency {
- cpu_id: 1
- state: 1000000
- }
+ timestamp: 140000000
+ pid: 200
+ cpu_frequency {
+ cpu_id: 1
+ state: 1000000
+ }
}
event {
- timestamp: 140000000
- pid: 500
- softirq_entry {
- vec: 3
- }
+ timestamp: 140000000
+ pid: 500
+ softirq_entry {
+ vec: 3
+ }
}
event {
timestamp: 140000000
@@ -296,11 +356,11 @@
}
}
event {
- timestamp: 140500000
- pid: 500
- softirq_exit {
- vec: 3
- }
+ timestamp: 140500000
+ pid: 500
+ softirq_exit {
+ vec: 3
+ }
}
}
}
diff --git a/tools/install-build-deps b/tools/install-build-deps
index de21e94..eeb0130 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -176,7 +176,7 @@
Dependency(
'buildtools/benchmark',
'https://chromium.googlesource.com/external/github.com/google/benchmark.git',
- '090faecb454fbd6e6e17a75ef8146acb037118d4', 'all', 'all'),
+ 'e991355c02b93fe17713efe04cbc2e278e00fdbd', 'all', 'all'),
# Libbacktrace, for stacktraces in Linux/Android debug builds.
# From https://github.com/ianlancetaylor/libbacktrace/archive/177940370e4a6b2509e92a0aaa9749184e64af43.zip
diff --git a/tools/proto_utils.py b/tools/proto_utils.py
index 45fad89..87a3150 100644
--- a/tools/proto_utils.py
+++ b/tools/proto_utils.py
@@ -18,7 +18,7 @@
import subprocess
import tempfile
-from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool
+from google.protobuf import descriptor, descriptor_pb2, message_factory
from google.protobuf import reflection, text_format
@@ -26,14 +26,15 @@
def create_message_factory(descriptor_file_paths, proto_type):
- pool = descriptor_pool.DescriptorPool()
+ files = []
for file_path in descriptor_file_paths:
- descriptor = read_descriptor(file_path)
- for file in descriptor.file:
- pool.Add(file)
+ files.extend(read_descriptor(file_path).file)
- return message_factory.MessageFactory().GetPrototype(
- pool.FindMessageTypeByName(proto_type))
+ # We use this method rather than working directly with DescriptorPool
+ # because, when the pure-Python protobuf runtime is used, extensions
+ # need to be explicitly registered with the message type. See
+ # https://github.com/protocolbuffers/protobuf/blob/9e09343a49e9e75be576b31ed7402bf8502b080c/python/google/protobuf/message_factory.py#L145
+ return message_factory.GetMessages(files)[proto_type]
def read_descriptor(file_name):
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 1f8ca17..e668c86 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -756,10 +756,6 @@
state.extensionInstalled = args.available;
},
- updateBufferUsage(state: StateDraft, args: {percentage: number}): void {
- state.bufferUsage = args.percentage;
- },
-
setRecordingTarget(state: StateDraft, args: {target: RecordingTarget}): void {
state.recordingTarget = args.target;
},
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 6447767..cd8fb60 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -394,8 +394,6 @@
LoadedConfigNone|LoadedConfigAutomatic|LoadedConfigNamed;
export interface State {
- // tslint:disable-next-line:no-any
- [key: string]: any;
version: number;
currentEngineId?: string;
nextId: string;
diff --git a/ui/src/controller/permalink_controller.ts b/ui/src/controller/permalink_controller.ts
index 31a7010..b922e8b 100644
--- a/ui/src/controller/permalink_controller.ts
+++ b/ui/src/controller/permalink_controller.ts
@@ -110,8 +110,9 @@
private static isRecordConfig(stateOrConfig: State|
RecordConfig): stateOrConfig is RecordConfig {
- return ['STOP_WHEN_FULL', 'RING_BUFFER', 'LONG_TRACE'].includes(
- stateOrConfig.mode);
+ const mode = (stateOrConfig as {mode?: string}).mode;
+ return mode !== undefined &&
+ ['STOP_WHEN_FULL', 'RING_BUFFER', 'LONG_TRACE'].includes(mode);
}
private static async createPermalink(isRecordingConfig: boolean):
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 62e9e59..ab76002 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -104,7 +104,6 @@
'android_ion',
'android_lmk',
'android_dma_heap',
- 'android_thread_time_in_state',
'android_surfaceflinger',
'android_batt',
'android_sysui_cuj',
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 88a44ce..d553aa9 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -643,7 +643,7 @@
from thread_counter_track
join thread using(utid)
left join process using(upid)
- where thread_counter_track.name not in ('time_in_state', 'thread_time')
+ where thread_counter_track.name != 'thread_time'
`);
const it = result.iter({
@@ -1102,10 +1102,6 @@
from sched join thread using(utid)
group by upid
) using(upid)
- left join (select upid, max(value) as total_cycles
- from android_thread_time_in_state_event
- group by upid
- ) using(upid)
left join (
select
distinct(upid) as upid,
@@ -1123,7 +1119,6 @@
chromeProcessRank desc,
hasHeapProfiles desc,
total_dur desc,
- total_cycles desc,
the_tracks.upid,
the_tracks.utid;
`);
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index c0977ce..af96463 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -81,7 +81,8 @@
globals.frontendLocalState.mergeState(this.state.frontendLocalState);
// Only redraw if something other than the frontendLocalState changed.
- for (const key in this.state) {
+ let key: keyof State;
+ for (key in this.state) {
if (key !== 'frontendLocalState' && key !== 'visibleTracks' &&
oldState[key] !== this.state[key]) {
globals.rafScheduler.scheduleFullRedraw();