зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1753305 - Add 'Awake' profiler markers whenever a thread is awake, r=gerald.
Differential Revision: https://phabricator.services.mozilla.com/D137695
This commit is contained in:
Родитель
7b45ca4063
Коммит
7e1f0527c2
|
@ -350,7 +350,6 @@ void BackgroundHangManager::RunMonitorThread() {
|
|||
while (!mShutdown) {
|
||||
autoLock.Wait(waitTime);
|
||||
|
||||
PROFILER_MARKER_UNTYPED("Wakeup", OTHER);
|
||||
TimeStamp newTime = TimeStamp::Now();
|
||||
TimeDuration systemInterval = newTime - systemTime;
|
||||
systemTime = newTime;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/ProfilerMarkers.h"
|
||||
#include "mozilla/ProfilerThreadRegistry.h"
|
||||
#include "nsString.h"
|
||||
#include "platform.h"
|
||||
|
||||
namespace mozilla::profiler {
|
||||
|
||||
|
@ -41,6 +42,7 @@ ThreadRegistration::ThreadRegistration(const char* aName, const void* aStackTop)
|
|||
|
||||
tls->set(this);
|
||||
ThreadRegistry::Register(OnThreadRef{*this});
|
||||
profiler_mark_thread_awake();
|
||||
}
|
||||
|
||||
ThreadRegistration::~ThreadRegistration() {
|
||||
|
@ -65,6 +67,7 @@ ThreadRegistration::~ThreadRegistration() {
|
|||
return;
|
||||
}
|
||||
|
||||
profiler_mark_thread_asleep();
|
||||
ThreadRegistry::Unregister(OnThreadRef{*this});
|
||||
#ifdef DEBUG
|
||||
// After ThreadRegistry::Unregister, other threads should not be able to
|
||||
|
|
|
@ -106,6 +106,22 @@
|
|||
# include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
|
||||
#if defined(GP_PLAT_amd64_darwin)
|
||||
# include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#if defined(GP_OS_windows)
|
||||
# include <processthreadsapi.h>
|
||||
|
||||
// GetThreadInformation is not available on Windows 7.
|
||||
WINBASEAPI
|
||||
BOOL WINAPI GetThreadInformation(
|
||||
_In_ HANDLE hThread, _In_ THREAD_INFORMATION_CLASS ThreadInformationClass,
|
||||
_Out_writes_bytes_(ThreadInformationSize) LPVOID ThreadInformation,
|
||||
_In_ DWORD ThreadInformationSize);
|
||||
|
||||
#endif
|
||||
|
||||
// Win32 builds always have frame pointers, so FramePointerStackWalk() always
|
||||
// works.
|
||||
#if defined(GP_PLAT_x86_windows)
|
||||
|
@ -5030,6 +5046,10 @@ void profiler_init(void* aStackTop) {
|
|||
filters.length(), activeTabID, duration);
|
||||
}
|
||||
|
||||
// The GeckoMain thread registration happened too early to record a marker,
|
||||
// so let's record it again now.
|
||||
profiler_mark_thread_awake();
|
||||
|
||||
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
|
||||
// Start counting memory allocations (outside of lock because this may call
|
||||
// profiler_add_sampled_counter which would attempt to take the lock.)
|
||||
|
@ -6191,14 +6211,143 @@ Maybe<uint64_t> profiler_get_inner_window_id_from_docshell(
|
|||
|
||||
} // namespace geckoprofiler::markers::detail
|
||||
|
||||
namespace geckoprofiler::markers {
|
||||
|
||||
struct CPUAwakeMarker {
|
||||
static constexpr Span<const char> MarkerTypeName() {
|
||||
return MakeStringSpan("Awake");
|
||||
}
|
||||
static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
|
||||
int64_t aCPUId
|
||||
#ifdef GP_OS_darwin
|
||||
,
|
||||
uint32_t aQoS
|
||||
#endif
|
||||
#ifdef GP_OS_windows
|
||||
,
|
||||
int32_t aAbsolutePriority,
|
||||
int32_t aRelativePriority
|
||||
#endif
|
||||
) {
|
||||
#ifndef GP_PLAT_arm64_darwin
|
||||
aWriter.IntProperty("CPU Id", aCPUId);
|
||||
#endif
|
||||
#ifdef GP_OS_windows
|
||||
if (aAbsolutePriority) {
|
||||
aWriter.IntProperty("absPriority", aAbsolutePriority);
|
||||
}
|
||||
aWriter.IntProperty("priority", aRelativePriority);
|
||||
#endif
|
||||
#ifdef GP_OS_darwin
|
||||
const char* QoS = "";
|
||||
switch (aQoS) {
|
||||
case QOS_CLASS_USER_INTERACTIVE:
|
||||
QoS = "User Interactive";
|
||||
break;
|
||||
case QOS_CLASS_USER_INITIATED:
|
||||
QoS = "User Initiated";
|
||||
break;
|
||||
case QOS_CLASS_DEFAULT:
|
||||
QoS = "Default";
|
||||
break;
|
||||
case QOS_CLASS_UTILITY:
|
||||
QoS = "Utility";
|
||||
break;
|
||||
case QOS_CLASS_BACKGROUND:
|
||||
QoS = "Background";
|
||||
break;
|
||||
default:
|
||||
QoS = "Unspecified";
|
||||
}
|
||||
|
||||
aWriter.StringProperty("QoS",
|
||||
ProfilerString8View::WrapNullTerminatedString(QoS));
|
||||
#endif
|
||||
}
|
||||
|
||||
static MarkerSchema MarkerTypeDisplay() {
|
||||
using MS = MarkerSchema;
|
||||
MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
|
||||
#ifndef GP_PLAT_arm64_darwin
|
||||
schema.AddKeyFormat("CPU Id", MS::Format::Integer);
|
||||
schema.SetTableLabel("Awake - CPU Id = {marker.data.CPU Id}");
|
||||
#endif
|
||||
#ifdef GP_OS_windows
|
||||
schema.AddKeyLabelFormat("priority", "Relative Thread Priority",
|
||||
MS::Format::Integer);
|
||||
schema.AddKeyLabelFormat("absPriority", "Absolute Thread Priority",
|
||||
MS::Format::Integer);
|
||||
#endif
|
||||
#ifdef GP_OS_darwin
|
||||
schema.AddKeyLabelFormat("QoS", "Quality of Service", MS::Format::String);
|
||||
#endif
|
||||
return schema;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace geckoprofiler::markers
|
||||
|
||||
void profiler_mark_thread_asleep() {
|
||||
PROFILER_MARKER_UNTYPED("Awake", OTHER, MarkerTiming::IntervalEnd());
|
||||
}
|
||||
|
||||
void profiler_thread_sleep() {
|
||||
profiler_mark_thread_asleep();
|
||||
ThreadRegistration::WithOnThreadRef(
|
||||
[](ThreadRegistration::OnThreadRef aOnThreadRef) {
|
||||
aOnThreadRef.UnlockedConstReaderAndAtomicRWRef().SetSleeping();
|
||||
});
|
||||
}
|
||||
|
||||
void profiler_mark_thread_awake() {
|
||||
if (!profiler_thread_is_being_profiled_for_markers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t cpuId = 0;
|
||||
#if defined(GP_OS_windows)
|
||||
cpuId = GetCurrentProcessorNumber();
|
||||
#elif defined(GP_OS_darwin)
|
||||
# ifdef GP_PLAT_amd64_darwin
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
__cpuid_count(1, 0, eax, ebx, ecx, edx);
|
||||
// Check if we have an APIC.
|
||||
if ((edx & (1 << 9))) {
|
||||
// APIC ID is bits 24-31 of EBX
|
||||
cpuId = ebx >> 24;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
cpuId = sched_getcpu();
|
||||
#endif
|
||||
|
||||
#if defined(GP_OS_windows)
|
||||
LONG priority;
|
||||
static const auto get_thread_information_fn =
|
||||
reinterpret_cast<decltype(&::GetThreadInformation)>(::GetProcAddress(
|
||||
::GetModuleHandle(L"Kernel32.dll"), "GetThreadInformation"));
|
||||
|
||||
if (!get_thread_information_fn ||
|
||||
!get_thread_information_fn(GetCurrentThread(), ThreadAbsoluteCpuPriority,
|
||||
&priority, sizeof(priority))) {
|
||||
priority = 0;
|
||||
}
|
||||
#endif
|
||||
PROFILER_MARKER("Awake", OTHER, MarkerTiming::IntervalStart(), CPUAwakeMarker,
|
||||
cpuId
|
||||
#if defined(GP_OS_darwin)
|
||||
,
|
||||
qos_class_self()
|
||||
#endif
|
||||
#if defined(GP_OS_windows)
|
||||
,
|
||||
priority, GetThreadPriority(GetCurrentThread())
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void profiler_thread_wake() {
|
||||
profiler_mark_thread_awake();
|
||||
ThreadRegistration::WithOnThreadRef(
|
||||
[](ThreadRegistration::OnThreadRef aOnThreadRef) {
|
||||
aOnThreadRef.UnlockedConstReaderAndAtomicRWRef().SetAwake();
|
||||
|
|
|
@ -92,6 +92,11 @@ uint32_t ParseFeaturesFromStringArray(const char** aFeatures,
|
|||
uint32_t aFeatureCount,
|
||||
bool aIsStartup = false);
|
||||
|
||||
// Add the begin/end 'Awake' markers for the thread.
|
||||
void profiler_mark_thread_awake();
|
||||
|
||||
void profiler_mark_thread_asleep();
|
||||
|
||||
bool profiler_get_profile_json(
|
||||
SpliceableChunkedJSONWriter& aSpliceableChunkedJSONWriter,
|
||||
double aSinceTime, bool aIsShuttingDown,
|
||||
|
|
Загрузка…
Ссылка в новой задаче