mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1862556: Allow LongTask markers to be generated for any nsThread r=nika
Differential Revision: https://phabricator.services.mozilla.com/D192532
This commit is contained in:
parent
9c00b13451
commit
e47f68f60e
@ -411,8 +411,7 @@ void StorageDBThread::SetDefaultPriority() {
|
||||
void StorageDBThread::ThreadFunc(void* aArg) {
|
||||
{
|
||||
auto queue = MakeRefPtr<ThreadEventQueue>(MakeUnique<EventQueue>());
|
||||
Unused << nsThreadManager::get().CreateCurrentThread(
|
||||
queue, nsThread::NOT_MAIN_THREAD);
|
||||
Unused << nsThreadManager::get().CreateCurrentThread(queue);
|
||||
}
|
||||
|
||||
AUTO_PROFILER_REGISTER_THREAD("localStorage DB");
|
||||
|
@ -152,8 +152,7 @@ void Thread::ThreadMain() {
|
||||
loopType == MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD) {
|
||||
auto queue = mozilla::MakeRefPtr<mozilla::ThreadEventQueue>(
|
||||
mozilla::MakeUnique<mozilla::EventQueue>());
|
||||
xpcomThread = nsThreadManager::get().CreateCurrentThread(
|
||||
queue, nsThread::NOT_MAIN_THREAD);
|
||||
xpcomThread = nsThreadManager::get().CreateCurrentThread(queue);
|
||||
} else {
|
||||
xpcomThread = NS_GetCurrentThread();
|
||||
}
|
||||
|
@ -381,8 +381,7 @@ void CacheIOThread::ThreadFunc() {
|
||||
auto queue =
|
||||
MakeRefPtr<ThreadEventQueue>(MakeUnique<mozilla::EventQueue>());
|
||||
nsCOMPtr<nsIThread> xpcomThread =
|
||||
nsThreadManager::get().CreateCurrentThread(queue,
|
||||
nsThread::NOT_MAIN_THREAD);
|
||||
nsThreadManager::get().CreateCurrentThread(queue);
|
||||
|
||||
threadInternal = do_QueryInterface(xpcomThread);
|
||||
if (threadInternal) threadInternal->SetObserver(this);
|
||||
|
@ -13,6 +13,10 @@ interface nsIEventTarget;
|
||||
interface nsIRunnable;
|
||||
interface nsIThread;
|
||||
|
||||
%{ C++
|
||||
#include "mozilla/Maybe.h"
|
||||
%}
|
||||
|
||||
[scriptable, function, uuid(039a227d-0cb7-44a5-a8f9-dbb7071979f2)]
|
||||
interface nsINestedEventLoopCondition : nsISupports
|
||||
{
|
||||
@ -72,6 +76,11 @@ interface nsIThreadManager : nsISupports
|
||||
// (Windows-only) Whether the thread should have a MessageLoop capable of
|
||||
// processing native UI events. Defaults to false.
|
||||
bool isUiThread = false;
|
||||
|
||||
// If set, long task markers will be collected for tasks
|
||||
// longer than longTaskLength ms when profiling is enabled.
|
||||
// See https://www.w3.org/TR/longtasks
|
||||
mozilla::Maybe<uint32_t> longTaskLength;
|
||||
};
|
||||
%}
|
||||
|
||||
|
@ -550,7 +550,8 @@ nsThread::nsThread(NotNull<SynchronizedEventQueue*> aQueue,
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
mLastWakeupCheckTime(TimeStamp::Now()),
|
||||
#endif
|
||||
mPerformanceCounterState(mNestedEventLoopDepth, mIsMainThread) {
|
||||
mPerformanceCounterState(mNestedEventLoopDepth, mIsMainThread,
|
||||
aOptions.longTaskLength) {
|
||||
#if !(defined(XP_WIN) || defined(XP_MACOSX))
|
||||
MOZ_ASSERT(!mIsUiThread,
|
||||
"Non-main UI threads are only supported on Windows and macOS");
|
||||
@ -581,7 +582,7 @@ nsThread::nsThread()
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
mLastWakeupCheckTime(TimeStamp::Now()),
|
||||
#endif
|
||||
mPerformanceCounterState(mNestedEventLoopDepth, mIsMainThread) {
|
||||
mPerformanceCounterState(mNestedEventLoopDepth) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
}
|
||||
|
||||
@ -1458,9 +1459,11 @@ void nsThreadShutdownContext::MarkCompleted() {
|
||||
namespace mozilla {
|
||||
PerformanceCounterState::Snapshot PerformanceCounterState::RunnableWillRun(
|
||||
TimeStamp aNow, bool aIsIdleRunnable) {
|
||||
if (IsNestedRunnable()) {
|
||||
if (mIsMainThread && IsNestedRunnable()) {
|
||||
// Flush out any accumulated time that should be accounted to the
|
||||
// current runnable before we start running a nested runnable.
|
||||
// current runnable before we start running a nested runnable. Don't
|
||||
// do this for non-mainthread threads that may be running their own
|
||||
// event loops, like SocketThread.
|
||||
MaybeReportAccumulatedTime("nested runnable"_ns, aNow);
|
||||
}
|
||||
|
||||
@ -1482,10 +1485,10 @@ void PerformanceCounterState::RunnableDidRun(const nsCString& aName,
|
||||
// We may not need the current timestamp; don't bother computing it if we
|
||||
// don't.
|
||||
TimeStamp now;
|
||||
if (mIsMainThread || IsNestedRunnable()) {
|
||||
if (mLongTaskLength.isSome() || IsNestedRunnable()) {
|
||||
now = TimeStamp::Now();
|
||||
}
|
||||
if (mIsMainThread) {
|
||||
if (mLongTaskLength.isSome()) {
|
||||
MaybeReportAccumulatedTime(aName, now);
|
||||
}
|
||||
|
||||
@ -1505,9 +1508,7 @@ void PerformanceCounterState::MaybeReportAccumulatedTime(const nsCString& aName,
|
||||
TimeStamp aNow) {
|
||||
MOZ_ASSERT(mCurrentTimeSliceStart,
|
||||
"How did we get here if we're not in a timeslice?");
|
||||
|
||||
if (!mIsMainThread) {
|
||||
// No one cares about this timeslice.
|
||||
if (!mLongTaskLength.isSome()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1520,7 +1521,7 @@ void PerformanceCounterState::MaybeReportAccumulatedTime(const nsCString& aName,
|
||||
#endif
|
||||
|
||||
// Long tasks only matter on the main thread.
|
||||
if (mIsMainThread && duration.ToMilliseconds() > LONGTASK_BUSY_WINDOW_MS) {
|
||||
if (duration.ToMilliseconds() >= mLongTaskLength.value()) {
|
||||
// Idle events (gc...) don't *really* count here
|
||||
if (!mCurrentRunnableIsIdleRunnable) {
|
||||
mLastLongNonIdleTaskEnd = aNow;
|
||||
|
@ -46,7 +46,7 @@ class nsIRunnable;
|
||||
class nsThreadShutdownContext;
|
||||
|
||||
// See https://www.w3.org/TR/longtasks
|
||||
#define LONGTASK_BUSY_WINDOW_MS 50
|
||||
#define W3_LONGTASK_BUSY_WINDOW_MS 50
|
||||
|
||||
// Time a Runnable executes before we accumulate telemetry on it
|
||||
#define LONGTASK_TELEMETRY_MS 30
|
||||
@ -55,10 +55,12 @@ class nsThreadShutdownContext;
|
||||
namespace mozilla {
|
||||
class PerformanceCounterState {
|
||||
public:
|
||||
explicit PerformanceCounterState(const uint32_t& aNestedEventLoopDepthRef,
|
||||
bool aIsMainThread)
|
||||
explicit PerformanceCounterState(
|
||||
const uint32_t& aNestedEventLoopDepthRef, bool aIsMainThread = false,
|
||||
const Maybe<uint32_t>& aLongTaskLength = Nothing())
|
||||
: mNestedEventLoopDepth(aNestedEventLoopDepthRef),
|
||||
mIsMainThread(aIsMainThread),
|
||||
mLongTaskLength(aLongTaskLength),
|
||||
// Does it really make sense to initialize these to "now" when we
|
||||
// haven't run any tasks?
|
||||
mLastLongTaskEnd(TimeStamp::Now()),
|
||||
@ -130,6 +132,9 @@ class PerformanceCounterState {
|
||||
// Whether we're attached to the mainthread nsThread.
|
||||
const bool mIsMainThread;
|
||||
|
||||
// what is considered a LongTask (in ms)
|
||||
const Maybe<uint32_t> mLongTaskLength;
|
||||
|
||||
// The timestamp from which time to be accounted for should be measured. This
|
||||
// can be the start of a runnable running or the end of a nested runnable
|
||||
// running.
|
||||
|
@ -308,8 +308,9 @@ nsresult nsThreadManager::Init() {
|
||||
RefPtr<ThreadEventQueue> synchronizedQueue =
|
||||
new ThreadEventQueue(std::move(queue), true);
|
||||
|
||||
mMainThread = new nsThread(WrapNotNull(synchronizedQueue),
|
||||
nsThread::MAIN_THREAD, {.stackSize = 0});
|
||||
mMainThread = new nsThread(
|
||||
WrapNotNull(synchronizedQueue), nsThread::MAIN_THREAD,
|
||||
{.stackSize = 0, .longTaskLength = Some(W3_LONGTASK_BUSY_WINDOW_MS)});
|
||||
|
||||
nsresult rv = mMainThread->InitCurrentThread();
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -490,8 +491,8 @@ void nsThreadManager::UnregisterCurrentThread(nsThread& aThread) {
|
||||
// Ref-count balanced via ReleaseThread
|
||||
}
|
||||
|
||||
nsThread* nsThreadManager::CreateCurrentThread(
|
||||
SynchronizedEventQueue* aQueue, nsThread::MainThreadFlag aMainThread) {
|
||||
// Not to be used for MainThread!
|
||||
nsThread* nsThreadManager::CreateCurrentThread(SynchronizedEventQueue* aQueue) {
|
||||
// Make sure we don't have an nsThread yet.
|
||||
MOZ_ASSERT(!PR_GetThreadPrivate(mCurThreadIndex));
|
||||
|
||||
@ -499,8 +500,8 @@ nsThread* nsThreadManager::CreateCurrentThread(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsThread> thread =
|
||||
new nsThread(WrapNotNull(aQueue), aMainThread, {.stackSize = 0});
|
||||
RefPtr<nsThread> thread = new nsThread(
|
||||
WrapNotNull(aQueue), nsThread::NOT_MAIN_THREAD, {.stackSize = 0});
|
||||
if (NS_FAILED(thread->InitCurrentThread())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -69,8 +69,7 @@ class nsThreadManager : public nsIThreadManager {
|
||||
// the thread that was created. GetCurrentThread() will also create a thread
|
||||
// (lazily), but it doesn't allow the queue or main-thread attributes to be
|
||||
// specified.
|
||||
nsThread* CreateCurrentThread(mozilla::SynchronizedEventQueue* aQueue,
|
||||
nsThread::MainThreadFlag aMainThread);
|
||||
nsThread* CreateCurrentThread(mozilla::SynchronizedEventQueue* aQueue);
|
||||
|
||||
nsresult DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||
uint32_t aDispatchFlags);
|
||||
|
Loading…
Reference in New Issue
Block a user