mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1328365 (part 1) - Replace tlsTicker with gSampler. r=mstange.
There is a single GeckoSampler and it is currently only accessed on the main thread, so it's silly to use TLS for it; a normal global variable is better. This patch also adds main thread assertions to a number of the profiler_*() functions. Even though bug 1330184 may get rid of some of them, right now they are a useful as both a sanity check and documentation. --HG-- extra : rebase_source : 7613eb3cc8089b31180365f6463c81f4556c7b66
This commit is contained in:
parent
22bea68112
commit
fd25b06c81
@ -2896,6 +2896,9 @@ WorkerThreadPrimaryRunnable::Run()
|
|||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (stack) {
|
if (stack) {
|
||||||
|
// XXX: this is currently a no-op because control ends up
|
||||||
|
// PseudoStack::flushSamplerOnJSShutdown() which is a no-op for any
|
||||||
|
// thread other than the main thread. See the comment in that function.
|
||||||
stack->sampleContext(nullptr);
|
stack->sampleContext(nullptr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -605,9 +605,15 @@ void GeckoSampler::FlushOnJSShutdown(JSContext* aContext)
|
|||||||
void PseudoStack::flushSamplerOnJSShutdown()
|
void PseudoStack::flushSamplerOnJSShutdown()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mContext);
|
MOZ_ASSERT(mContext);
|
||||||
GeckoSampler* t = tlsTicker.get();
|
|
||||||
if (t) {
|
// XXX: this function should handle being called by any thread, but it
|
||||||
t->FlushOnJSShutdown(mContext);
|
// currently doesn't because it accesses gSampler, which is main-thread-only.
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gSampler) {
|
||||||
|
gSampler->FlushOnJSShutdown(mContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
|
MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
|
||||||
MOZ_THREAD_LOCAL(GeckoSampler *) tlsTicker;
|
GeckoSampler* gSampler;
|
||||||
|
|
||||||
// We need to track whether we've been initialized otherwise
|
// We need to track whether we've been initialized otherwise
|
||||||
// we end up using tlsStack without initializing it.
|
// we end up using tlsStack without initializing it.
|
||||||
// Because tlsStack is totally opaque to us we can't reuse
|
// Because tlsStack is totally opaque to us we can't reuse
|
||||||
@ -505,6 +506,8 @@ profiler_log(const char* fmt, va_list args)
|
|||||||
void
|
void
|
||||||
profiler_init(void* stackTop)
|
profiler_init(void* stackTop)
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
sInitCount++;
|
sInitCount++;
|
||||||
|
|
||||||
if (stack_key_initialized)
|
if (stack_key_initialized)
|
||||||
@ -515,7 +518,7 @@ profiler_init(void* stackTop)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG("BEGIN profiler_init");
|
LOG("BEGIN profiler_init");
|
||||||
if (!tlsPseudoStack.init() || !tlsTicker.init()) {
|
if (!tlsPseudoStack.init()) {
|
||||||
LOG("Failed to init.");
|
LOG("Failed to init.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -581,20 +584,21 @@ profiler_init(void* stackTop)
|
|||||||
void
|
void
|
||||||
profiler_shutdown()
|
profiler_shutdown()
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
sInitCount--;
|
sInitCount--;
|
||||||
|
|
||||||
if (sInitCount > 0)
|
if (sInitCount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Save the profile on shutdown if requested.
|
// Save the profile on shutdown if requested.
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (gSampler) {
|
||||||
if (t) {
|
|
||||||
const char *val = getenv("MOZ_PROFILER_SHUTDOWN");
|
const char *val = getenv("MOZ_PROFILER_SHUTDOWN");
|
||||||
if (val) {
|
if (val) {
|
||||||
std::ofstream stream;
|
std::ofstream stream;
|
||||||
stream.open(val);
|
stream.open(val);
|
||||||
if (stream.is_open()) {
|
if (stream.is_open()) {
|
||||||
t->ToStreamAsJSON(stream);
|
gSampler->ToStreamAsJSON(stream);
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,48 +622,52 @@ profiler_shutdown()
|
|||||||
mozilla::UniquePtr<char[]>
|
mozilla::UniquePtr<char[]>
|
||||||
profiler_get_profile(double aSinceTime)
|
profiler_get_profile(double aSinceTime)
|
||||||
{
|
{
|
||||||
GeckoSampler *t = tlsTicker.get();
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
if (!t) {
|
|
||||||
|
if (!gSampler) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return t->ToJSON(aSinceTime);
|
return gSampler->ToJSON(aSinceTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
profiler_get_profile_jsobject(JSContext *aCx, double aSinceTime)
|
profiler_get_profile_jsobject(JSContext *aCx, double aSinceTime)
|
||||||
{
|
{
|
||||||
GeckoSampler *t = tlsTicker.get();
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
if (!t) {
|
|
||||||
|
if (!gSampler) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return t->ToJSObject(aCx, aSinceTime);
|
return gSampler->ToJSObject(aCx, aSinceTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
profiler_get_profile_jsobject_async(double aSinceTime,
|
profiler_get_profile_jsobject_async(double aSinceTime,
|
||||||
mozilla::dom::Promise* aPromise)
|
mozilla::dom::Promise* aPromise)
|
||||||
{
|
{
|
||||||
GeckoSampler *t = tlsTicker.get();
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
if (NS_WARN_IF(!t)) {
|
|
||||||
|
if (NS_WARN_IF(!gSampler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->ToJSObjectAsync(aSinceTime, aPromise);
|
gSampler->ToJSObjectAsync(aSinceTime, aPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
profiler_save_profile_to_file_async(double aSinceTime, const char* aFileName)
|
profiler_save_profile_to_file_async(double aSinceTime, const char* aFileName)
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
nsCString filename(aFileName);
|
nsCString filename(aFileName);
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction([=] () {
|
NS_DispatchToMainThread(NS_NewRunnableFunction([=] () {
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (NS_WARN_IF(!gSampler)) {
|
||||||
if (NS_WARN_IF(!t)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->ToFileAsync(filename, aSinceTime);
|
gSampler->ToFileAsync(filename, aSinceTime);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,26 +677,28 @@ profiler_get_start_params(int* aEntrySize,
|
|||||||
mozilla::Vector<const char*>* aFilters,
|
mozilla::Vector<const char*>* aFilters,
|
||||||
mozilla::Vector<const char*>* aFeatures)
|
mozilla::Vector<const char*>* aFeatures)
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (NS_WARN_IF(!aEntrySize) || NS_WARN_IF(!aInterval) ||
|
if (NS_WARN_IF(!aEntrySize) || NS_WARN_IF(!aInterval) ||
|
||||||
NS_WARN_IF(!aFilters) || NS_WARN_IF(!aFeatures)) {
|
NS_WARN_IF(!aFilters) || NS_WARN_IF(!aFeatures)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (NS_WARN_IF(!gSampler)) {
|
||||||
if (NS_WARN_IF(!t)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aEntrySize = t->EntrySize();
|
*aEntrySize = gSampler->EntrySize();
|
||||||
*aInterval = t->interval();
|
*aInterval = gSampler->interval();
|
||||||
|
|
||||||
const ThreadNameFilterList& threadNameFilterList = t->ThreadNameFilters();
|
const ThreadNameFilterList& threadNameFilterList =
|
||||||
|
gSampler->ThreadNameFilters();
|
||||||
MOZ_ALWAYS_TRUE(aFilters->resize(threadNameFilterList.length()));
|
MOZ_ALWAYS_TRUE(aFilters->resize(threadNameFilterList.length()));
|
||||||
for (uint32_t i = 0; i < threadNameFilterList.length(); ++i) {
|
for (uint32_t i = 0; i < threadNameFilterList.length(); ++i) {
|
||||||
(*aFilters)[i] = threadNameFilterList[i].c_str();
|
(*aFilters)[i] = threadNameFilterList[i].c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureList& featureList = t->Features();
|
const FeatureList& featureList = gSampler->Features();
|
||||||
MOZ_ALWAYS_TRUE(aFeatures->resize(featureList.length()));
|
MOZ_ALWAYS_TRUE(aFeatures->resize(featureList.length()));
|
||||||
for (size_t i = 0; i < featureList.length(); ++i) {
|
for (size_t i = 0; i < featureList.length(); ++i) {
|
||||||
(*aFeatures)[i] = featureList[i].c_str();
|
(*aFeatures)[i] = featureList[i].c_str();
|
||||||
@ -698,6 +708,8 @@ profiler_get_start_params(int* aEntrySize,
|
|||||||
void
|
void
|
||||||
profiler_get_gatherer(nsISupports** aRetVal)
|
profiler_get_gatherer(nsISupports** aRetVal)
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (!aRetVal) {
|
if (!aRetVal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -707,27 +719,27 @@ profiler_get_gatherer(nsISupports** aRetVal)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (NS_WARN_IF(!gSampler)) {
|
||||||
if (NS_WARN_IF(!t)) {
|
|
||||||
*aRetVal = nullptr;
|
*aRetVal = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->GetGatherer(aRetVal);
|
gSampler->GetGatherer(aRetVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
profiler_save_profile_to_file(const char* aFilename)
|
profiler_save_profile_to_file(const char* aFilename)
|
||||||
{
|
{
|
||||||
GeckoSampler *t = tlsTicker.get();
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
if (!t) {
|
|
||||||
|
if (!gSampler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream stream;
|
std::ofstream stream;
|
||||||
stream.open(aFilename);
|
stream.open(aFilename);
|
||||||
if (stream.is_open()) {
|
if (stream.is_open()) {
|
||||||
t->ToStreamAsJSON(stream);
|
gSampler->ToStreamAsJSON(stream);
|
||||||
stream.close();
|
stream.close();
|
||||||
LOGF("Saved to %s", aFilename);
|
LOGF("Saved to %s", aFilename);
|
||||||
} else {
|
} else {
|
||||||
@ -790,14 +802,16 @@ profiler_get_buffer_info_helper(uint32_t *aCurrentPosition,
|
|||||||
// This function is called by profiler_get_buffer_info(), which has already
|
// This function is called by profiler_get_buffer_info(), which has already
|
||||||
// zeroed the outparams.
|
// zeroed the outparams.
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (!stack_key_initialized)
|
if (!stack_key_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (!gSampler) {
|
||||||
if (!t)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
t->GetBufferInfo(aCurrentPosition, aTotalSize, aGeneration);
|
gSampler->GetBufferInfo(aCurrentPosition, aTotalSize, aGeneration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values are only honored on the first start
|
// Values are only honored on the first start
|
||||||
@ -807,6 +821,8 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
const char** aThreadNameFilters, uint32_t aFilterCount)
|
const char** aThreadNameFilters, uint32_t aFilterCount)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
LOG("BEGIN profiler_start");
|
LOG("BEGIN profiler_start");
|
||||||
|
|
||||||
if (!stack_key_initialized)
|
if (!stack_key_initialized)
|
||||||
@ -824,17 +840,16 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
// Reset the current state if the profiler is running
|
// Reset the current state if the profiler is running
|
||||||
profiler_stop();
|
profiler_stop();
|
||||||
|
|
||||||
GeckoSampler* t;
|
gSampler =
|
||||||
t = new GeckoSampler(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
|
new GeckoSampler(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
|
||||||
aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY,
|
aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY,
|
||||||
aFeatures, aFeatureCount,
|
aFeatures, aFeatureCount,
|
||||||
aThreadNameFilters, aFilterCount);
|
aThreadNameFilters, aFilterCount);
|
||||||
|
|
||||||
tlsTicker.set(t);
|
gSampler->Start();
|
||||||
t->Start();
|
if (gSampler->ProfileJS() || gSampler->InPrivacyMode()) {
|
||||||
if (t->ProfileJS() || t->InPrivacyMode()) {
|
|
||||||
MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
|
MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
|
||||||
const std::vector<ThreadInfo*>& threads = t->GetRegisteredThreads();
|
const std::vector<ThreadInfo*>& threads = gSampler->GetRegisteredThreads();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < threads.size(); i++) {
|
for (uint32_t i = 0; i < threads.size(); i++) {
|
||||||
ThreadInfo* info = threads[i];
|
ThreadInfo* info = threads[i];
|
||||||
@ -846,17 +861,17 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
thread_profile->GetPseudoStack()->reinitializeOnResume();
|
thread_profile->GetPseudoStack()->reinitializeOnResume();
|
||||||
if (t->ProfileJS()) {
|
if (gSampler->ProfileJS()) {
|
||||||
thread_profile->GetPseudoStack()->enableJSSampling();
|
thread_profile->GetPseudoStack()->enableJSSampling();
|
||||||
}
|
}
|
||||||
if (t->InPrivacyMode()) {
|
if (gSampler->InPrivacyMode()) {
|
||||||
thread_profile->GetPseudoStack()->mPrivacyMode = true;
|
thread_profile->GetPseudoStack()->mPrivacyMode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
|
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
|
||||||
if (t->ProfileJava()) {
|
if (gSampler->ProfileJava()) {
|
||||||
int javaInterval = aInterval;
|
int javaInterval = aInterval;
|
||||||
// Java sampling doesn't accuratly keep up with 1ms sampling
|
// Java sampling doesn't accuratly keep up with 1ms sampling
|
||||||
if (javaInterval < 10) {
|
if (javaInterval < 10) {
|
||||||
@ -866,7 +881,7 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (t->AddMainThreadIO()) {
|
if (gSampler->AddMainThreadIO()) {
|
||||||
if (!sInterposeObserver) {
|
if (!sInterposeObserver) {
|
||||||
// Lazily create IO interposer observer
|
// Lazily create IO interposer observer
|
||||||
sInterposeObserver = new mozilla::ProfilerIOInterposeObserver();
|
sInterposeObserver = new mozilla::ProfilerIOInterposeObserver();
|
||||||
@ -876,10 +891,10 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sIsProfiling = true;
|
sIsProfiling = true;
|
||||||
sIsGPUProfiling = t->ProfileGPU();
|
sIsGPUProfiling = gSampler->ProfileGPU();
|
||||||
sIsLayersDump = t->LayersDump();
|
sIsLayersDump = gSampler->LayersDump();
|
||||||
sIsDisplayListDump = t->DisplayListDump();
|
sIsDisplayListDump = gSampler->DisplayListDump();
|
||||||
sIsRestyleProfiling = t->ProfileRestyle();
|
sIsRestyleProfiling = gSampler->ProfileRestyle();
|
||||||
|
|
||||||
if (Sampler::CanNotifyObservers()) {
|
if (Sampler::CanNotifyObservers()) {
|
||||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||||
@ -909,22 +924,23 @@ profiler_start(int aProfileEntries, double aInterval,
|
|||||||
void
|
void
|
||||||
profiler_stop()
|
profiler_stop()
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
LOG("BEGIN profiler_stop");
|
LOG("BEGIN profiler_stop");
|
||||||
|
|
||||||
if (!stack_key_initialized)
|
if (!stack_key_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GeckoSampler *t = tlsTicker.get();
|
if (!gSampler) {
|
||||||
if (!t) {
|
|
||||||
LOG("END profiler_stop-early");
|
LOG("END profiler_stop-early");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool disableJS = t->ProfileJS();
|
bool disableJS = gSampler->ProfileJS();
|
||||||
|
|
||||||
t->Stop();
|
gSampler->Stop();
|
||||||
delete t;
|
delete gSampler;
|
||||||
tlsTicker.set(nullptr);
|
gSampler = nullptr;
|
||||||
|
|
||||||
if (disableJS) {
|
if (disableJS) {
|
||||||
PseudoStack *stack = tlsPseudoStack.get();
|
PseudoStack *stack = tlsPseudoStack.get();
|
||||||
@ -1169,6 +1185,8 @@ profiler_in_privacy_mode()
|
|||||||
UniqueProfilerBacktrace
|
UniqueProfilerBacktrace
|
||||||
profiler_get_backtrace()
|
profiler_get_backtrace()
|
||||||
{
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (!stack_key_initialized)
|
if (!stack_key_initialized)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -1182,12 +1200,12 @@ profiler_get_backtrace()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeckoSampler* t = tlsTicker.get();
|
if (!gSampler) {
|
||||||
if (!t) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UniqueProfilerBacktrace(new ProfilerBacktrace(t->GetBacktrace()));
|
return UniqueProfilerBacktrace(
|
||||||
|
new ProfilerBacktrace(gSampler->GetBacktrace()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -312,7 +312,7 @@ class nsISupports;
|
|||||||
class ProfilerMarkerPayload;
|
class ProfilerMarkerPayload;
|
||||||
|
|
||||||
extern MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
|
extern MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
|
||||||
extern MOZ_THREAD_LOCAL(GeckoSampler *) tlsTicker;
|
extern GeckoSampler* gSampler;
|
||||||
extern bool stack_key_initialized;
|
extern bool stack_key_initialized;
|
||||||
|
|
||||||
#ifndef SAMPLE_FUNCTION_NAME
|
#ifndef SAMPLE_FUNCTION_NAME
|
||||||
|
Loading…
Reference in New Issue
Block a user