tools/profiler/TableTicker.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:e9678cc1a9ac
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #ifndef TableTicker_h
7 #define TableTicker_h
8
9 #include "platform.h"
10 #include "ProfileEntry.h"
11 #include "mozilla/Mutex.h"
12 #include "IntelPowerGadget.h"
13
14 static bool
15 hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) {
16 for(size_t i = 0; i < aFeatureCount; i++) {
17 if (strcmp(aFeatures[i], aFeature) == 0)
18 return true;
19 }
20 return false;
21 }
22
23 static bool
24 threadSelected(ThreadInfo* aInfo, char** aThreadNameFilters, uint32_t aFeatureCount) {
25 if (aFeatureCount == 0) {
26 return true;
27 }
28
29 for (uint32_t i = 0; i < aFeatureCount; ++i) {
30 const char* filterPrefix = aThreadNameFilters[i];
31 if (strncmp(aInfo->Name(), filterPrefix, strlen(filterPrefix)) == 0) {
32 return true;
33 }
34 }
35
36 return false;
37 }
38
39 extern TimeStamp sLastTracerEvent;
40 extern int sFrameNumber;
41 extern int sLastFrameNumber;
42 extern unsigned int sCurrentEventGeneration;
43 extern unsigned int sLastSampledEventGeneration;
44
45 class BreakpadSampler;
46
47 class TableTicker: public Sampler {
48 public:
49 TableTicker(double aInterval, int aEntrySize,
50 const char** aFeatures, uint32_t aFeatureCount,
51 const char** aThreadNameFilters, uint32_t aFilterCount)
52 : Sampler(aInterval, true, aEntrySize)
53 , mPrimaryThreadProfile(nullptr)
54 , mSaveRequested(false)
55 , mUnwinderThread(false)
56 , mFilterCount(aFilterCount)
57 #if defined(XP_WIN)
58 , mIntelPowerGadget(nullptr)
59 #endif
60 {
61 mUseStackWalk = hasFeature(aFeatures, aFeatureCount, "stackwalk");
62
63 //XXX: It's probably worth splitting the jank profiler out from the regular profiler at some point
64 mJankOnly = hasFeature(aFeatures, aFeatureCount, "jank");
65 mProfileJS = hasFeature(aFeatures, aFeatureCount, "js");
66 mProfileJava = hasFeature(aFeatures, aFeatureCount, "java");
67 mProfilePower = hasFeature(aFeatures, aFeatureCount, "power");
68 mProfileThreads = hasFeature(aFeatures, aFeatureCount, "threads");
69 mUnwinderThread = hasFeature(aFeatures, aFeatureCount, "unwinder") || sps_version2();
70 mAddLeafAddresses = hasFeature(aFeatures, aFeatureCount, "leaf");
71 mPrivacyMode = hasFeature(aFeatures, aFeatureCount, "privacy");
72 mAddMainThreadIO = hasFeature(aFeatures, aFeatureCount, "mainthreadio");
73
74 #if defined(XP_WIN)
75 if (mProfilePower) {
76 mIntelPowerGadget = new IntelPowerGadget();
77 mProfilePower = mIntelPowerGadget->Init();
78 }
79 #endif
80
81 // Deep copy aThreadNameFilters
82 mThreadNameFilters = new char*[aFilterCount];
83 for (uint32_t i = 0; i < aFilterCount; ++i) {
84 mThreadNameFilters[i] = strdup(aThreadNameFilters[i]);
85 }
86
87 sStartTime = TimeStamp::Now();
88
89 {
90 mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
91
92 // Create ThreadProfile for each registered thread
93 for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
94 ThreadInfo* info = sRegisteredThreads->at(i);
95
96 RegisterThread(info);
97 }
98
99 SetActiveSampler(this);
100 }
101 }
102
103 ~TableTicker() {
104 if (IsActive())
105 Stop();
106
107 SetActiveSampler(nullptr);
108
109 // Destroy ThreadProfile for all threads
110 {
111 mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
112
113 for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
114 ThreadInfo* info = sRegisteredThreads->at(i);
115 ThreadProfile* profile = info->Profile();
116 if (profile) {
117 delete profile;
118 info->SetProfile(nullptr);
119 }
120 }
121 }
122 #if defined(XP_WIN)
123 delete mIntelPowerGadget;
124 #endif
125 }
126
127 void RegisterThread(ThreadInfo* aInfo) {
128 if (!aInfo->IsMainThread() && !mProfileThreads) {
129 return;
130 }
131
132 if (!threadSelected(aInfo, mThreadNameFilters, mFilterCount)) {
133 return;
134 }
135
136 ThreadProfile* profile = new ThreadProfile(aInfo->Name(),
137 EntrySize(),
138 aInfo->Stack(),
139 aInfo->ThreadId(),
140 aInfo->GetPlatformData(),
141 aInfo->IsMainThread(),
142 aInfo->StackTop());
143 aInfo->SetProfile(profile);
144 }
145
146 // Called within a signal. This function must be reentrant
147 virtual void Tick(TickSample* sample);
148
149 // Immediately captures the calling thread's call stack and returns it.
150 virtual SyncProfile* GetBacktrace();
151
152 // Called within a signal. This function must be reentrant
153 virtual void RequestSave()
154 {
155 mSaveRequested = true;
156 }
157
158 virtual void HandleSaveRequest();
159
160 ThreadProfile* GetPrimaryThreadProfile()
161 {
162 if (!mPrimaryThreadProfile) {
163 mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
164
165 for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
166 ThreadInfo* info = sRegisteredThreads->at(i);
167 if (info->IsMainThread()) {
168 mPrimaryThreadProfile = info->Profile();
169 break;
170 }
171 }
172 }
173
174 return mPrimaryThreadProfile;
175 }
176
177 void ToStreamAsJSON(std::ostream& stream);
178 virtual JSObject *ToJSObject(JSContext *aCx);
179 void StreamMetaJSCustomObject(JSStreamWriter& b);
180 bool HasUnwinderThread() const { return mUnwinderThread; }
181 bool ProfileJS() const { return mProfileJS; }
182 bool ProfileJava() const { return mProfileJava; }
183 bool ProfilePower() const { return mProfilePower; }
184 bool ProfileThreads() const { return mProfileThreads; }
185 bool InPrivacyMode() const { return mPrivacyMode; }
186 bool AddMainThreadIO() const { return mAddMainThreadIO; }
187
188 protected:
189 // Called within a signal. This function must be reentrant
190 virtual void UnwinderTick(TickSample* sample);
191
192 // Called within a signal. This function must be reentrant
193 virtual void InplaceTick(TickSample* sample);
194
195 // Not implemented on platforms which do not support backtracing
196 void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample);
197
198 void StreamJSObject(JSStreamWriter& b);
199
200 // This represent the application's main thread (SAMPLER_INIT)
201 ThreadProfile* mPrimaryThreadProfile;
202 bool mSaveRequested;
203 bool mAddLeafAddresses;
204 bool mUseStackWalk;
205 bool mJankOnly;
206 bool mProfileJS;
207 bool mProfileThreads;
208 bool mUnwinderThread;
209 bool mProfileJava;
210 bool mProfilePower;
211
212 // Keep the thread filter to check against new thread that
213 // are started while profiling
214 char** mThreadNameFilters;
215 uint32_t mFilterCount;
216 bool mPrivacyMode;
217 bool mAddMainThreadIO;
218 #if defined(XP_WIN)
219 IntelPowerGadget* mIntelPowerGadget;
220 #endif
221 };
222
223 #endif
224

mercurial