Quelle ProfilerThreadRegistrationData.cpp
Sprache: C
/* -*- 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/. */
ThreadRegistrationData::ThreadRegistrationData(constchar* aName, constvoid* aStackTop)
: mInfo(aName),
mPlatformData(mInfo.ThreadId()),
mStackTop( #ifdefined(XP_WIN) // We don't have to guess on Windows. reinterpret_cast<constvoid*>( reinterpret_cast<PNT_TIB>(NtCurrentTeb())->StackBase) #elifdefined(XP_DARWIN) // We don't have to guess on Mac/Darwin. reinterpret_cast<constvoid*>(
pthread_get_stackaddr_np(pthread_self())) #else // Otherwise use the given guess.
aStackTop #endif
) {
}
// This is a simplified version of profiler_add_marker that can be easily passed // into the JS engine. staticvoid profiler_add_js_marker(constchar* aMarkerName, constchar* aMarkerText) {
PROFILER_MARKER_TEXT(
mozilla::ProfilerString8View::WrapNullTerminatedString(aMarkerName), JS,
{}, mozilla::ProfilerString8View::WrapNullTerminatedString(aMarkerText));
}
staticvoid profiler_add_js_allocation_marker(JS::RecordAllocationInfo&& info) { if (!profiler_thread_is_being_profiled_for_markers()) { return;
}
if (mCCJSContext) { // The thread is now being profiled, and we already have a JSContext, // allocate a JsFramesBuffer to allow profiler-unlocked on-thread sampling.
MOZ_ASSERT(!mJsFrameBuffer);
mJsFrameBuffer = new JsFrame[MAX_JS_FRAMES];
}
if (mProfiledThreadData) {
MOZ_ASSERT((mProfilingFeatures != ThreadProfilingFeatures::NotProfiled) ==
!!mProfiledThreadData); // We now have a JSContext, and the thread is already being profiled, // allocate a JsFramesBuffer to allow profiler-unlocked on-thread sampling.
MOZ_ASSERT(!mJsFrameBuffer);
mJsFrameBuffer = new JsFrame[MAX_JS_FRAMES];
}
// We give the JS engine a non-owning reference to the ProfilingStack. It's // important that the JS engine doesn't touch this once the thread dies.
js::SetContextProfilingStack(aCx->Context(), &ProfilingStackRef());
void ThreadRegistrationLockedRWOnThread::PollJSSampling() { // We can't start/stop profiling until we have the thread's JSContext. if (mCCJSContext) { // It is possible for mJSSampling to go through the following sequences. // // - INACTIVE, ACTIVE_REQUESTED, INACTIVE_REQUESTED, INACTIVE // // - ACTIVE, INACTIVE_REQUESTED, ACTIVE_REQUESTED, ACTIVE // // Therefore, the if and else branches here aren't always interleaved. // This is ok because the JS engine can handle that. //
JSContext* cx = mCCJSContext->Context(); if (mJSSampling == ACTIVE_REQUESTED) {
mJSSampling = ACTIVE;
js::EnableContextProfilingStack(cx, true);
if (JSAllocationsEnabled()) { // TODO - This probability should not be hardcoded. See Bug 1547284.
JS::EnableRecordingAllocations(cx, profiler_add_js_allocation_marker,
0.01);
}
js::RegisterContextProfilingEventMarker(cx, profiler_add_js_marker);
uint64_t newWakeCount = mWakeCount - mAlreadyRecordedWakeCount; if (newWakeCount == 0 && mSleep != AWAKE) { // If no new wake-up was counted, and the thread is not marked awake, // we can be pretty sure there is no CPU activity to record. // Threads that are never annotated as asleep/awake (typically rust threads) // start as awake. return;
}
uint64_t cpuTimeNs; if (!GetCpuTimeSinceThreadStartInNs(&cpuTimeNs, PlatformDataCRef())) {
cpuTimeNs = 0;
}
if (!newWakeCount && !newCpuTimeMs) { // Nothing to report, avoid computing the Glean friendly thread name. return;
}
nsAutoCString threadName(mInfo.Name()); // Trim the trailing number of threads that are part of a thread pool. for (size_t length = threadName.Length(); length > 0; --length) { constchar c = threadName.CharAt(length - 1); if ((c < '0' || c > '9') && c != '#' && c != ' ') { if (length != threadName.Length()) {
threadName.SetLength(length);
} break;
}
}
// The thread id is provided as part of the payload because this call is // inside a ThreadRegistration data function, which could be invoked with // the ThreadRegistry locked. We cannot call any function/option that could // attempt to lock the ThreadRegistry again, like MarkerThreadId.
PROFILER_MARKER("Thread CPU use", OTHER, {}, ThreadCpuUseMarker,
mInfo.ThreadId(), newCpuTimeMs, newWakeCount, threadName);
mAlreadyRecordedCpuTimeInMs = cpuTimeMs;
mAlreadyRecordedWakeCount += newWakeCount;
} #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.