Backed out 3 changesets (bug 1572337, bug 1594015) for causing linting failures and build bustages CLOSED TREE

Backed out changeset 25f074eb5074 (bug 1594015)
Backed out changeset fc8a37c2c22c (bug 1572337)
Backed out changeset 913d6bd82284 (bug 1572337)
This commit is contained in:
Ciure Andrei 2019-11-07 16:37:00 +02:00
parent 355aa03f2d
commit b7c3599997
14 changed files with 260 additions and 97 deletions

View File

@ -2764,12 +2764,6 @@ void WorkerPrivate::DoRunLoop(JSContext* aCx) {
!(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
!(normalRunnablesPending = NS_HasPendingEvents(mThread)) &&
!(mStatus != Running && !HasActiveWorkerRefs())) {
// We pop out to this loop when there are no pending events.
// If we don't reset these, we may not re-enter ProcessNextEvent()
// until we have events to process, and it may seem like we have
// an event running for a very long time.
mThread->SetRunningEventDelay(TimeDuration(), TimeStamp());
WaitForWorkerEvents();
}

View File

@ -173,6 +173,7 @@ static uint32_t AvailableFeatures() {
// Now remove features not supported on this platform/configuration.
ProfilerFeature::ClearJava(features);
ProfilerFeature::ClearJS(features);
ProfilerFeature::ClearResponsiveness(features);
ProfilerFeature::ClearScreenshots(features);
# if !defined(HAVE_NATIVE_UNWIND)
ProfilerFeature::ClearStackWalk(features);
@ -187,7 +188,8 @@ static uint32_t AvailableFeatures() {
// Default features common to all contexts (even if not available).
static uint32_t DefaultFeatures() {
return ProfilerFeature::Java | ProfilerFeature::JS | ProfilerFeature::Leaf |
ProfilerFeature::StackWalk | ProfilerFeature::Threads;
ProfilerFeature::StackWalk | ProfilerFeature::Threads |
ProfilerFeature::Responsiveness;
}
// Extra default features when MOZ_BASE_PROFILER_STARTUP is set (even if not

View File

@ -134,24 +134,27 @@ class SpliceableJSONWriter;
MACRO(4, "privacy", Privacy, \
"Do not include user-identifiable information") \
\
MACRO(5, "screenshots", Screenshots, \
MACRO(5, "responsiveness", Responsiveness, \
"Collect thread responsiveness information") \
\
MACRO(6, "screenshots", Screenshots, \
"Take a snapshot of the window on every composition") \
\
MACRO(6, "seqstyle", SequentialStyle, \
MACRO(7, "seqstyle", SequentialStyle, \
"Disable parallel traversal in styling") \
\
MACRO(7, "stackwalk", StackWalk, \
MACRO(8, "stackwalk", StackWalk, \
"Walk the C++ stack, not available on all platforms") \
\
MACRO(8, "tasktracer", TaskTracer, \
MACRO(9, "tasktracer", TaskTracer, \
"Start profiling with feature TaskTracer") \
\
MACRO(9, "threads", Threads, "Profile the registered secondary threads") \
MACRO(10, "threads", Threads, "Profile the registered secondary threads") \
\
MACRO(10, "trackopts", TrackOptimizations, \
MACRO(11, "trackopts", TrackOptimizations, \
"Have the JavaScript engine track JIT optimizations") \
\
MACRO(11, "jstracer", JSTracer, "Enable tracing of the JavaScript engine") \
MACRO(12, "jstracer", JSTracer, "Enable tracing of the JavaScript engine") \
\
MACRO(14, "nostacksampling", NoStackSampling, \
"Disable all stack sampling: Cancels \"js\", \"leaf\", " \

View File

@ -961,11 +961,6 @@ nsSocketTransportService::Run() {
startOfNextIteration = TimeStamp::NowLoRes();
}
pollDuration = nullptr;
// We pop out to this loop when there are no pending events.
// If we don't reset these, we may not re-enter ProcessNextEvent()
// until we have events to process, and it may seem like we have
// an event running for a very long time.
mRawThread->SetRunningEventDelay(TimeDuration(), TimeStamp());
do {
if (Telemetry::CanRecordPrereleaseData()) {

View File

@ -47,9 +47,7 @@ add_task(async function() {
}
for (const feature of acceptedFeatures) {
ok(
// Bug 1594566 - ignore Responsiveness until the extension is updated
allFeaturesAcceptedByProfiler.includes(feature) ||
feature == "responsiveness",
allFeaturesAcceptedByProfiler.includes(feature),
`The schema of the geckoProfiler.start() method mentions a "${feature}" feature which is not supported by the profiler.`
);
}

View File

@ -17,9 +17,13 @@
#endif
ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo,
nsIEventTarget* aEventTarget)
nsIEventTarget* aEventTarget,
bool aIncludeResponsiveness)
: mThreadInfo(aThreadInfo) {
MOZ_COUNT_CTOR(ProfiledThreadData);
if (aIncludeResponsiveness) {
mResponsiveness.emplace(aEventTarget, aThreadInfo->IsMainThread());
}
}
ProfiledThreadData::~ProfiledThreadData() {

View File

@ -10,6 +10,7 @@
#include "platform.h"
#include "ProfileBufferEntry.h"
#include "ThreadInfo.h"
#include "ThreadResponsiveness.h"
#include "js/ProfilingStack.h"
#include "mozilla/TimeStamp.h"
@ -42,10 +43,12 @@ class ProfileBuffer;
// when the profiler is stopped.
class ProfiledThreadData final {
public:
ProfiledThreadData(ThreadInfo* aThreadInfo, nsIEventTarget* aEventTarget);
ProfiledThreadData(ThreadInfo* aThreadInfo, nsIEventTarget* aEventTarget,
bool aIncludeResponsiveness);
~ProfiledThreadData();
void NotifyUnregistered(uint64_t aBufferPosition) {
mResponsiveness.reset();
mLastSample = mozilla::Nothing();
MOZ_ASSERT(!mBufferPositionWhenReceivedJSContext,
"JSContext should have been cleared before the thread was "
@ -68,6 +71,13 @@ class ProfiledThreadData final {
void StreamTraceLoggerJSON(JSContext* aCx, SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime);
// Returns nullptr if this is not the main thread, the responsiveness
// feature is not turned on, or if this thread is not being profiled.
ThreadResponsiveness* GetThreadResponsiveness() {
ThreadResponsiveness* responsiveness = mResponsiveness.ptrOr(nullptr);
return responsiveness;
}
const RefPtr<ThreadInfo> Info() const { return mThreadInfo; }
void NotifyReceivedJSContext(uint64_t aCurrentBufferPosition) {
@ -99,6 +109,10 @@ class ProfiledThreadData final {
// The following fields are only used while this thread is alive and
// registered. They become Nothing() once the thread is unregistered.
// A helper object that instruments nsIThreads to obtain responsiveness
// information about their event loop.
mozilla::Maybe<ThreadResponsiveness> mResponsiveness;
// When sampling, this holds the position in ActivePS::mBuffer of the most
// recent sample for this thread, or Nothing() if there is no sample for this
// thread in the buffer.

View File

@ -225,7 +225,8 @@ static uint32_t AvailableFeatures() {
// Default features common to all contexts (even if not available).
static uint32_t DefaultFeatures() {
return ProfilerFeature::Java | ProfilerFeature::JS | ProfilerFeature::Leaf |
ProfilerFeature::StackWalk | ProfilerFeature::Threads;
ProfilerFeature::StackWalk | ProfilerFeature::Threads |
ProfilerFeature::Responsiveness;
}
// Extra default features when MOZ_PROFILER_STARTUP is set (even if not
@ -2347,7 +2348,8 @@ static void locked_profiler_stream_json_for_this_process(
// java thread, we have to get thread id and name via JNI.
RefPtr<ThreadInfo> threadInfo = new ThreadInfo(
"Java Main Thread", 0, false, CorePS::ProcessStartTime());
ProfiledThreadData profiledThreadData(threadInfo, nullptr);
ProfiledThreadData profiledThreadData(
threadInfo, nullptr, ActivePS::FeatureResponsiveness(aLock));
profiledThreadData.StreamJSON(*javaBuffer.get(), nullptr, aWriter,
CorePS::ProcessName(aLock),
CorePS::ProcessStartTime(), aSinceTime,
@ -2437,7 +2439,6 @@ static char FeatureCategory(uint32_t aFeature) {
return 'x';
}
// Doesn't exist if aExitCode is 0
static void PrintUsageThenExit(int aExitCode) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
@ -2537,9 +2538,7 @@ static void PrintUsageThenExit(int aExitCode) {
#endif
);
if (aExitCode != 0) {
exit(aExitCode);
}
exit(aExitCode);
}
////////////////////////////////////////////////////////////////////////
@ -3062,8 +3061,7 @@ static uint32_t ParseFeature(const char* aFeature, bool aIsStartup) {
#undef PARSE_FEATURE_BIT
printf("\nUnrecognized feature \"%s\".\n\n", aFeature);
// Since we may have an old feature we don't implement anymore, don't exit
PrintUsageThenExit(0);
PrintUsageThenExit(1);
return 0;
}
@ -3117,7 +3115,8 @@ static ProfilingStack* locked_register_thread(PSLockRef aLock,
nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
ProfiledThreadData* profiledThreadData = ActivePS::AddLiveProfiledThread(
aLock, registeredThread.get(),
MakeUnique<ProfiledThreadData>(info, eventTarget));
MakeUnique<ProfiledThreadData>(info, eventTarget,
ActivePS::FeatureResponsiveness(aLock)));
if (ActivePS::FeatureJS(aLock)) {
// This StartJSSampling() call is on-thread, so we can poll manually to
@ -3242,7 +3241,7 @@ void profiler_init(void* aStackTop) {
MOZ_RELEASE_ASSERT(!CorePS::Exists());
if (getenv("MOZ_PROFILER_HELP")) {
PrintUsageThenExit(1); // terminates execution
PrintUsageThenExit(0); // terminates execution
}
SharedLibraryInfo::Initialize();
@ -3811,7 +3810,8 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
ProfiledThreadData* profiledThreadData = ActivePS::AddLiveProfiledThread(
aLock, registeredThread.get(),
MakeUnique<ProfiledThreadData>(info, eventTarget));
MakeUnique<ProfiledThreadData>(
info, eventTarget, ActivePS::FeatureResponsiveness(aLock)));
if (ActivePS::FeatureJS(aLock)) {
registeredThread->StartJSSampling(ActivePS::JSFlags(aLock));
if (info->ThreadId() == tid) {

View File

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "ThreadResponsiveness.h"
#include "platform.h"
#include "mozilla/Atomics.h"
#include "mozilla/SystemGroup.h"
#include "nsITimer.h"
using namespace mozilla;
class CheckResponsivenessTask : public CancelableRunnable,
public nsITimerCallback {
public:
explicit CheckResponsivenessTask(nsIEventTarget* aThread, bool aIsMainThread)
: CancelableRunnable("CheckResponsivenessTask"),
mStartToPrevTracer_us(uint64_t(profiler_time() * 1000.0)),
mStop(false),
mHasEverBeenSuccessfullyDispatched(false),
mThread(aThread),
mIsMainThread(aIsMainThread) {}
protected:
~CheckResponsivenessTask() {}
public:
// Must be called from the same thread every time. Call that the update
// thread, because it's the thread that ThreadResponsiveness::Update() is
// called on. In reality it's the profiler's sampler thread.
bool DoFirstDispatchIfNeeded() {
if (mHasEverBeenSuccessfullyDispatched) {
return true;
}
// The profiler for the main thread is set up before the thread manager is,
// meaning we can't get the nsIThread when the CheckResponsivenessTask is
// constructed. We _do_ know whether it is the main thread at that time,
// however, so here's the workaround. We can still hit this code before the
// thread manager is initted, in which case we won't try to record
// responsiveness, which is fine because there's no event queue to check
// responsiveness on anyway.
if (mIsMainThread) {
if (!mThread) {
nsCOMPtr<nsIThread> temp;
NS_GetMainThread(getter_AddRefs(temp));
mThread = temp.forget();
}
if (mThread) {
nsresult rv =
SystemGroup::Dispatch(TaskCategory::Other, do_AddRef(this));
if (NS_SUCCEEDED(rv)) {
mHasEverBeenSuccessfullyDispatched = true;
}
}
} else if (mThread) {
nsresult rv = mThread->Dispatch(this, nsIThread::NS_DISPATCH_NORMAL);
if (NS_SUCCEEDED(rv)) {
mHasEverBeenSuccessfullyDispatched = true;
}
}
return mHasEverBeenSuccessfullyDispatched;
}
nsresult Cancel() override {
// No special work needed.
return NS_OK;
}
// Only runs on the thread being profiled. Always called via a thread
// dispatch, so inherently functions as a responsiveness statistic.
NS_IMETHOD Run() override {
// This approach means that the 16ms delay in the timer below, _plus_ any
// additional delays in the TimerThread itself, become part of the
// responsiveness statistic for this thread. What we should probably be
// doing is recording responsiveness only when we have dispatched (but not
// executed) a call to this function, either because of a call to
// DoFirstDispatchIfNeeded, or a call to Notify.
mStartToPrevTracer_us = uint64_t(profiler_time() * 1000.0);
if (!mStop) {
if (!mTimer) {
if (mIsMainThread) {
mTimer =
NS_NewTimer(SystemGroup::EventTargetFor(TaskCategory::Other));
} else {
mTimer = NS_NewTimer();
}
}
mTimer->InitWithCallback(this, 16, nsITimer::TYPE_ONE_SHOT);
}
return NS_OK;
}
// Should always fire on the thread being profiled
NS_IMETHOD Notify(nsITimer* aTimer) final {
Run();
return NS_OK;
}
// Can be called on any thread.
void Terminate() { mStop = true; }
// Can be called on any thread.
double GetStartToPrevTracer_ms() const {
return mStartToPrevTracer_us / 1000.0;
}
NS_DECL_ISUPPORTS_INHERITED
private:
// The timer that's responsible for redispatching this event to the thread we
// are profiling (ie; mThread). Only touched on mThread.
nsCOMPtr<nsITimer> mTimer;
// The time (in integer microseconds since process startup) at which this
// event was last processed (Run() was last called).
// This field is written on mThread and read on the update thread.
// This is stored as integer microseconds instead of double milliseconds
// because Atomic<double> is not available.
Atomic<uint64_t> mStartToPrevTracer_us;
// Whether we should stop redispatching this event once the timer fires the
// next time. Set to true by any thread when the profiler is stopped; read on
// mThread.
Atomic<bool> mStop;
// Only accessed on the update thread.
bool mHasEverBeenSuccessfullyDispatched;
// The thread that we're profiling. Use nsIEventTarget to allow for checking
// responsiveness on non-nsIThreads someday.
nsCOMPtr<nsIEventTarget> mThread;
bool mIsMainThread;
};
NS_IMPL_ISUPPORTS_INHERITED(CheckResponsivenessTask, CancelableRunnable,
nsITimerCallback)
ThreadResponsiveness::ThreadResponsiveness(nsIEventTarget* aThread,
bool aIsMainThread)
: mActiveTracerEvent(new CheckResponsivenessTask(aThread, aIsMainThread)) {
MOZ_COUNT_CTOR(ThreadResponsiveness);
}
ThreadResponsiveness::~ThreadResponsiveness() {
MOZ_COUNT_DTOR(ThreadResponsiveness);
mActiveTracerEvent->Terminate();
}
void ThreadResponsiveness::Update() {
if (!mActiveTracerEvent->DoFirstDispatchIfNeeded()) {
return;
}
mStartToPrevTracer_ms = Some(mActiveTracerEvent->GetStartToPrevTracer_ms());
}

View File

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 ThreadResponsiveness_h
#define ThreadResponsiveness_h
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
#include "nsISupports.h"
class CheckResponsivenessTask;
class nsIEventTarget;
// This class should only be used for the main thread.
class ThreadResponsiveness {
public:
explicit ThreadResponsiveness(nsIEventTarget* aThread, bool aIsMainThread);
~ThreadResponsiveness();
void Update();
// The number of milliseconds that elapsed since the last
// CheckResponsivenessTask was processed.
double GetUnresponsiveDuration(double aStartToNow_ms) const {
return aStartToNow_ms - *mStartToPrevTracer_ms;
}
bool HasData() const { return mStartToPrevTracer_ms.isSome(); }
private:
RefPtr<CheckResponsivenessTask> mActiveTracerEvent;
// The time at which the last CheckResponsivenessTask was processed, in
// milliseconds since process start (i.e. what you get from profiler_time()).
mozilla::Maybe<double> mStartToPrevTracer_ms;
};
#endif

View File

@ -36,6 +36,7 @@ if CONFIG['MOZ_GECKO_PROFILER']:
'gecko/ProfilerChild.cpp',
'gecko/ProfilerIOInterposeObserver.cpp',
'gecko/ProfilerParent.cpp',
'gecko/ThreadResponsiveness.cpp',
]
if CONFIG['MOZ_REPLACE_MALLOC'] and CONFIG['MOZ_PROFILER_MEMORY']:
SOURCES += [

View File

@ -147,26 +147,29 @@ class Vector;
MACRO(4, "privacy", Privacy, \
"Do not include user-identifiable information") \
\
MACRO(5, "screenshots", Screenshots, \
MACRO(5, "responsiveness", Responsiveness, \
"Collect thread responsiveness information") \
\
MACRO(6, "screenshots", Screenshots, \
"Take a snapshot of the window on every composition") \
\
MACRO(6, "seqstyle", SequentialStyle, \
MACRO(7, "seqstyle", SequentialStyle, \
"Disable parallel traversal in styling") \
\
MACRO(7, "stackwalk", StackWalk, \
MACRO(8, "stackwalk", StackWalk, \
"Walk the C++ stack, not available on all platforms") \
\
MACRO(8, "tasktracer", TaskTracer, \
MACRO(9, "tasktracer", TaskTracer, \
"Start profiling with feature TaskTracer") \
\
MACRO(9, "threads", Threads, "Profile the registered secondary threads") \
MACRO(10, "threads", Threads, "Profile the registered secondary threads") \
\
MACRO(10, "trackopts", TrackOptimizations, \
MACRO(11, "trackopts", TrackOptimizations, \
"Have the JavaScript engine track JIT optimizations") \
\
MACRO(11, "jstracer", JSTracer, "Enable tracing of the JavaScript engine") \
MACRO(12, "jstracer", JSTracer, "Enable tracing of the JavaScript engine") \
\
MACRO(12, "jsallocations", JSAllocations, \
MACRO(13, "jsallocations", JSAllocations, \
"Have the JavaScript engine track allocations") \
\
MACRO(14, "nostacksampling", NoStackSampling, \

View File

@ -1,53 +0,0 @@
/* 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/. */
/**
* Test that we can measure non-zero event delays (responsiveness)
*/
add_task(async () => {
if (!AppConstants.MOZ_GECKO_PROFILER) {
return;
}
const entries = 10000;
const interval = 1;
const threads = [];
const features = [];
Services.profiler.StartProfiler(entries, interval, features, threads);
await functionA();
const profile = await Services.profiler.getProfileDataAsync();
const [thread] = profile.threads;
const { samples } = thread;
const message = "Responsiveness > 0 not found.";
let SAMPLE_STACK_SLOT = thread.samples.schema.responsiveness;
for (let i = 0; i < samples.data.length; i++) {
if (samples.data[i][SAMPLE_STACK_SLOT] > 0) {
Assert.ok(true, message);
return;
}
}
Assert.ok(false, message);
});
function doSyncWork(milliseconds) {
const start = Date.now();
while (true) {
this.n = 0;
for (let i = 0; i < 1e5; i++) {
this.n += Math.random();
}
if (Date.now() - start > milliseconds) {
return;
}
}
}
function functionA() {
doSyncWork(100);
doAtLeastOnePeriodicSample();
}

View File

@ -6,7 +6,6 @@ skip-if = toolkit == 'android'
[test_start.js]
skip-if = true
[test_get_features.js]
[test_responsiveness.js]
[test_shared_library.js]
[test_run.js]
skip-if = true