void mozilla_sampler_get_profiler_start_params(int* aEntrySize, double* aInterval, mozilla::Vector<const char*>* aFilters, mozilla::Vector<const char*>* aFeatures) { if (NS_WARN_IF(!aEntrySize) || NS_WARN_IF(!aInterval) || NS_WARN_IF(!aFilters) || NS_WARN_IF(!aFeatures)) { return; } GeckoSampler *t = tlsTicker.get(); if (NS_WARN_IF(!t)) { return; } *aEntrySize = t->EntrySize(); *aInterval = t->interval(); const ThreadNameFilterList& threadNameFilterList = t->ThreadNameFilters(); MOZ_ALWAYS_TRUE(aFilters->resize(threadNameFilterList.length())); for (uint32_t i = 0; i < threadNameFilterList.length(); ++i) { (*aFilters)[i] = threadNameFilterList[i].c_str(); } const FeatureList& featureList = t->Features(); MOZ_ALWAYS_TRUE(aFeatures->resize(featureList.length())); for (size_t i = 0; i < featureList.length(); ++i) { (*aFeatures)[i] = featureList[i].c_str(); } }
JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, double aSinceTime) { GeckoSampler *t = tlsTicker.get(); if (!t) { return nullptr; } return t->ToJSObject(aCx, aSinceTime); }
mozilla::UniquePtr<char[]> mozilla_sampler_get_profile(double aSinceTime) { GeckoSampler *t = tlsTicker.get(); if (!t) { return nullptr; } return t->ToJSON(aSinceTime); }
void mozilla_sampler_get_profile_data_async(double aSinceTime, mozilla::dom::Promise* aPromise) { GeckoSampler *t = tlsTicker.get(); if (NS_WARN_IF(!t)) { return; } t->ToJSObjectAsync(aSinceTime, aPromise); }
void PseudoStack::flushSamplerOnJSShutdown() { #ifndef SPS_STANDALONE MOZ_ASSERT(mRuntime); GeckoSampler* t = tlsTicker.get(); if (t) { t->FlushOnJSShutdown(mRuntime); } #endif }
void mozilla_sampler_save() { GeckoSampler *t = tlsTicker.get(); if (!t) { return; } t->RequestSave(); // We're on the main thread already so we don't // have to wait to handle the save request. t->HandleSaveRequest(); }
void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration) { *aCurrentPosition = 0; *aTotalSize = 0; *aGeneration = 0; if (!stack_key_initialized) return; GeckoSampler *t = tlsTicker.get(); if (!t) return; t->GetBufferInfo(aCurrentPosition, aTotalSize, aGeneration); }
void mozilla_sampler_stop() { LOG("BEGIN mozilla_sampler_stop"); if (!stack_key_initialized) return; GeckoSampler *t = tlsTicker.get(); if (!t) { LOG("END mozilla_sampler_stop-early"); return; } bool disableJS = t->ProfileJS(); t->Stop(); delete t; tlsTicker.set(nullptr); #ifndef SPS_STANDALONE if (disableJS) { PseudoStack *stack = tlsPseudoStack.get(); ASSERT(stack != nullptr); stack->disableJSSampling(); } mozilla::IOInterposer::Unregister(mozilla::IOInterposeObserver::OpAll, sInterposeObserver); sInterposeObserver = nullptr; #endif sIsProfiling = false; #ifndef SPS_STANDALONE sIsGPUProfiling = false; sIsLayersDump = false; sIsDisplayListDump = false; sIsRestyleProfiling = false; if (Sampler::CanNotifyObservers()) { nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) os->NotifyObservers(nullptr, "profiler-stopped", nullptr); } #endif LOG("END mozilla_sampler_stop"); }
void mozilla_sampler_save_profile_to_file(const char* aFilename) { GeckoSampler *t = tlsTicker.get(); if (!t) { return; } std::ofstream stream; stream.open(aFilename); if (stream.is_open()) { t->ToStreamAsJSON(stream); stream.close(); LOGF("Saved to %s", aFilename); } else { LOG("Fail to open profile log file."); } }
void mozilla_sampler_get_gatherer(nsISupports** aRetVal) { if (!aRetVal) { return; } if (NS_WARN_IF(!profiler_is_active())) { *aRetVal = nullptr; return; } GeckoSampler *t = tlsTicker.get(); if (NS_WARN_IF(!t)) { *aRetVal = nullptr; return; } t->GetGatherer(aRetVal); }
void mozilla_sampler_shutdown() { sInitCount--; if (sInitCount > 0) return; // Save the profile on shutdown if requested. GeckoSampler *t = tlsTicker.get(); if (t) { const char *val = getenv("MOZ_PROFILER_SHUTDOWN"); if (val) { std::ofstream stream; stream.open(val); if (stream.is_open()) { t->ToStreamAsJSON(stream); stream.close(); } } } profiler_stop(); #ifndef SPS_STANDALONE set_stderr_callback(nullptr); #endif Sampler::Shutdown(); #ifdef SPS_STANDALONE mozilla::TimeStamp::Shutdown(); #endif PseudoStack *stack = tlsPseudoStack.get(); stack->deref(); tlsPseudoStack.set(nullptr); #ifdef MOZ_TASK_TRACER mozilla::tasktracer::ShutdownTaskTracer(); #endif }
ProfilerBacktrace* mozilla_sampler_get_backtrace() { if (!stack_key_initialized) return nullptr; // Don't capture a stack if we're not profiling if (!profiler_is_active()) { return nullptr; } // Don't capture a stack if we don't want to include personal information if (profiler_in_privacy_mode()) { return nullptr; } GeckoSampler* t = tlsTicker.get(); if (!t) { return nullptr; } return new ProfilerBacktrace(t->GetBacktrace()); }
// Values are only honored on the first start void mozilla_sampler_start(int aProfileEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, const char** aThreadNameFilters, uint32_t aFilterCount) { LOG("BEGIN mozilla_sampler_start"); if (!stack_key_initialized) profiler_init(nullptr); /* If the sampling interval was set using env vars, use that in preference to anything else. */ if (sUnwindInterval > 0) aInterval = sUnwindInterval; /* If the entry count was set using env vars, use that, too: */ if (sProfileEntries > 0) aProfileEntries = sProfileEntries; // Reset the current state if the profiler is running profiler_stop(); GeckoSampler* t; t = new GeckoSampler(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL, aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY, aFeatures, aFeatureCount, aThreadNameFilters, aFilterCount); tlsTicker.set(t); t->Start(); if (t->ProfileJS() || t->InPrivacyMode()) { ::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex); std::vector<ThreadInfo*> threads = t->GetRegisteredThreads(); for (uint32_t i = 0; i < threads.size(); i++) { ThreadInfo* info = threads[i]; if (info->IsPendingDelete()) { continue; } ThreadProfile* thread_profile = info->Profile(); if (!thread_profile) { continue; } thread_profile->GetPseudoStack()->reinitializeOnResume(); #ifndef SPS_STANDALONE if (t->ProfileJS()) { thread_profile->GetPseudoStack()->enableJSSampling(); } if (t->InPrivacyMode()) { thread_profile->GetPseudoStack()->mPrivacyMode = true; } #endif } } #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK) if (t->ProfileJava()) { int javaInterval = aInterval; // Java sampling doesn't accuratly keep up with 1ms sampling if (javaInterval < 10) { aInterval = 10; } mozilla::widget::GeckoJavaSampler::StartJavaProfiling(javaInterval, 1000); } #endif #ifndef SPS_STANDALONE if (t->AddMainThreadIO()) { if (!sInterposeObserver) { // Lazily create IO interposer observer sInterposeObserver = new mozilla::ProfilerIOInterposeObserver(); } mozilla::IOInterposer::Register(mozilla::IOInterposeObserver::OpAll, sInterposeObserver); } #endif sIsProfiling = true; #ifndef SPS_STANDALONE sIsGPUProfiling = t->ProfileGPU(); sIsLayersDump = t->LayersDump(); sIsDisplayListDump = t->DisplayListDump(); sIsRestyleProfiling = t->ProfileRestyle(); if (Sampler::CanNotifyObservers()) { nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { nsTArray<nsCString> featuresArray; nsTArray<nsCString> threadNameFiltersArray; for (size_t i = 0; i < aFeatureCount; ++i) { featuresArray.AppendElement(aFeatures[i]); } for (size_t i = 0; i < aFilterCount; ++i) { threadNameFiltersArray.AppendElement(aThreadNameFilters[i]); } nsCOMPtr<nsIProfilerStartParams> params = new nsProfilerStartParams(aProfileEntries, aInterval, featuresArray, threadNameFiltersArray); os->NotifyObservers(params, "profiler-started", nullptr); } } #endif LOG("END mozilla_sampler_start"); }