Add perfetto build config
This adds Perfetto support to WebRTC with a GN flag rtc_use_perfetto.
The configuration of perfetto depends on whether or not webrtc is
build within Chrome or not. When in Chrome, WebRTC will depend on
//third_party/perfetto:libperfetto. When building standalone, specific includes required for Perfetto are exposed with the library webrtc_libperfetto.
The perfetto trace API is exposed with a header export in
trace_event.h which is used instead of the legacy API.
The addition of Perfetto means there are 4 compilation modes for
tracing in WebRTC,
1. No tracing implementation.
2. Legacy tracing (AddTraceEvent/GetCategoryEnabled).
3.a. Perfetto statically linked (webrtc_libperfetto).
3.b. Perfetto in Chrome (Chrome's libperfetto).
This CL removes the tracing expectations from
rtc_stats_integrationtest.cc because those directly used the old API.
Integration into Chrome is a follow up CL which depends on
https://chromium-review.googlesource.com/c/chromium/src/+/5471691.
Tested: Ran Chrome with Perfetto and traces appear. WebRTC Unit test tracing working: https://ui.perfetto.dev/#!?s=04ea2613ea36b814394639a1ec4b60be5b5097527f1a485995ecc13469885468
Bug: webrtc:15917
Change-Id: I537d79dc247c2b759689910c621087286a4d8fdc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/347880
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Auto-Submit: Evan Shrubsole <eshr@google.com>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Mikhail Khokhlov <khokhlov@google.com>
Cr-Commit-Position: refs/heads/main@{#42166}
diff --git a/BUILD.gn b/BUILD.gn
index 571049f..5828a81 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -174,16 +174,18 @@
defines += [ "RTC_ENABLE_WIN_WGC" ]
}
- # Some tests need to declare their own trace event handlers. If this define is
- # not set, the first time TRACE_EVENT_* is called it will store the return
- # value for the current handler in an static variable, so that subsequent
- # changes to the handler for that TRACE_EVENT_* will be ignored.
- # So when tests are included, we set this define, making it possible to use
- # different event handlers in different tests.
- if (rtc_include_tests) {
- defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=1" ]
- } else {
- defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0" ]
+ if (!rtc_use_perfetto) {
+ # Some tests need to declare their own trace event handlers. If this define is
+ # not set, the first time TRACE_EVENT_* is called it will store the return
+ # value for the current handler in an static variable, so that subsequent
+ # changes to the handler for that TRACE_EVENT_* will be ignored.
+ # So when tests are included, we set this define, making it possible to use
+ # different event handlers in different tests.
+ if (rtc_include_tests) {
+ defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=1" ]
+ } else {
+ defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0" ]
+ }
}
if (build_with_chromium) {
defines += [ "WEBRTC_CHROMIUM_BUILD" ]
@@ -269,6 +271,30 @@
}
}
+group("tracing") {
+ if (rtc_use_perfetto) {
+ if (build_with_chromium) {
+ public_deps = # no-presubmit-check TODO(webrtc:8603)
+ [ "//third_party/perfetto:libperfetto" ]
+ } else {
+ public_deps = # no-presubmit-check TODO(webrtc:8603)
+ [ ":webrtc_libperfetto" ]
+ }
+ }
+}
+
+if (rtc_use_perfetto) {
+ rtc_library("webrtc_libperfetto") {
+ public_configs = [ "//third_party/perfetto/gn:public_config" ]
+ deps = [
+ "//third_party/perfetto/src/tracing:client_api_without_backends",
+ "//third_party/perfetto/src/tracing:platform_impl",
+ ]
+ public_deps += # no-presubmit-check TODO(webrtc:8603)
+ [ "//third_party/perfetto/include/perfetto/tracing" ]
+ }
+}
+
config("common_config") {
cflags = []
cflags_c = []
@@ -478,6 +504,10 @@
"/U_UNICODE",
]
}
+
+ if (rtc_use_perfetto) {
+ defines += [ "RTC_USE_PERFETTO" ]
+ }
}
config("common_objc") {
diff --git a/DEPS b/DEPS
index 69c52e8..89ffcb4 100644
--- a/DEPS
+++ b/DEPS
@@ -2668,6 +2668,10 @@
# Abseil flags are allowed in tests and tools.
"+absl/flags",
+
+ # Perfetto
+ '+third_party/perfetto/include/perfetto/tracing',
+ '+third_party/perfetto/include/perfetto/test',
]
specific_include_rules = {
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index cfa7958..219de19 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -34,6 +34,9 @@
# so we just ignore that assert. See https://crbug.com/648948 for more info.
ignore_elf32_limitations = true
+perfetto_build_with_embedder = true
+enable_perfetto_trace_processor = true
+
# Use bundled hermetic Xcode installation maintainted by Chromium,
# except for local iOS builds where it's unsupported.
# Allow for mac cross compile on linux machines.
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc
index 1ff060c..8c28532 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -50,64 +50,11 @@
const int64_t kGetStatsTimeoutMs = 10000;
-const unsigned char* GetCategoryEnabledHandler(const char* name) {
- if (strcmp("webrtc_stats", name) != 0) {
- return reinterpret_cast<const unsigned char*>("");
- }
- return reinterpret_cast<const unsigned char*>(name);
-}
-
-class RTCStatsReportTraceListener {
- public:
- static void SetUp() {
- if (!traced_report_)
- traced_report_ = new RTCStatsReportTraceListener();
- traced_report_->last_trace_ = "";
- SetupEventTracer(&GetCategoryEnabledHandler,
- &RTCStatsReportTraceListener::AddTraceEventHandler);
- }
-
- static const std::string& last_trace() {
- RTC_DCHECK(traced_report_);
- return traced_report_->last_trace_;
- }
-
- private:
- static void AddTraceEventHandler(
- char phase,
- const unsigned char* category_enabled,
- const char* name,
- unsigned long long id, // NOLINT(runtime/int)
- int num_args,
- const char** arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values, // NOLINT(runtime/int)
- unsigned char flags) {
- RTC_DCHECK(traced_report_);
- EXPECT_STREQ("webrtc_stats",
- reinterpret_cast<const char*>(category_enabled));
- EXPECT_STREQ("webrtc_stats", name);
- EXPECT_EQ(1, num_args);
- EXPECT_STREQ("report", arg_names[0]);
- EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, arg_types[0]);
-
- traced_report_->last_trace_ = reinterpret_cast<const char*>(arg_values[0]);
- }
-
- static RTCStatsReportTraceListener* traced_report_;
- std::string last_trace_;
-};
-
-RTCStatsReportTraceListener* RTCStatsReportTraceListener::traced_report_ =
- nullptr;
-
class RTCStatsIntegrationTest : public ::testing::Test {
public:
RTCStatsIntegrationTest()
: network_thread_(new rtc::Thread(&virtual_socket_server_)),
worker_thread_(rtc::Thread::Create()) {
- RTCStatsReportTraceListener::SetUp();
-
RTC_CHECK(network_thread_->Start());
RTC_CHECK(worker_thread_->Start());
@@ -1054,10 +1001,6 @@
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsFromCaller();
RTCStatsReportVerifier(report.get()).VerifyReport({});
-
-#if RTC_TRACE_EVENTS_ENABLED
- EXPECT_EQ(report->ToJson(), RTCStatsReportTraceListener::last_trace());
-#endif
}
TEST_F(RTCStatsIntegrationTest, GetStatsFromCallee) {
@@ -1076,10 +1019,6 @@
};
EXPECT_TRUE_WAIT(GetStatsReportAndReturnTrueIfRttIsDefined(), kMaxWaitMs);
RTCStatsReportVerifier(report.get()).VerifyReport({});
-
-#if RTC_TRACE_EVENTS_ENABLED
- EXPECT_EQ(report->ToJson(), RTCStatsReportTraceListener::last_trace());
-#endif
}
// These tests exercise the integration of the stats selection algorithm inside
@@ -1157,10 +1096,6 @@
// Any pending stats requests should have completed in the act of destroying
// the peer connection.
ASSERT_TRUE(stats_obtainer->report());
-#if RTC_TRACE_EVENTS_ENABLED
- EXPECT_EQ(stats_obtainer->report()->ToJson(),
- RTCStatsReportTraceListener::last_trace());
-#endif
}
TEST_F(RTCStatsIntegrationTest, GetsStatsWhileClosingPeerConnection) {
@@ -1172,10 +1107,6 @@
caller_->pc()->Close();
ASSERT_TRUE(stats_obtainer->report());
-#if RTC_TRACE_EVENTS_ENABLED
- EXPECT_EQ(stats_obtainer->report()->ToJson(),
- RTCStatsReportTraceListener::last_trace());
-#endif
}
// GetStatsReferencedIds() is optimized to recognize what is or isn't a
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index b3cb17c..e5ead5b 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -215,6 +215,13 @@
"system:rtc_export",
]
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
+ if (rtc_use_perfetto) {
+ sources += [
+ "trace_categories.cc",
+ "trace_categories.h",
+ ]
+ deps += [ "..:tracing" ]
+ }
}
rtc_library("histogram_percentile_counter") {
diff --git a/rtc_base/DEPS b/rtc_base/DEPS
index 3a77b55..4ba8c92 100644
--- a/rtc_base/DEPS
+++ b/rtc_base/DEPS
@@ -12,4 +12,10 @@
"gunit\.h": [
"+testing/base/public/gunit.h"
],
+ "trace_categories\.h": [
+ "+perfetto",
+ ],
+ "event_tracer\.cc": [
+ "+perfetto",
+ ]
}
diff --git a/rtc_base/event_tracer.cc b/rtc_base/event_tracer.cc
index 6ad8330..677b95b 100644
--- a/rtc_base/event_tracer.cc
+++ b/rtc_base/event_tracer.cc
@@ -7,11 +7,19 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
+
#include "rtc_base/event_tracer.h"
+#include <stdio.h>
+
+#include "rtc_base/trace_event.h"
+
+#if defined(RTC_USE_PERFETTO)
+#include "perfetto/tracing/tracing.h"
+#include "rtc_base/trace_categories.h"
+#else
#include <inttypes.h>
#include <stdint.h>
-#include <stdio.h>
#include <string.h>
#include <atomic>
@@ -28,21 +36,27 @@
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/time_utils.h"
-#include "rtc_base/trace_event.h"
-
-// This is a guesstimate that should be enough in most cases.
-static const size_t kEventLoggerArgsStrBufferInitialSize = 256;
-static const size_t kTraceArgBufferLength = 32;
+#endif
namespace webrtc {
namespace {
+#if !defined(RTC_USE_PERFETTO)
GetCategoryEnabledPtr g_get_category_enabled_ptr = nullptr;
AddTraceEventPtr g_add_trace_event_ptr = nullptr;
+#endif
} // namespace
+#if defined(RTC_USE_PERFETTO)
+void RegisterPerfettoTrackEvents() {
+ if (perfetto::Tracing::IsInitialized()) {
+ webrtc::TrackEvent::Register();
+ }
+}
+#else
+
void SetupEventTracer(GetCategoryEnabledPtr get_category_enabled_ptr,
AddTraceEventPtr add_trace_event_ptr) {
g_get_category_enabled_ptr = get_category_enabled_ptr;
@@ -73,9 +87,28 @@
arg_names, arg_types, arg_values, flags);
}
}
+#endif
} // namespace webrtc
+#if defined(RTC_USE_PERFETTO)
+// TODO(bugs.webrtc.org/15917): Implement for perfetto.
+namespace rtc::tracing {
+void SetupInternalTracer(bool enable_all_categories) {}
+bool StartInternalCapture(absl::string_view filename) {
+ return false;
+}
+void StartInternalCaptureToFile(FILE* file) {}
+void StopInternalCapture() {}
+void ShutdownInternalTracer() {}
+
+} // namespace rtc::tracing
+#else
+
+// This is a guesstimate that should be enough in most cases.
+static const size_t kEventLoggerArgsStrBufferInitialSize = 256;
+static const size_t kTraceArgBufferLength = 32;
+
namespace rtc {
namespace tracing {
namespace {
@@ -412,3 +445,5 @@
} // namespace tracing
} // namespace rtc
+
+#endif // defined(RTC_USE_PERFETTO)
diff --git a/rtc_base/event_tracer.h b/rtc_base/event_tracer.h
index dc2eaed..7f8d3e6 100644
--- a/rtc_base/event_tracer.h
+++ b/rtc_base/event_tracer.h
@@ -8,6 +8,9 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#ifndef RTC_BASE_EVENT_TRACER_H_
+#define RTC_BASE_EVENT_TRACER_H_
+
// This file defines the interface for event tracing in WebRTC.
//
// Event log handlers are set through SetupEventTracer(). User of this API will
@@ -23,9 +26,6 @@
//
// Parameters for the above two functions are described in trace_event.h.
-#ifndef RTC_BASE_EVENT_TRACER_H_
-#define RTC_BASE_EVENT_TRACER_H_
-
#include <stdio.h>
#include "absl/strings/string_view.h"
@@ -33,6 +33,9 @@
namespace webrtc {
+#if defined(RTC_USE_PERFETTO)
+void RegisterPerfettoTrackEvents();
+#else
typedef const unsigned char* (*GetCategoryEnabledPtr)(const char* name);
typedef void (*AddTraceEventPtr)(char phase,
const unsigned char* category_enabled,
@@ -67,19 +70,19 @@
const unsigned long long* arg_values,
unsigned char flags);
};
+#endif
} // namespace webrtc
-namespace rtc {
-namespace tracing {
+namespace rtc::tracing {
// Set up internal event tracer.
+// TODO(webrtc:15917): Implement for perfetto.
RTC_EXPORT void SetupInternalTracer(bool enable_all_categories = true);
RTC_EXPORT bool StartInternalCapture(absl::string_view filename);
RTC_EXPORT void StartInternalCaptureToFile(FILE* file);
RTC_EXPORT void StopInternalCapture();
// Make sure we run this, this will tear down the internal tracing.
RTC_EXPORT void ShutdownInternalTracer();
-} // namespace tracing
-} // namespace rtc
+} // namespace rtc::tracing
#endif // RTC_BASE_EVENT_TRACER_H_
diff --git a/rtc_base/event_tracer_unittest.cc b/rtc_base/event_tracer_unittest.cc
index d0783c3..eae19a2 100644
--- a/rtc_base/event_tracer_unittest.cc
+++ b/rtc_base/event_tracer_unittest.cc
@@ -50,16 +50,16 @@
namespace webrtc {
TEST(EventTracerTest, EventTracerDisabled) {
- { TRACE_EVENT0("test", "EventTracerDisabled"); }
+ { TRACE_EVENT0("webrtc-test", "EventTracerDisabled"); }
EXPECT_FALSE(TestStatistics::Get()->Count());
TestStatistics::Get()->Reset();
}
-#if RTC_TRACE_EVENTS_ENABLED
+#if RTC_TRACE_EVENTS_ENABLED && !defined(RTC_USE_PERFETTO)
TEST(EventTracerTest, ScopedTraceEvent) {
SetupEventTracer(
[](const char* /*name*/) {
- return reinterpret_cast<const unsigned char*>("test");
+ return reinterpret_cast<const unsigned char*>("webrtc-test");
},
[](char /*phase*/, const unsigned char* /*category_enabled*/,
const char* /*name*/, unsigned long long /*id*/, int /*num_args*/,
diff --git a/rtc_base/trace_categories.cc b/rtc_base/trace_categories.cc
new file mode 100644
index 0000000..2fe63e2
--- /dev/null
+++ b/rtc_base/trace_categories.cc
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/trace_categories.h"
+
+PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE_WITH_ATTRS(webrtc, RTC_EXPORT);
diff --git a/rtc_base/trace_categories.h b/rtc_base/trace_categories.h
new file mode 100644
index 0000000..c22ce91
--- /dev/null
+++ b/rtc_base/trace_categories.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TRACE_CATEGORIES_H_
+#define RTC_BASE_TRACE_CATEGORIES_H_
+
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
+
+#include "perfetto/tracing/track_event.h" // IWYU pragma: export
+#include "perfetto/tracing/track_event_category_registry.h"
+#include "perfetto/tracing/track_event_legacy.h" // IWYU pragma: export
+#include "rtc_base/system/rtc_export.h"
+
+PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES("webrtc-test");
+
+PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS(
+ webrtc,
+ RTC_EXPORT,
+ perfetto::Category("webrtc"),
+ perfetto::Category("webrtc_stats"),
+ perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webrtc")),
+ perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webrtc_stats")));
+
+PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(webrtc);
+
+#endif // RTC_BASE_TRACE_CATEGORIES_H_
diff --git a/rtc_base/trace_event.h b/rtc_base/trace_event.h
index 8499983..ab62802 100644
--- a/rtc_base/trace_event.h
+++ b/rtc_base/trace_event.h
@@ -1,25 +1,40 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file under third_party_mods/chromium or at:
-// http://src.chromium.org/svn/trunk/src/LICENSE
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
#ifndef RTC_BASE_TRACE_EVENT_H_
#define RTC_BASE_TRACE_EVENT_H_
-#include <string>
-
-#include "rtc_base/event_tracer.h"
-
-#if defined(TRACE_EVENT0)
-#error "Another copy of trace_event.h has already been included."
-#endif
-
#if defined(RTC_DISABLE_TRACE_EVENTS)
#define RTC_TRACE_EVENTS_ENABLED 0
#else
#define RTC_TRACE_EVENTS_ENABLED 1
#endif
+#if defined(RTC_USE_PERFETTO)
+
+#include "rtc_base/trace_categories.h" // IWYU pragma: export
+
+// TODO(webrtc:15917): Replace these events.
+#define TRACE_EVENT_ASYNC_STEP0(category_group, name, id, step) \
+ TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step)
+#define TRACE_EVENT_ASYNC_STEP1(category_group, name, id, step, arg1_name, \
+ arg1_val) \
+ TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, arg1_name, \
+ arg1_val)
+
+#else
+
+#include <string>
+
+#include "rtc_base/event_tracer.h"
+
// Type values for identifying types in the TraceValue union.
#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
@@ -29,6 +44,10 @@
#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
+#if defined(TRACE_EVENT0)
+#error "Another copy of trace_event.h has already been included."
+#endif
+
#if RTC_TRACE_EVENTS_ENABLED
// Extracted from Chromium's src/base/debug/trace_event.h.
@@ -705,6 +724,7 @@
} // namespace trace_event_internal
} // namespace webrtc
+
#else
////////////////////////////////////////////////////////////////////////////////
@@ -779,5 +799,6 @@
#define TRACE_EVENT_API_ADD_TRACE_EVENT RTC_NOOP()
#endif // RTC_TRACE_EVENTS_ENABLED
+#endif // RTC_USE_PERFETTO
#endif // RTC_BASE_TRACE_EVENT_H_
diff --git a/test/BUILD.gn b/test/BUILD.gn
index d1554d7..783e94a 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -627,6 +627,9 @@
if (is_win) {
deps += [ "../rtc_base:win32_socket_init" ]
}
+ if (rtc_use_perfetto) {
+ deps += [ "//third_party/perfetto/src/tracing:client_api" ]
+ }
}
rtc_library("test_main") {
diff --git a/test/DEPS b/test/DEPS
index a9e9a7b..f9f47e1 100644
--- a/test/DEPS
+++ b/test/DEPS
@@ -49,6 +49,10 @@
".*stun_validator_fuzzer\.cc": [
"+p2p/base/stun.h",
],
+ ".*test_main_lib\.cc": [
+ "+perfetto/tracing",
+ "+protos/perfetto/config",
+ ],
".*test_main\.cc": [
"+absl/debugging/failure_signal_handler.h",
"+absl/debugging/symbolize.h",
diff --git a/test/test_main_lib.cc b/test/test_main_lib.cc
index 4c80315..76b5a16 100644
--- a/test/test_main_lib.cc
+++ b/test/test_main_lib.cc
@@ -10,7 +10,10 @@
#include "test/test_main_lib.h"
+#include <cstddef>
+#include <cstdio>
#include <fstream>
+#include <ios>
#include <memory>
#include <string>
#include <vector>
@@ -18,6 +21,7 @@
#include "absl/flags/flag.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/test/metrics/chrome_perf_dashboard_metrics_exporter.h"
#include "api/test/metrics/global_metrics_logger_and_exporter.h"
@@ -39,6 +43,13 @@
#include "test/testsupport/perf_test.h"
#include "test/testsupport/resources_dir_flag.h"
+#if defined(RTC_USE_PERFETTO)
+#include "perfetto/tracing/backend_type.h"
+#include "perfetto/tracing/tracing.h"
+#include "protos/perfetto/config/trace_config.gen.h"
+#include "rtc_base/event_tracer.h"
+#endif
+
#if defined(WEBRTC_WIN)
#include "rtc_base/win32_socket_init.h"
#endif
@@ -92,8 +103,7 @@
ABSL_FLAG(std::string,
trace_event,
"",
- "Path to collect trace events (json file) for chrome://tracing. "
- "If not set, events aren't captured.");
+ "Path to collect trace events. If not set, events aren't captured.");
ABSL_FLAG(std::string,
test_launcher_shard_index,
@@ -167,8 +177,7 @@
std::string trace_event_path = absl::GetFlag(FLAGS_trace_event);
const bool capture_events = !trace_event_path.empty();
if (capture_events) {
- rtc::tracing::SetupInternalTracer();
- rtc::tracing::StartInternalCapture(trace_event_path);
+ StartTracingCapture(trace_event_path);
}
absl::optional<std::vector<std::string>> metrics_to_plot =
@@ -236,7 +245,7 @@
#endif
if (capture_events) {
- rtc::tracing::StopInternalCapture();
+ StopTracingCapture();
}
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
@@ -256,6 +265,59 @@
#if defined(WEBRTC_WIN)
std::unique_ptr<rtc::WinsockInitializer> winsock_init_;
#endif
+#if defined(RTC_USE_PERFETTO)
+ std::unique_ptr<perfetto::TracingSession> tracing_session_;
+ FILE* tracing_output_file_ = nullptr;
+#endif
+
+ void StartTracingCapture(absl::string_view trace_output_file) {
+#if defined(RTC_USE_PERFETTO)
+ tracing_output_file_ = std::fopen(trace_output_file.data(), "w");
+ if (!tracing_output_file_) {
+ RTC_LOG(LS_ERROR) << "Failed to open trace file \"" << trace_output_file
+ << "\". Tracing will be disabled.";
+ }
+ perfetto::TracingInitArgs args;
+ args.backends |= perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ webrtc::RegisterPerfettoTrackEvents();
+
+ perfetto::TraceConfig cfg;
+ cfg.add_buffers()->set_size_kb(1024); // Record up to 1 MiB.
+ tracing_session_ = perfetto::Tracing::NewTrace();
+ tracing_session_->Setup(cfg);
+ RTC_LOG(LS_INFO)
+ << "Starting tracing with Perfetto and outputting to file \""
+ << trace_output_file << "\"";
+ tracing_session_->StartBlocking();
+#else
+ rtc::tracing::SetupInternalTracer();
+ rtc::tracing::StartInternalCapture(trace_output_file);
+#endif
+ }
+
+ void StopTracingCapture() {
+#if defined(RTC_USE_PERFETTO)
+ if (tracing_output_file_) {
+ RTC_CHECK(tracing_session_);
+ tracing_session_->StopBlocking();
+ std::vector<char> tracing_data = tracing_session_->ReadTraceBlocking();
+ size_t count = std::fwrite(tracing_data.data(), sizeof tracing_data[0],
+ tracing_data.size(), tracing_output_file_);
+ if (count != tracing_data.size()) {
+ RTC_LOG(LS_ERROR) << "Expected to write " << tracing_data.size()
+ << " bytes but only " << count << " bytes written";
+ }
+ std::fclose(tracing_output_file_);
+ tracing_output_file_ = nullptr;
+ } else {
+ RTC_LOG(LS_INFO) << "no file";
+ }
+
+#else
+ rtc::tracing::StopInternalCapture();
+#endif
+ }
};
} // namespace
diff --git a/tools_webrtc/mb/mb_config.pyl b/tools_webrtc/mb/mb_config.pyl
index 8862950..a64b9e0 100644
--- a/tools_webrtc/mb/mb_config.pyl
+++ b/tools_webrtc/mb/mb_config.pyl
@@ -147,6 +147,7 @@
'dummy_audio_file_devices_no_protobuf_android_arm',
'rtti_no_sctp': 'rtti_no_sctp_android_arm',
'disable_trace_events': 'disable_trace_events_android_arm',
+ 'perfetto': 'perfetto_android_arm',
},
'android_arm_rel': 'android_release_bot_arm',
'android_compile_arm64_dbg': 'android_debug_static_bot_arm64',
@@ -185,6 +186,7 @@
'dummy_audio_file_devices_no_protobuf_x64',
'rtti_no_sctp': 'rtti_no_sctp_x64',
'disable_trace_events': 'disable_trace_events_x64',
+ 'perfetto': 'perfetto_x64',
},
'linux_msan': 'msan_clang_release_bot_x64',
'linux_rel': 'release_bot_x64',
@@ -221,6 +223,7 @@
'dummy_audio_file_devices_no_protobuf_x86',
'rtti_no_sctp': 'rtti_no_sctp_no_unicode_win_x86',
'disable_trace_events': 'disable_trace_events_x86',
+ 'perfetto': 'perfetto_x86',
},
}
},
@@ -353,6 +356,9 @@
'msan_clang_release_bot_x64':
['msan', 'clang', 'openh264', 'pure_release_bot', 'x64', 'h265'],
'no_h264_debug_bot_x86': ['debug_bot', 'x86'],
+ 'perfetto_android_arm': [ 'android', 'arm', 'perfetto', 'release_bot'],
+ 'perfetto_x64': [ 'x64', 'perfetto', 'release_bot'],
+ 'perfetto_x86': [ 'x86', 'perfetto', 'release_bot'],
'pure_release_bot_x64': ['openh264', 'pure_release_bot', 'x64', 'h265'],
'pure_release_bot_x86': ['openh264', 'pure_release_bot', 'x86', 'h265'],
'release_bot_arm': ['openh264', 'release_bot', 'arm', 'h265'],
@@ -513,6 +519,9 @@
'gn_args':
'coverage_instrumentation_input_file="//.code-coverage/files_to_instrument.txt"'
},
+ 'perfetto': {
+ 'gn_args': 'rtc_use_perfetto=true',
+ },
# The 'pure_release_bot' configuration is for release bots that are doing a
# 100% release build without DCHECKs while 'release_bot' is a partial
# release configs since `dcheck_always_on` is set to true.
diff --git a/webrtc.gni b/webrtc.gni
index 969cdbd..de35c21 100644
--- a/webrtc.gni
+++ b/webrtc.gni
@@ -268,6 +268,9 @@
# WebRTC does not declare its public dependencies. See webrtc:8603. Instead
# WebRTC is using a global common dependencies.
rtc_common_public_deps = [] # no-presubmit-check TODO(webrtc:8603)
+
+ # When true, include the Perfetto library.
+ rtc_use_perfetto = false
}
if (!build_with_mozilla) {
@@ -385,6 +388,9 @@
rtc_common_configs += [ "//build/config/compiler:enable_arc" ]
}
}
+if (rtc_use_perfetto) {
+ rtc_common_configs += [ "//third_party/perfetto/gn:public_config" ]
+}
# Global public configuration that should be applied to all WebRTC targets. You
# normally shouldn't need to include this in your target as it's automatically