Merge changes I6be837f9,I516669d3
* changes:
Proto filter: adds plumbing into tracing service
Proto filtering: add core MessageFilter and FilterUtil
diff --git a/debian/compat b/debian/compat
index f599e28..b1bd38b 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-10
+13
diff --git a/debian/control b/debian/control
index 28fcef2..94a03bb 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@
Section: kernel
Priority: optional
Maintainer: Sami Kyostila <skyostil@google.com>
-Build-Depends: debhelper (>= 10),
+Build-Depends: debhelper (>= 13),
generate-ninja,
git,
libprotoc-dev,
@@ -11,14 +11,15 @@
python3,
zlib1g-dev,
zlib1g
-Standards-Version: 3.9.8
+Standards-Version: 4.5.1
Homepage: https://perfetto.dev
Vcs-Git: https://android.googlesource.com/platform/external/perfetto/
Vcs-Browser: https://android.googlesource.com/platform/external/perfetto/
+Rules-Requires-Root: no
Package: perfetto
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, zlib1g
+Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, zlib1g
Description: Performance instrumentation and logging framework
Perfetto is a performance instrumentation and logging framework for POSIX
systems.
diff --git a/debian/copyright b/debian/copyright
index e23f57d..7b7058c 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -4,12 +4,12 @@
Files: *
Copyright: Copyright (C) 2017 The Android Open Source Project
-License: Apache 2
+License: Apache-2
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 at
.
- http://www.apache.org/licenses/LICENSE-2.0
+ /usr/share/common-licenses/Apache-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/debian/postinst b/debian/postinst
index 7d7e266..e6cdff5 100755
--- a/debian/postinst
+++ b/debian/postinst
@@ -3,3 +3,5 @@
adduser --home /nonexistent --quiet --system --no-create-home --group traced
addgroup --quiet --system traced-consumer
usermod -a -G traced-consumer traced
+
+#DEBHELPER#
diff --git a/debian/postrm b/debian/postrm
index 20c9767..efa1590 100755
--- a/debian/postrm
+++ b/debian/postrm
@@ -1,3 +1,5 @@
#!/bin/sh
set -e
rm -f /tmp/perfetto-consumer /tmp/perfetto-producer
+
+#DEBHELPER#
diff --git a/debian/rules b/debian/rules
index 2b0e32c..a081c5c 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,4 +1,9 @@
#!/usr/bin/make -f
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/buildflags.mk
+
%:
dh $@
@@ -24,7 +29,7 @@
enable_perfetto_unittests=false perfetto_use_system_protobuf=true\
perfetto_use_system_zlib=true perfetto_enable_git_rev_version_header=false\
extra_cflags=\"${CFLAGS}\" extra_cxxflags=\"${CXXFLAGS}\"\
- extra_ldflags=\"${CXXFLAGS}\" cc=\"${CC}\" cxx=\"${CXX}\"\
+ extra_ldflags=\"${LDFLAGS}\" cc=\"${CC}\" cxx=\"${CXX}\"\
${MAYBE_HOST_CPU}"
override_dh_auto_build:
diff --git a/debian/traced-perf.service b/debian/traced-perf.service
index b04463b..73bffb9 100644
--- a/debian/traced-perf.service
+++ b/debian/traced-perf.service
@@ -1,5 +1,6 @@
[Unit]
Description=Perfetto sampling and profiling data source
+Documentation=https://perfetto.dev/docs/
[Service]
ExecStart=/usr/sbin/traced_perf
diff --git a/debian/traced-probes.service b/debian/traced-probes.service
index 81a23f7..1d853b0 100644
--- a/debian/traced-probes.service
+++ b/debian/traced-probes.service
@@ -1,5 +1,6 @@
[Unit]
Description=Perfetto data sources for system tracing (ftrace and /proc pollers)
+Documentation=https://perfetto.dev/docs/
[Service]
ExecStart=/usr/sbin/traced_probes
diff --git a/debian/traced.service b/debian/traced.service
index 6eb7d8a..4ca8d7a 100644
--- a/debian/traced.service
+++ b/debian/traced.service
@@ -1,5 +1,6 @@
[Unit]
Description=Perfetto tracing service daemon
+Documentation=https://perfetto.dev/docs/
[Service]
ExecStart=/usr/sbin/traced \
diff --git a/include/perfetto/ext/base/thread_task_runner.h b/include/perfetto/ext/base/thread_task_runner.h
index d4e672e..5f5947e 100644
--- a/include/perfetto/ext/base/thread_task_runner.h
+++ b/include/perfetto/ext/base/thread_task_runner.h
@@ -32,7 +32,7 @@
// * the UnixTaskRunner will be constructed and destructed on the task thread.
// * the task thread will live for the lifetime of the UnixTaskRunner.
//
-class ThreadTaskRunner : public TaskRunner {
+class PERFETTO_EXPORT ThreadTaskRunner : public TaskRunner {
public:
static ThreadTaskRunner CreateAndStart(const std::string& name = "") {
return ThreadTaskRunner(name);
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 5eec2e2..5b0f2b6 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -621,6 +621,12 @@
// Introduced in Android 12.
repeated string heaps = 20;
+ // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
+ // combination with all_heaps;
+ //
+ // Introduced in Android 12.
+ repeated string exclude_heaps = 27;
+
optional bool stream_allocations = 23;
// If given, needs to be the same length as heaps and gives the sampling
diff --git a/protos/perfetto/config/profiling/heapprofd_config.proto b/protos/perfetto/config/profiling/heapprofd_config.proto
index 2d8654c..00dd692 100644
--- a/protos/perfetto/config/profiling/heapprofd_config.proto
+++ b/protos/perfetto/config/profiling/heapprofd_config.proto
@@ -81,6 +81,12 @@
// Introduced in Android 12.
repeated string heaps = 20;
+ // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
+ // combination with all_heaps;
+ //
+ // Introduced in Android 12.
+ repeated string exclude_heaps = 27;
+
optional bool stream_allocations = 23;
// If given, needs to be the same length as heaps and gives the sampling
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index f9d963a..402fae8 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -621,6 +621,12 @@
// Introduced in Android 12.
repeated string heaps = 20;
+ // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
+ // combination with all_heaps;
+ //
+ // Introduced in Android 12.
+ repeated string exclude_heaps = 27;
+
optional bool stream_allocations = 23;
// If given, needs to be the same length as heaps and gives the sampling
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index 16da1fa..dfc6922 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -149,10 +149,13 @@
cli_config->adaptive_sampling_max_sampling_interval_bytes =
heapprofd_config.adaptive_sampling_max_sampling_interval_bytes();
size_t n = 0;
+ const std::vector<std::string>& exclude_heaps = heapprofd_config.exclude_heaps();
+ // heaps[i] and heaps_interval[i] represent that the heap named in heaps[i]
+ // should be sampled with sampling interval of heap_interval[i].
std::vector<std::string> heaps = heapprofd_config.heaps();
std::vector<uint64_t> heap_intervals =
heapprofd_config.heap_sampling_intervals();
- if (heaps.empty()) {
+ if (heaps.empty() && !cli_config->all_heaps) {
heaps.push_back("libc.malloc");
}
@@ -169,6 +172,15 @@
PERFETTO_ELOG("zero sampling interval.");
return false;
}
+ if (!exclude_heaps.empty()) {
+ // For disabled heaps, we add explicit entries but with sampling interval
+ // 0. The consumer of the sampling intervals in ClientConfiguration,
+ // GetSamplingInterval in wire_protocol.h, uses 0 to signal a heap is
+ // disabled, either because it isn't enabled (all_heaps is not set, and the
+ // heap isn't named), or because we explicitely set it here.
+ heaps.insert(heaps.end(), exclude_heaps.cbegin(), exclude_heaps.cend());
+ heap_intervals.insert(heap_intervals.end(), exclude_heaps.size(), 0u);
+ }
if (heaps.size() > base::ArraySize(cli_config->heaps)) {
heaps.resize(base::ArraySize(cli_config->heaps));
PERFETTO_ELOG("Too many heaps requested. Truncating.");
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index 8a75145..fa08e95 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -202,5 +202,42 @@
4 * 4096u);
}
+TEST(HeapprofdConfigToClientConfigurationTest, AllHeaps) {
+ HeapprofdConfig cfg;
+ cfg.set_all_heaps(true);
+ cfg.set_sampling_interval_bytes(4096);
+ ClientConfiguration cli_config;
+ ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
+ EXPECT_EQ(cli_config.num_heaps, 0u);
+ EXPECT_EQ(cli_config.default_interval, 4096u);
+}
+
+TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndExplicit) {
+ HeapprofdConfig cfg;
+ cfg.set_all_heaps(true);
+ cfg.set_sampling_interval_bytes(4096);
+ cfg.add_heaps("foo");
+ cfg.add_heap_sampling_intervals(1024u);
+ ClientConfiguration cli_config;
+ ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
+ EXPECT_EQ(cli_config.num_heaps, 1u);
+ EXPECT_STREQ(cli_config.heaps[0].name, "foo");
+ EXPECT_EQ(cli_config.heaps[0].interval, 1024u);
+ EXPECT_EQ(cli_config.default_interval, 4096u);
+}
+
+TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndDisabled) {
+ HeapprofdConfig cfg;
+ cfg.set_all_heaps(true);
+ cfg.set_sampling_interval_bytes(4096);
+ cfg.add_exclude_heaps("foo");
+ ClientConfiguration cli_config;
+ ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
+ EXPECT_EQ(cli_config.num_heaps, 1u);
+ EXPECT_STREQ(cli_config.heaps[0].name, "foo");
+ EXPECT_EQ(cli_config.heaps[0].interval, 0u);
+ EXPECT_EQ(cli_config.default_interval, 4096u);
+}
+
} // namespace profiling
} // namespace perfetto
diff --git a/src/profiling/memory/wire_protocol_unittest.cc b/src/profiling/memory/wire_protocol_unittest.cc
index 69df58f..3f7e494 100644
--- a/src/profiling/memory/wire_protocol_unittest.cc
+++ b/src/profiling/memory/wire_protocol_unittest.cc
@@ -160,6 +160,17 @@
EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
}
+TEST(GetHeapSamplingInterval, DisabledAndDefault) {
+ ClientConfiguration cli_config{};
+ cli_config.all_heaps = true;
+ cli_config.num_heaps = 1;
+ cli_config.default_interval = 1;
+ memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
+ cli_config.heaps[0].interval = 0u;
+ EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 0u);
+ EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
+}
+
} // namespace
} // namespace profiling
} // namespace perfetto
diff --git a/src/trace_processor/importers/common/clock_tracker.cc b/src/trace_processor/importers/common/clock_tracker.cc
index f59fbfc..75518a2 100644
--- a/src/trace_processor/importers/common/clock_tracker.cc
+++ b/src/trace_processor/importers/common/clock_tracker.cc
@@ -41,7 +41,7 @@
ClockTracker::~ClockTracker() = default;
-void ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
+uint32_t ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
const auto snapshot_id = cur_snapshot_id_++;
// Clear the cache
@@ -65,7 +65,7 @@
"supported for sequence-scoped clocks.",
clock_id);
context_->storage->IncrementStats(stats::invalid_clock_snapshots);
- return;
+ return snapshot_id;
}
domain.unit_multiplier_ns = clock.unit_multiplier_ns;
domain.is_incremental = clock.is_incremental;
@@ -79,7 +79,7 @@
clock_id, clock.unit_multiplier_ns, clock.is_incremental,
domain.unit_multiplier_ns, domain.is_incremental);
context_->storage->IncrementStats(stats::invalid_clock_snapshots);
- return;
+ return snapshot_id;
}
const int64_t timestamp_ns =
clock.absolute_timestamp * domain.unit_multiplier_ns;
@@ -92,7 +92,7 @@
" at snapshot %" PRIu32 ".",
clock_id, snapshot_id);
context_->storage->IncrementStats(stats::invalid_clock_snapshots);
- return;
+ return snapshot_id;
}
// Clock ids in the range [64, 128) are sequence-scoped and must be
@@ -116,7 +116,7 @@
clock_id, snapshot_id, timestamp_ns,
vect.timestamps_ns.back());
context_->storage->IncrementStats(stats::invalid_clock_snapshots);
- return;
+ return snapshot_id;
}
PERFETTO_DLOG("Detected non-monotonic clock with ID %" PRIu64, clock_id);
@@ -159,6 +159,7 @@
graph_.emplace(it2->clock_id, it1->clock_id, snapshot_hash);
}
}
+ return snapshot_id;
}
// Finds the shortest clock resolution path in the graph that allows to
diff --git a/src/trace_processor/importers/common/clock_tracker.h b/src/trace_processor/importers/common/clock_tracker.h
index 80b2a4e..16b9d79 100644
--- a/src/trace_processor/importers/common/clock_tracker.h
+++ b/src/trace_processor/importers/common/clock_tracker.h
@@ -154,7 +154,8 @@
// Appends a new snapshot for the given clock domains.
// This is typically called by the code that reads the ClockSnapshot packet.
- void AddSnapshot(const std::vector<ClockValue>&);
+ // Returns the internal snapshot id of this set of clocks.
+ uint32_t AddSnapshot(const std::vector<ClockValue>&);
// Converts a timestamp between two clock domains. Tries to use the cache
// first (only for single-path resolutions), then falls back on path finding
diff --git a/src/trace_processor/importers/proto/proto_trace_reader.cc b/src/trace_processor/importers/proto/proto_trace_reader.cc
index 863d5bd..ee03db3 100644
--- a/src/trace_processor/importers/proto/proto_trace_reader.cc
+++ b/src/trace_processor/importers/proto/proto_trace_reader.cc
@@ -378,10 +378,61 @@
clocks.emplace_back(clock_id, clk.timestamp(), unit_multiplier_ns,
clk.is_incremental());
}
- context_->clock_tracker->AddSnapshot(clocks);
+
+ uint32_t snapshot_id = context_->clock_tracker->AddSnapshot(clocks);
+
+ // Add the all the clock values to the clock snapshot table.
+ base::Optional<int64_t> trace_ts_for_check;
+ for (const auto& clock : clocks) {
+ // If the clock is incremental, we need to use 0 to map correctly to
+ // |absolute_timestamp|.
+ int64_t ts_to_convert = clock.is_incremental ? 0 : clock.absolute_timestamp;
+ base::Optional<int64_t> opt_trace_ts =
+ context_->clock_tracker->ToTraceTime(clock.clock_id, ts_to_convert);
+ if (!opt_trace_ts) {
+ // This can happen if |AddSnapshot| failed to resolve this clock. Just
+ // ignore this and move on.
+ continue;
+ }
+
+ // Double check that all the clocks in this snapshot resolve to the same
+ // trace timestamp value.
+ PERFETTO_DCHECK(!trace_ts_for_check || opt_trace_ts == trace_ts_for_check);
+ trace_ts_for_check = *opt_trace_ts;
+
+ tables::ClockSnapshotTable::Row row;
+ row.ts = *opt_trace_ts;
+ row.clock_id = static_cast<int64_t>(clock.clock_id);
+ row.clock_value = clock.absolute_timestamp;
+ row.clock_name = GetBuiltinClockNameOrNull(clock.clock_id);
+ row.snapshot_id = snapshot_id;
+
+ auto* snapshot_table = context_->storage->mutable_clock_snapshot_table();
+ snapshot_table->Insert(row);
+ }
return util::OkStatus();
}
+base::Optional<StringId> ProtoTraceReader::GetBuiltinClockNameOrNull(
+ uint64_t clock_id) {
+ switch (clock_id) {
+ case protos::pbzero::ClockSnapshot::Clock::REALTIME:
+ return context_->storage->InternString("REALTIME");
+ case protos::pbzero::ClockSnapshot::Clock::REALTIME_COARSE:
+ return context_->storage->InternString("REALTIME_COARSE");
+ case protos::pbzero::ClockSnapshot::Clock::MONOTONIC:
+ return context_->storage->InternString("MONOTONIC");
+ case protos::pbzero::ClockSnapshot::Clock::MONOTONIC_COARSE:
+ return context_->storage->InternString("MONOTONIC_COARSE");
+ case protos::pbzero::ClockSnapshot::Clock::MONOTONIC_RAW:
+ return context_->storage->InternString("MONOTONIC_RAW");
+ case protos::pbzero::ClockSnapshot::Clock::BOOTTIME:
+ return context_->storage->InternString("BOOTTIME");
+ default:
+ return base::nullopt;
+ }
+}
+
util::Status ProtoTraceReader::ParseServiceEvent(int64_t ts, ConstBytes blob) {
protos::pbzero::TracingServiceEvent::Decoder tse(blob);
if (tse.tracing_started()) {
diff --git a/src/trace_processor/importers/proto/proto_trace_reader.h b/src/trace_processor/importers/proto/proto_trace_reader.h
index b2f4069..1adb841 100644
--- a/src/trace_processor/importers/proto/proto_trace_reader.h
+++ b/src/trace_processor/importers/proto/proto_trace_reader.h
@@ -75,6 +75,8 @@
TraceBlobView interned_data);
void ParseTraceConfig(ConstBytes);
+ base::Optional<StringId> GetBuiltinClockNameOrNull(uint64_t clock_id);
+
PacketSequenceState* GetIncrementalStateForPacketSequence(
uint32_t sequence_id) {
if (!incremental_state)
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 698aa7c..e2af2ce 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -442,6 +442,13 @@
}
tables::MetadataTable* mutable_metadata_table() { return &metadata_table_; }
+ const tables::ClockSnapshotTable& clock_snapshot_table() const {
+ return clock_snapshot_table_;
+ }
+ tables::ClockSnapshotTable* mutable_clock_snapshot_table() {
+ return &clock_snapshot_table_;
+ }
+
const tables::ArgTable& arg_table() const { return arg_table_; }
tables::ArgTable* mutable_arg_table() { return &arg_table_; }
@@ -719,6 +726,9 @@
// * descriptions of android packages
tables::MetadataTable metadata_table_{&string_pool_, nullptr};
+ // Contains data from all the clock snapshots in the trace.
+ tables::ClockSnapshotTable clock_snapshot_table_{&string_pool_, nullptr};
+
// Metadata for tracks.
tables::TrackTable track_table_{&string_pool_, nullptr};
tables::GpuTrackTable gpu_track_table_{&string_pool_, &track_table_};
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index fa3136b..3f1bb90 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -113,6 +113,28 @@
PERFETTO_TP_TABLE(PERFETTO_TP_CPU_FREQ_TABLE_DEF);
+// Contains all the mapping between clock snapshots and trace time.
+//
+// NOTE: this table is not sorted by timestamp; this is why we omit the
+// sorted flag on the ts column.
+//
+// @param ts timestamp of the snapshot in trace time.
+// @param clock_id id of the clock (corresponds to the id in the trace).
+// @param clock_name the name of the clock for builtin clocks or null
+// otherwise.
+// @param clock_value timestamp of the snapshot in clock time.
+// @param snapshot_id the index of this snapshot (only useful for debugging)
+#define PERFETTO_TP_CLOCK_SNAPSHOT_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ClockSnapshotTable, "clock_snapshot") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, ts) \
+ C(int64_t, clock_id) \
+ C(base::Optional<StringPool::Id>, clock_name) \
+ C(int64_t, clock_value) \
+ C(uint32_t, snapshot_id)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_CLOCK_SNAPSHOT_TABLE_DEF);
+
} // namespace tables
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index d57b71b..34206b9 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -45,6 +45,7 @@
CpuFreqTable::~CpuFreqTable() = default;
ThreadTable::~ThreadTable() = default;
ProcessTable::~ProcessTable() = default;
+ClockSnapshotTable::~ClockSnapshotTable() = default;
// profiler_tables.h
StackProfileMappingTable::~StackProfileMappingTable() = default;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 8893144..0ca05ea 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -825,6 +825,7 @@
RegisterDbTable(storage->metadata_table());
RegisterDbTable(storage->cpu_table());
RegisterDbTable(storage->cpu_freq_table());
+ RegisterDbTable(storage->clock_snapshot_table());
RegisterDbTable(storage->memory_snapshot_table());
RegisterDbTable(storage->process_memory_snapshot_table());