1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/TableTicker.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,224 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef TableTicker_h 1.10 +#define TableTicker_h 1.11 + 1.12 +#include "platform.h" 1.13 +#include "ProfileEntry.h" 1.14 +#include "mozilla/Mutex.h" 1.15 +#include "IntelPowerGadget.h" 1.16 + 1.17 +static bool 1.18 +hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) { 1.19 + for(size_t i = 0; i < aFeatureCount; i++) { 1.20 + if (strcmp(aFeatures[i], aFeature) == 0) 1.21 + return true; 1.22 + } 1.23 + return false; 1.24 +} 1.25 + 1.26 +static bool 1.27 +threadSelected(ThreadInfo* aInfo, char** aThreadNameFilters, uint32_t aFeatureCount) { 1.28 + if (aFeatureCount == 0) { 1.29 + return true; 1.30 + } 1.31 + 1.32 + for (uint32_t i = 0; i < aFeatureCount; ++i) { 1.33 + const char* filterPrefix = aThreadNameFilters[i]; 1.34 + if (strncmp(aInfo->Name(), filterPrefix, strlen(filterPrefix)) == 0) { 1.35 + return true; 1.36 + } 1.37 + } 1.38 + 1.39 + return false; 1.40 +} 1.41 + 1.42 +extern TimeStamp sLastTracerEvent; 1.43 +extern int sFrameNumber; 1.44 +extern int sLastFrameNumber; 1.45 +extern unsigned int sCurrentEventGeneration; 1.46 +extern unsigned int sLastSampledEventGeneration; 1.47 + 1.48 +class BreakpadSampler; 1.49 + 1.50 +class TableTicker: public Sampler { 1.51 + public: 1.52 + TableTicker(double aInterval, int aEntrySize, 1.53 + const char** aFeatures, uint32_t aFeatureCount, 1.54 + const char** aThreadNameFilters, uint32_t aFilterCount) 1.55 + : Sampler(aInterval, true, aEntrySize) 1.56 + , mPrimaryThreadProfile(nullptr) 1.57 + , mSaveRequested(false) 1.58 + , mUnwinderThread(false) 1.59 + , mFilterCount(aFilterCount) 1.60 +#if defined(XP_WIN) 1.61 + , mIntelPowerGadget(nullptr) 1.62 +#endif 1.63 + { 1.64 + mUseStackWalk = hasFeature(aFeatures, aFeatureCount, "stackwalk"); 1.65 + 1.66 + //XXX: It's probably worth splitting the jank profiler out from the regular profiler at some point 1.67 + mJankOnly = hasFeature(aFeatures, aFeatureCount, "jank"); 1.68 + mProfileJS = hasFeature(aFeatures, aFeatureCount, "js"); 1.69 + mProfileJava = hasFeature(aFeatures, aFeatureCount, "java"); 1.70 + mProfilePower = hasFeature(aFeatures, aFeatureCount, "power"); 1.71 + mProfileThreads = hasFeature(aFeatures, aFeatureCount, "threads"); 1.72 + mUnwinderThread = hasFeature(aFeatures, aFeatureCount, "unwinder") || sps_version2(); 1.73 + mAddLeafAddresses = hasFeature(aFeatures, aFeatureCount, "leaf"); 1.74 + mPrivacyMode = hasFeature(aFeatures, aFeatureCount, "privacy"); 1.75 + mAddMainThreadIO = hasFeature(aFeatures, aFeatureCount, "mainthreadio"); 1.76 + 1.77 +#if defined(XP_WIN) 1.78 + if (mProfilePower) { 1.79 + mIntelPowerGadget = new IntelPowerGadget(); 1.80 + mProfilePower = mIntelPowerGadget->Init(); 1.81 + } 1.82 +#endif 1.83 + 1.84 + // Deep copy aThreadNameFilters 1.85 + mThreadNameFilters = new char*[aFilterCount]; 1.86 + for (uint32_t i = 0; i < aFilterCount; ++i) { 1.87 + mThreadNameFilters[i] = strdup(aThreadNameFilters[i]); 1.88 + } 1.89 + 1.90 + sStartTime = TimeStamp::Now(); 1.91 + 1.92 + { 1.93 + mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex); 1.94 + 1.95 + // Create ThreadProfile for each registered thread 1.96 + for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) { 1.97 + ThreadInfo* info = sRegisteredThreads->at(i); 1.98 + 1.99 + RegisterThread(info); 1.100 + } 1.101 + 1.102 + SetActiveSampler(this); 1.103 + } 1.104 + } 1.105 + 1.106 + ~TableTicker() { 1.107 + if (IsActive()) 1.108 + Stop(); 1.109 + 1.110 + SetActiveSampler(nullptr); 1.111 + 1.112 + // Destroy ThreadProfile for all threads 1.113 + { 1.114 + mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex); 1.115 + 1.116 + for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) { 1.117 + ThreadInfo* info = sRegisteredThreads->at(i); 1.118 + ThreadProfile* profile = info->Profile(); 1.119 + if (profile) { 1.120 + delete profile; 1.121 + info->SetProfile(nullptr); 1.122 + } 1.123 + } 1.124 + } 1.125 +#if defined(XP_WIN) 1.126 + delete mIntelPowerGadget; 1.127 +#endif 1.128 + } 1.129 + 1.130 + void RegisterThread(ThreadInfo* aInfo) { 1.131 + if (!aInfo->IsMainThread() && !mProfileThreads) { 1.132 + return; 1.133 + } 1.134 + 1.135 + if (!threadSelected(aInfo, mThreadNameFilters, mFilterCount)) { 1.136 + return; 1.137 + } 1.138 + 1.139 + ThreadProfile* profile = new ThreadProfile(aInfo->Name(), 1.140 + EntrySize(), 1.141 + aInfo->Stack(), 1.142 + aInfo->ThreadId(), 1.143 + aInfo->GetPlatformData(), 1.144 + aInfo->IsMainThread(), 1.145 + aInfo->StackTop()); 1.146 + aInfo->SetProfile(profile); 1.147 + } 1.148 + 1.149 + // Called within a signal. This function must be reentrant 1.150 + virtual void Tick(TickSample* sample); 1.151 + 1.152 + // Immediately captures the calling thread's call stack and returns it. 1.153 + virtual SyncProfile* GetBacktrace(); 1.154 + 1.155 + // Called within a signal. This function must be reentrant 1.156 + virtual void RequestSave() 1.157 + { 1.158 + mSaveRequested = true; 1.159 + } 1.160 + 1.161 + virtual void HandleSaveRequest(); 1.162 + 1.163 + ThreadProfile* GetPrimaryThreadProfile() 1.164 + { 1.165 + if (!mPrimaryThreadProfile) { 1.166 + mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex); 1.167 + 1.168 + for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) { 1.169 + ThreadInfo* info = sRegisteredThreads->at(i); 1.170 + if (info->IsMainThread()) { 1.171 + mPrimaryThreadProfile = info->Profile(); 1.172 + break; 1.173 + } 1.174 + } 1.175 + } 1.176 + 1.177 + return mPrimaryThreadProfile; 1.178 + } 1.179 + 1.180 + void ToStreamAsJSON(std::ostream& stream); 1.181 + virtual JSObject *ToJSObject(JSContext *aCx); 1.182 + void StreamMetaJSCustomObject(JSStreamWriter& b); 1.183 + bool HasUnwinderThread() const { return mUnwinderThread; } 1.184 + bool ProfileJS() const { return mProfileJS; } 1.185 + bool ProfileJava() const { return mProfileJava; } 1.186 + bool ProfilePower() const { return mProfilePower; } 1.187 + bool ProfileThreads() const { return mProfileThreads; } 1.188 + bool InPrivacyMode() const { return mPrivacyMode; } 1.189 + bool AddMainThreadIO() const { return mAddMainThreadIO; } 1.190 + 1.191 +protected: 1.192 + // Called within a signal. This function must be reentrant 1.193 + virtual void UnwinderTick(TickSample* sample); 1.194 + 1.195 + // Called within a signal. This function must be reentrant 1.196 + virtual void InplaceTick(TickSample* sample); 1.197 + 1.198 + // Not implemented on platforms which do not support backtracing 1.199 + void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample); 1.200 + 1.201 + void StreamJSObject(JSStreamWriter& b); 1.202 + 1.203 + // This represent the application's main thread (SAMPLER_INIT) 1.204 + ThreadProfile* mPrimaryThreadProfile; 1.205 + bool mSaveRequested; 1.206 + bool mAddLeafAddresses; 1.207 + bool mUseStackWalk; 1.208 + bool mJankOnly; 1.209 + bool mProfileJS; 1.210 + bool mProfileThreads; 1.211 + bool mUnwinderThread; 1.212 + bool mProfileJava; 1.213 + bool mProfilePower; 1.214 + 1.215 + // Keep the thread filter to check against new thread that 1.216 + // are started while profiling 1.217 + char** mThreadNameFilters; 1.218 + uint32_t mFilterCount; 1.219 + bool mPrivacyMode; 1.220 + bool mAddMainThreadIO; 1.221 +#if defined(XP_WIN) 1.222 + IntelPowerGadget* mIntelPowerGadget; 1.223 +#endif 1.224 +}; 1.225 + 1.226 +#endif 1.227 +