diff options
Diffstat (limited to 'tools/profiler/core/GeckoSampler.h')
-rw-r--r-- | tools/profiler/core/GeckoSampler.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/tools/profiler/core/GeckoSampler.h b/tools/profiler/core/GeckoSampler.h new file mode 100644 index 000000000..da1fdfe43 --- /dev/null +++ b/tools/profiler/core/GeckoSampler.h @@ -0,0 +1,181 @@ +/* -*- 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 GeckoSampler_h +#define GeckoSampler_h + +#include "platform.h" +#include "ProfileEntry.h" +#include "mozilla/Vector.h" +#include "ThreadProfile.h" +#include "ThreadInfo.h" +#ifndef SPS_STANDALONE +#include "IntelPowerGadget.h" +#endif +#ifdef MOZ_TASK_TRACER +#include "GeckoTaskTracer.h" +#endif + +#include <algorithm> + +namespace mozilla { +class ProfileGatherer; +} // namespace mozilla + +typedef mozilla::Vector<std::string> ThreadNameFilterList; +typedef mozilla::Vector<std::string> FeatureList; + +static bool +threadSelected(ThreadInfo* aInfo, const ThreadNameFilterList &aThreadNameFilters) { + if (aThreadNameFilters.empty()) { + return true; + } + + std::string name = aInfo->Name(); + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + + for (uint32_t i = 0; i < aThreadNameFilters.length(); ++i) { + std::string filter = aThreadNameFilters[i]; + std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower); + + // Crude, non UTF-8 compatible, case insensitive substring search + if (name.find(filter) != std::string::npos) { + return true; + } + } + + return false; +} + +extern mozilla::TimeStamp sLastTracerEvent; +extern int sFrameNumber; +extern int sLastFrameNumber; + +class GeckoSampler: public Sampler { + public: + GeckoSampler(double aInterval, int aEntrySize, + const char** aFeatures, uint32_t aFeatureCount, + const char** aThreadNameFilters, uint32_t aFilterCount); + ~GeckoSampler(); + + void RegisterThread(ThreadInfo* aInfo) { + if (!aInfo->IsMainThread() && !mProfileThreads) { + return; + } + + if (!threadSelected(aInfo, mThreadNameFilters)) { + return; + } + + ThreadProfile* profile = new ThreadProfile(aInfo, mBuffer); + aInfo->SetProfile(profile); + } + + // Called within a signal. This function must be reentrant + virtual void Tick(TickSample* sample) override; + + // Immediately captures the calling thread's call stack and returns it. + virtual SyncProfile* GetBacktrace() override; + + // Called within a signal. This function must be reentrant + virtual void RequestSave() override + { + mSaveRequested = true; +#ifdef MOZ_TASK_TRACER + if (mTaskTracer) { + mozilla::tasktracer::StopLogging(); + } +#endif + } + + virtual void HandleSaveRequest() override; + virtual void DeleteExpiredMarkers() override; + + ThreadProfile* GetPrimaryThreadProfile() + { + if (!mPrimaryThreadProfile) { + ::MutexAutoLock lock(*sRegisteredThreadsMutex); + + for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) { + ThreadInfo* info = sRegisteredThreads->at(i); + if (info->IsMainThread() && !info->IsPendingDelete()) { + mPrimaryThreadProfile = info->Profile(); + break; + } + } + } + + return mPrimaryThreadProfile; + } + + void ToStreamAsJSON(std::ostream& stream, double aSinceTime = 0); +#ifndef SPS_STANDALONE + virtual JSObject *ToJSObject(JSContext *aCx, double aSinceTime = 0); + void GetGatherer(nsISupports** aRetVal); +#endif + mozilla::UniquePtr<char[]> ToJSON(double aSinceTime = 0); + virtual void ToJSObjectAsync(double aSinceTime = 0, mozilla::dom::Promise* aPromise = 0); + void StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter); + void StreamTaskTracer(SpliceableJSONWriter& aWriter); + void FlushOnJSShutdown(JSContext* aContext); + bool ProfileJS() const { return mProfileJS; } + bool ProfileJava() const { return mProfileJava; } + bool ProfileGPU() const { return mProfileGPU; } + bool ProfilePower() const { return mProfilePower; } + bool ProfileThreads() const override { return mProfileThreads; } + bool InPrivacyMode() const { return mPrivacyMode; } + bool AddMainThreadIO() const { return mAddMainThreadIO; } + bool ProfileMemory() const { return mProfileMemory; } + bool TaskTracer() const { return mTaskTracer; } + bool LayersDump() const { return mLayersDump; } + bool DisplayListDump() const { return mDisplayListDump; } + bool ProfileRestyle() const { return mProfileRestyle; } + const ThreadNameFilterList& ThreadNameFilters() { return mThreadNameFilters; } + const FeatureList& Features() { return mFeatures; } + + void GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration); + +protected: + // Called within a signal. This function must be reentrant + virtual void InplaceTick(TickSample* sample); + + // Not implemented on platforms which do not support backtracing + void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample); + + void StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime); + + // This represent the application's main thread (SAMPLER_INIT) + ThreadProfile* mPrimaryThreadProfile; + RefPtr<ProfileBuffer> mBuffer; + bool mSaveRequested; + bool mAddLeafAddresses; + bool mUseStackWalk; + bool mProfileJS; + bool mProfileGPU; + bool mProfileThreads; + bool mProfileJava; + bool mProfilePower; + bool mLayersDump; + bool mDisplayListDump; + bool mProfileRestyle; + + // Keep the thread filter to check against new thread that + // are started while profiling + ThreadNameFilterList mThreadNameFilters; + FeatureList mFeatures; + bool mPrivacyMode; + bool mAddMainThreadIO; + bool mProfileMemory; + bool mTaskTracer; +#if defined(XP_WIN) + IntelPowerGadget* mIntelPowerGadget; +#endif + +private: + RefPtr<mozilla::ProfileGatherer> mGatherer; +}; + +#endif + |