зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1887068: Add perfetto event traces for taskcontroller tasks and dom performance measurement markers. r=smaug
Depends on D205662 Differential Revision: https://phabricator.services.mozilla.com/D205663
This commit is contained in:
Родитель
91cc9e373c
Коммит
a37693bbe8
|
@ -33,6 +33,7 @@
|
||||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||||
#include "mozilla/dom/PerformanceNavigationTiming.h"
|
#include "mozilla/dom/PerformanceNavigationTiming.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
|
#include "mozilla/Perfetto.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/dom/WorkerPrivate.h"
|
#include "mozilla/dom/WorkerPrivate.h"
|
||||||
|
@ -764,6 +765,25 @@ already_AddRefed<PerformanceMeasure> Performance::Measure(
|
||||||
detail.setNull();
|
detail.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_PERFETTO
|
||||||
|
// Perfetto requires that events are properly nested within each category.
|
||||||
|
// Since this is not a guarantee here, we need to define a dynamic category
|
||||||
|
// for each measurement so it's not prematurely ended by another measurement
|
||||||
|
// that overlaps. We also use the usertiming category to guard these markers
|
||||||
|
// so it's easy to toggle.
|
||||||
|
if (TRACE_EVENT_CATEGORY_ENABLED("usertiming")) {
|
||||||
|
NS_ConvertUTF16toUTF8 str(aName);
|
||||||
|
perfetto::DynamicCategory category{str.get()};
|
||||||
|
TimeStamp startTimeStamp =
|
||||||
|
CreationTimeStamp() + TimeDuration::FromMilliseconds(startTime);
|
||||||
|
TimeStamp endTimeStamp =
|
||||||
|
CreationTimeStamp() + TimeDuration::FromMilliseconds(endTime);
|
||||||
|
PERFETTO_TRACE_EVENT_BEGIN(category, perfetto::DynamicString{str.get()},
|
||||||
|
startTimeStamp);
|
||||||
|
PERFETTO_TRACE_EVENT_END(category, endTimeStamp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RefPtr<PerformanceMeasure> performanceMeasure = new PerformanceMeasure(
|
RefPtr<PerformanceMeasure> performanceMeasure = new PerformanceMeasure(
|
||||||
GetParentObject(), aName, startTime, endTime, detail);
|
GetParentObject(), aName, startTime, endTime, detail);
|
||||||
InsertUserEntry(performanceMeasure);
|
InsertUserEntry(performanceMeasure);
|
||||||
|
|
|
@ -469,7 +469,7 @@ class TimeStamp {
|
||||||
static MFBT_API void RecordProcessRestart();
|
static MFBT_API void RecordProcessRestart();
|
||||||
|
|
||||||
#ifdef XP_LINUX
|
#ifdef XP_LINUX
|
||||||
uint64_t RawClockMonotonicNanosecondsSinceBoot() {
|
uint64_t RawClockMonotonicNanosecondsSinceBoot() const {
|
||||||
return static_cast<uint64_t>(mValue);
|
return static_cast<uint64_t>(mValue);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/Perfetto.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
|
||||||
|
|
||||||
|
void InitPerfetto() {
|
||||||
|
if (!getenv("MOZ_DISABLE_PERFETTO")) {
|
||||||
|
perfetto::TracingInitArgs args;
|
||||||
|
args.backends |= perfetto::kSystemBackend;
|
||||||
|
perfetto::Tracing::Initialize(args);
|
||||||
|
perfetto::TrackEvent::Register();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_Perfetto_h
|
||||||
|
#define mozilla_Perfetto_h
|
||||||
|
|
||||||
|
#ifdef MOZ_PERFETTO
|
||||||
|
# include "perfetto/perfetto.h"
|
||||||
|
# include "mozilla/TimeStamp.h"
|
||||||
|
|
||||||
|
// Initialization is called when a content process is created.
|
||||||
|
// This can be called multiple times.
|
||||||
|
extern void InitPerfetto();
|
||||||
|
|
||||||
|
/* Perfetto Tracing:
|
||||||
|
*
|
||||||
|
* This file provides an interface to the perfetto tracing API. The API from
|
||||||
|
* the perfetto sdk can be used directly, but an additional set of macros
|
||||||
|
* prefixed with PERFETTO_* have been defined to help minimize the use of
|
||||||
|
* ifdef's.
|
||||||
|
*
|
||||||
|
* The common perfetto macros require a category and name at the very least.
|
||||||
|
* These must be static strings, or wrapped with perfetto::DynamicString if
|
||||||
|
* dynamic. If the string is static, but provided through a runtime pointer,
|
||||||
|
* then it must be wrapped with perfetto::StaticString.
|
||||||
|
*
|
||||||
|
* You can also provide additional parameters such as a timestamp,
|
||||||
|
* or a lambda to add additional information to the trace marker.
|
||||||
|
* For more info, see https://perfetto.dev/docs/instrumentation/tracing-sdk
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* // Add a trace event to measure work inside a block,
|
||||||
|
* // using static strings only.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* PERFETTO_TRACE_EVENT("js", "JS::RunScript");
|
||||||
|
* run_script();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Add a trace event to measure work inside a block,
|
||||||
|
* // using a dynamic string.
|
||||||
|
*
|
||||||
|
* void runScript(nsCString& scriptName)
|
||||||
|
* {
|
||||||
|
* PERFETTO_TRACE_EVENT("js", perfetto::DynamicString{scriptName.get()});
|
||||||
|
* run_script();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Add a trace event using a dynamic category and name.
|
||||||
|
*
|
||||||
|
* void runScript(nsCString& categoryName, nsCString& scriptName)
|
||||||
|
* {
|
||||||
|
* perfetto::DynamicCategory category{category.get()};
|
||||||
|
* PERFETTO_TRACE_EVENT(category, perfetto::DynamicString{scriptName.get()});
|
||||||
|
* run_script();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Add a trace event to measure two arbitrary points of code.
|
||||||
|
* // Events in the same category must always be nested.
|
||||||
|
*
|
||||||
|
* void startWork() {
|
||||||
|
* PERFETTO_TRACE_EVENT_BEGIN("js", "StartWork");
|
||||||
|
* ...
|
||||||
|
* PERFETTO_TRACE_EVENT_END("js");
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Create a trace marker for an event that has already occurred
|
||||||
|
* // using previously saved timestamps.
|
||||||
|
*
|
||||||
|
* void record_event(TimeStamp startTimeStamp, TimeStamp endTimeStamp)
|
||||||
|
* {
|
||||||
|
* PERFETTO_TRACE_EVENT_BEGIN("js", "Some Event", startTimeStamp);
|
||||||
|
* PERFETTO_TRACE_EVENT_END("js", endTimeStamp);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Wrap the common trace event macros from perfetto so
|
||||||
|
// they can be called without #ifdef's.
|
||||||
|
# define PERFETTO_TRACE_EVENT(...) TRACE_EVENT(__VA_ARGS__)
|
||||||
|
# define PERFETTO_TRACE_EVENT_BEGIN(...) TRACE_EVENT_BEGIN(__VA_ARGS__)
|
||||||
|
# define PERFETTO_TRACE_EVENT_END(...) TRACE_EVENT_END(__VA_ARGS__)
|
||||||
|
|
||||||
|
namespace perfetto {
|
||||||
|
// Specialize custom timestamps for mozilla::TimeStamp.
|
||||||
|
template <>
|
||||||
|
struct TraceTimestampTraits<mozilla::TimeStamp> {
|
||||||
|
static inline TraceTimestamp ConvertTimestampToTraceTimeNs(
|
||||||
|
const mozilla::TimeStamp& timestamp) {
|
||||||
|
return {protos::gen::BuiltinClock::BUILTIN_CLOCK_MONOTONIC,
|
||||||
|
timestamp.RawClockMonotonicNanosecondsSinceBoot()};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace perfetto
|
||||||
|
|
||||||
|
// Categories can be added dynamically, but to minimize overhead
|
||||||
|
// all categories should be pre-defined here whenever possible.
|
||||||
|
PERFETTO_DEFINE_CATEGORIES(perfetto::Category("task"),
|
||||||
|
perfetto::Category("usertiming"));
|
||||||
|
|
||||||
|
#else // !defined(MOZ_PERFETTO)
|
||||||
|
# define PERFETTO_TRACE_EVENT(...) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
# define PERFETTO_TRACE_EVENT_BEGIN(...) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
# define PERFETTO_TRACE_EVENT_END(...) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
inline void InitPerfetto() {}
|
||||||
|
#endif // MOZ_PERFETTO
|
||||||
|
|
||||||
|
#endif // mozilla_Perfetto_h
|
|
@ -9,12 +9,14 @@ UNIFIED_SOURCES += [
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
|
"Perfetto.h",
|
||||||
"PerfStats.h",
|
"PerfStats.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
include("/ipc/chromium/chromium-config.mozbuild")
|
include("/ipc/chromium/chromium-config.mozbuild")
|
||||||
|
|
||||||
if CONFIG["MOZ_PERFETTO"]:
|
if CONFIG["MOZ_PERFETTO"]:
|
||||||
|
UNIFIED_SOURCES += ["Perfetto.cpp"]
|
||||||
DIRS += ["/third_party/perfetto/"]
|
DIRS += ["/third_party/perfetto/"]
|
||||||
|
|
||||||
FINAL_LIBRARY = "xul"
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "mozilla/InputTaskManager.h"
|
#include "mozilla/InputTaskManager.h"
|
||||||
#include "mozilla/VsyncTaskManager.h"
|
#include "mozilla/VsyncTaskManager.h"
|
||||||
#include "mozilla/IOInterposer.h"
|
#include "mozilla/IOInterposer.h"
|
||||||
|
#include "mozilla/Perfetto.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/SchedulerGroup.h"
|
#include "mozilla/SchedulerGroup.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
|
@ -135,6 +136,7 @@ class MOZ_RAII AutoProfileTask {
|
||||||
# define AUTO_PROFILE_FOLLOWING_TASK(task) \
|
# define AUTO_PROFILE_FOLLOWING_TASK(task) \
|
||||||
nsAutoCString name; \
|
nsAutoCString name; \
|
||||||
(task)->GetName(name); \
|
(task)->GetName(name); \
|
||||||
|
PERFETTO_TRACE_EVENT("task", perfetto::DynamicString{name.get()}); \
|
||||||
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE("Task", OTHER, name); \
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE("Task", OTHER, name); \
|
||||||
mozilla::AutoProfileTask PROFILER_RAII(name, (task)->GetPriority());
|
mozilla::AutoProfileTask PROFILER_RAII(name, (task)->GetPriority());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "mozilla/InputTaskManager.h"
|
#include "mozilla/InputTaskManager.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/NeverDestroyed.h"
|
#include "mozilla/NeverDestroyed.h"
|
||||||
|
#include "mozilla/Perfetto.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
#include "mozilla/ProfilerMarkers.h"
|
||||||
#include "mozilla/SpinEventLoopUntil.h"
|
#include "mozilla/SpinEventLoopUntil.h"
|
||||||
|
@ -270,6 +271,9 @@ nsThreadManager::nsThreadManager()
|
||||||
nsThreadManager::~nsThreadManager() = default;
|
nsThreadManager::~nsThreadManager() = default;
|
||||||
|
|
||||||
nsresult nsThreadManager::Init() {
|
nsresult nsThreadManager::Init() {
|
||||||
|
// Initialize perfetto if on Android.
|
||||||
|
InitPerfetto();
|
||||||
|
|
||||||
// Child processes need to initialize the thread manager before they
|
// Child processes need to initialize the thread manager before they
|
||||||
// initialize XPCOM in order to set up the crash reporter. This leads to
|
// initialize XPCOM in order to set up the crash reporter. This leads to
|
||||||
// situations where we get initialized twice.
|
// situations where we get initialized twice.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче