/src/mozilla-central/toolkit/components/perfmonitoring/nsPerformanceStats.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; 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 nsPerformanceStats_h |
7 | | #define nsPerformanceStats_h |
8 | | |
9 | | #include "jsapi.h" |
10 | | |
11 | | #include "nsHashKeys.h" |
12 | | #include "nsTHashtable.h" |
13 | | |
14 | | #include "nsIObserver.h" |
15 | | #include "nsPIDOMWindow.h" |
16 | | |
17 | | #include "nsIPerformanceStats.h" |
18 | | |
19 | | class nsPerformanceGroup; |
20 | | class nsPerformanceGroupDetails; |
21 | | |
22 | | typedef mozilla::Vector<RefPtr<nsPerformanceGroup>, 8> GroupVector; |
23 | | |
24 | | /** |
25 | | * A data structure for registering observers interested in |
26 | | * performance alerts. |
27 | | * |
28 | | * Each performance group owns a single instance of this class. |
29 | | * Additionally, the service owns instances designed to observe the |
30 | | * performance alerts in all webpages. |
31 | | */ |
32 | | class nsPerformanceObservationTarget final: public nsIPerformanceObservable { |
33 | | public: |
34 | | NS_DECL_ISUPPORTS |
35 | | NS_DECL_NSIPERFORMANCEOBSERVABLE |
36 | | |
37 | | /** |
38 | | * `true` if this target has at least once performance observer |
39 | | * registered, `false` otherwise. |
40 | | */ |
41 | | bool HasObservers() const; |
42 | | |
43 | | /** |
44 | | * Notify all the observers that jank has happened. |
45 | | */ |
46 | | void NotifyJankObservers(nsIPerformanceGroupDetails* source, nsIPerformanceAlert* gravity); |
47 | | |
48 | | /** |
49 | | * Set the details on the group being observed. |
50 | | */ |
51 | | void SetTarget(nsPerformanceGroupDetails* details); |
52 | | |
53 | | private: |
54 | 0 | ~nsPerformanceObservationTarget() {} |
55 | | |
56 | | // The observers for this target. We hold them as a vector, despite |
57 | | // the linear removal cost, as we expect that the typical number of |
58 | | // observers will be lower than 3, and that (un)registrations will |
59 | | // be fairly infrequent. |
60 | | mozilla::Vector<nsCOMPtr<nsIPerformanceObserver>> mObservers; |
61 | | |
62 | | // Details on the group being observed. May be `nullptr`. |
63 | | RefPtr<nsPerformanceGroupDetails> mDetails; |
64 | | }; |
65 | | |
66 | | /** |
67 | | * The base class for entries of maps from window id to |
68 | | * performance group. |
69 | | * |
70 | | * Performance observers may be registered before their group is |
71 | | * created (e.g., one may register an observer for a webpage before all |
72 | | * its iframes are loaded). This class serves to hold the observation |
73 | | * target until the performance group may be created, and then to |
74 | | * associate the observation target and the performance group. |
75 | | */ |
76 | | class nsGroupHolder { |
77 | | public: |
78 | | nsGroupHolder() |
79 | | : mGroup(nullptr) |
80 | | , mPendingObservationTarget(nullptr) |
81 | 0 | { } |
82 | | |
83 | | /** |
84 | | * Get the observation target, creating it if necessary. |
85 | | */ |
86 | | nsPerformanceObservationTarget* ObservationTarget(); |
87 | | |
88 | | /** |
89 | | * Get the group, if it has been created. |
90 | | * |
91 | | * May return `null` if the group hasn't been created yet. |
92 | | */ |
93 | | class nsPerformanceGroup* GetGroup(); |
94 | | |
95 | | /** |
96 | | * Set the group. |
97 | | * |
98 | | * Once this method has been called, calling |
99 | | * `this->ObservationTarget()` and `group->ObservationTarget()` is equivalent. |
100 | | * |
101 | | * Must only be called once. |
102 | | */ |
103 | | void SetGroup(class nsPerformanceGroup*); |
104 | | private: |
105 | | // The group. Initially `nullptr`, until we have called `SetGroup`. |
106 | | class nsPerformanceGroup* mGroup; |
107 | | |
108 | | // The observation target. Instantiated by the first call to |
109 | | // `ObservationTarget()`. |
110 | | RefPtr<nsPerformanceObservationTarget> mPendingObservationTarget; |
111 | | }; |
112 | | |
113 | | /** |
114 | | * An implementation of the nsIPerformanceStatsService. |
115 | | * |
116 | | * Note that this implementation is not thread-safe. |
117 | | */ |
118 | | class nsPerformanceStatsService final : public nsIPerformanceStatsService, |
119 | | public nsIObserver |
120 | | { |
121 | | public: |
122 | | NS_DECL_ISUPPORTS |
123 | | NS_DECL_NSIPERFORMANCESTATSSERVICE |
124 | | NS_DECL_NSIOBSERVER |
125 | | |
126 | | nsPerformanceStatsService(); |
127 | | nsresult Init(); |
128 | | |
129 | | private: |
130 | | nsresult InitInternal(); |
131 | | void Dispose(); |
132 | | ~nsPerformanceStatsService(); |
133 | | |
134 | | protected: |
135 | | friend nsPerformanceGroup; |
136 | | |
137 | | /** |
138 | | * `false` until `Init()` and after `Dispose()`, `true` inbetween. |
139 | | */ |
140 | | bool mIsAvailable; |
141 | | |
142 | | /** |
143 | | * `true` once we have called `Dispose()`. |
144 | | */ |
145 | | bool mDisposed; |
146 | | |
147 | | /** |
148 | | * A unique identifier for the process. |
149 | | * |
150 | | * Process HANDLE under Windows, pid under Unix. |
151 | | */ |
152 | | const uint64_t mProcessId; |
153 | | |
154 | | /** |
155 | | * Generate unique identifiers. |
156 | | */ |
157 | | uint64_t GetNextId(); |
158 | | uint64_t mUIdCounter; |
159 | | |
160 | | |
161 | | |
162 | | /** |
163 | | * Extract a snapshot of performance statistics from a performance group. |
164 | | */ |
165 | | static nsIPerformanceStats* GetStatsForGroup(const js::PerformanceGroup* group); |
166 | | static nsIPerformanceStats* GetStatsForGroup(const nsPerformanceGroup* group); |
167 | | |
168 | | |
169 | | |
170 | | /** |
171 | | * Get the performance groups associated to a given JS compartment. |
172 | | * |
173 | | * A compartment is typically associated to the following groups: |
174 | | * - the top group, shared by the entire process; |
175 | | * - the window group, if the code is executed in a window, shared |
176 | | * by all compartments for that window (typically, all frames); |
177 | | * - the compartment's own group. |
178 | | * |
179 | | * Pre-condition: the VM must have entered the JS compartment. |
180 | | * |
181 | | * The caller is expected to cache the results of this method, as |
182 | | * calling it more than once may not return the same instances of |
183 | | * performance groups. |
184 | | */ |
185 | | bool GetPerformanceGroups(JSContext* cx, js::PerformanceGroupVector&); |
186 | | static bool GetPerformanceGroupsCallback(JSContext* cx, js::PerformanceGroupVector&, void* closure); |
187 | | |
188 | | |
189 | | |
190 | | /********************************************************** |
191 | | * |
192 | | * Sets of all performance groups, indexed by several keys. |
193 | | * |
194 | | * These sets do not keep the performance groups alive. Rather, a |
195 | | * performance group is inserted in the relevant sets upon |
196 | | * construction and removed from the sets upon destruction or when |
197 | | * we Dispose() of the service. |
198 | | * |
199 | | * A `nsPerformanceGroup` is typically kept alive (as a |
200 | | * `js::PerformanceGroup`) by the JS::Compartment to which it is |
201 | | * associated. It may also temporarily be kept alive by the JS |
202 | | * stack, in particular in case of nested event loops. |
203 | | */ |
204 | | |
205 | | /** |
206 | | * Set of performance groups associated to windows, indexed by outer |
207 | | * window id. Each item is shared by all the compartments that |
208 | | * belong to the window. |
209 | | */ |
210 | | struct WindowIdToGroup: public nsUint64HashKey, |
211 | | public nsGroupHolder { |
212 | | explicit WindowIdToGroup(const uint64_t* key) |
213 | | : nsUint64HashKey(key) |
214 | 0 | {} |
215 | | }; |
216 | | nsTHashtable<WindowIdToGroup> mWindowIdToGroup; |
217 | | |
218 | | /** |
219 | | * Set of all performance groups. |
220 | | */ |
221 | | struct Groups: public nsPtrHashKey<nsPerformanceGroup> { |
222 | | explicit Groups(const nsPerformanceGroup* key) |
223 | | : nsPtrHashKey<nsPerformanceGroup>(key) |
224 | 0 | {} |
225 | | }; |
226 | | nsTHashtable<Groups> mGroups; |
227 | | |
228 | | /** |
229 | | * The performance group representing the runtime itself. All |
230 | | * compartments are associated to this group. |
231 | | */ |
232 | | RefPtr<nsPerformanceGroup> mTopGroup; |
233 | | |
234 | | /********************************************************** |
235 | | * |
236 | | * Measuring and recording the CPU use of the system. |
237 | | * |
238 | | */ |
239 | | |
240 | | /** |
241 | | * Get the OS-reported time spent in userland/systemland, in |
242 | | * microseconds. On most platforms, this data is per-thread, |
243 | | * but on some platforms we need to fall back to per-process. |
244 | | * |
245 | | * Data is not guaranteed to be monotonic. |
246 | | */ |
247 | | nsresult GetResources(uint64_t* userTime, uint64_t* systemTime) const; |
248 | | |
249 | | /** |
250 | | * Amount of user/system CPU time used by the thread (or process, |
251 | | * for platforms that don't support per-thread measure) since start. |
252 | | * Updated by `StopwatchStart` at most once per event. |
253 | | * |
254 | | * Unit: microseconds. |
255 | | */ |
256 | | uint64_t mUserTimeStart; |
257 | | uint64_t mSystemTimeStart; |
258 | | |
259 | | bool mIsHandlingUserInput; |
260 | | |
261 | | /** |
262 | | * The number of user inputs since the start of the process. Used to |
263 | | * determine whether the current iteration has triggered a |
264 | | * (JS-implemented) user input. |
265 | | */ |
266 | | uint64_t mUserInputCount; |
267 | | |
268 | | /********************************************************** |
269 | | * |
270 | | * Callbacks triggered by the JS VM when execution of JavaScript |
271 | | * code starts/completes. |
272 | | * |
273 | | * As measures of user CPU time/system CPU time have low resolution |
274 | | * (and are somewhat slow), we measure both only during the calls to |
275 | | * `StopwatchStart`/`StopwatchCommit` and we make the assumption |
276 | | * that each group's user/system CPU time is proportional to the |
277 | | * number of clock cycles spent executing code in the group between |
278 | | * `StopwatchStart`/`StopwatchCommit`. |
279 | | * |
280 | | * The results may be skewed by the thread being rescheduled to a |
281 | | * different CPU during the measure, but we expect that on average, |
282 | | * the skew will have limited effects, and will generally tend to |
283 | | * make already-slow executions appear slower. |
284 | | */ |
285 | | |
286 | | /** |
287 | | * Execution of JavaScript code has started. This may happen several |
288 | | * times in succession if the JavaScript code contains nested event |
289 | | * loops, in which case only the innermost call will receive |
290 | | * `StopwatchCommitCallback`. |
291 | | * |
292 | | * @param iteration The number of times we have started executing |
293 | | * JavaScript code. |
294 | | */ |
295 | | static bool StopwatchStartCallback(uint64_t iteration, void* closure); |
296 | | bool StopwatchStart(uint64_t iteration); |
297 | | |
298 | | /** |
299 | | * Execution of JavaScript code has reached completion (including |
300 | | * enqueued microtasks). In cse of tested event loops, any ongoing |
301 | | * measurement on outer loops is silently cancelled without any call |
302 | | * to this method. |
303 | | * |
304 | | * @param iteration The number of times we have started executing |
305 | | * JavaScript code. |
306 | | * @param recentGroups The groups that have seen activity during this |
307 | | * event. |
308 | | */ |
309 | | static bool StopwatchCommitCallback(uint64_t iteration, |
310 | | js::PerformanceGroupVector& recentGroups, |
311 | | void* closure); |
312 | | bool StopwatchCommit(uint64_t iteration, js::PerformanceGroupVector& recentGroups); |
313 | | |
314 | | /** |
315 | | * The number of times we have started executing JavaScript code. |
316 | | */ |
317 | | uint64_t mIteration; |
318 | | |
319 | | /** |
320 | | * Commit performance measures of a single group. |
321 | | * |
322 | | * Data is transfered from `group->recent*` to `group->data`. |
323 | | * |
324 | | * |
325 | | * @param iteration The current iteration. |
326 | | * @param userTime The total user CPU time for this thread (or |
327 | | * process, if per-thread data is not available) between the |
328 | | * calls to `StopwatchStart` and `StopwatchCommit`. |
329 | | * @param systemTime The total system CPU time for this thread (or |
330 | | * process, if per-thread data is not available) between the |
331 | | * calls to `StopwatchStart` and `StopwatchCommit`. |
332 | | * @param cycles The total number of cycles for this thread |
333 | | * between the calls to `StopwatchStart` and `StopwatchCommit`. |
334 | | * @param isJankVisible If `true`, expect that the user will notice |
335 | | * any slowdown. |
336 | | * @param group The group containing the data to commit. |
337 | | */ |
338 | | void CommitGroup(uint64_t iteration, |
339 | | uint64_t userTime, uint64_t systemTime, uint64_t cycles, |
340 | | bool isJankVisible, |
341 | | nsPerformanceGroup* group); |
342 | | |
343 | | |
344 | | |
345 | | |
346 | | /********************************************************** |
347 | | * |
348 | | * To check whether our algorithm makes sense, we keep count of the |
349 | | * number of times the process has been rescheduled to another CPU |
350 | | * while we were monitoring the performance of a group and we upload |
351 | | * this data through Telemetry. |
352 | | */ |
353 | | nsresult UpdateTelemetry(); |
354 | | |
355 | | uint64_t mProcessStayed; |
356 | | uint64_t mProcessMoved; |
357 | | uint32_t mProcessUpdateCounter; |
358 | | |
359 | | /********************************************************** |
360 | | * |
361 | | * Options controlling measurements. |
362 | | */ |
363 | | |
364 | | /** |
365 | | * Determine if we are measuring the performance of every individual |
366 | | * compartment (in particular, every individual module, frame, |
367 | | * sandbox). Note that this makes measurements noticeably slower. |
368 | | */ |
369 | | bool mIsMonitoringPerCompartment; |
370 | | |
371 | | |
372 | | /********************************************************** |
373 | | * |
374 | | * Determining whether jank is user-visible. |
375 | | */ |
376 | | |
377 | | /** |
378 | | * `true` if we believe that any slowdown can cause a noticeable |
379 | | * delay in handling user-input. |
380 | | * |
381 | | * In the current implementation, we return `true` if the latest |
382 | | * user input was less than MAX_DURATION_OF_INTERACTION_MS ago. This |
383 | | * includes all inputs (mouse, keyboard, other devices), with the |
384 | | * exception of mousemove. |
385 | | */ |
386 | | bool IsHandlingUserInput(); |
387 | | |
388 | | |
389 | | public: |
390 | | /********************************************************** |
391 | | * |
392 | | * Letting observers register themselves to watch for performance |
393 | | * alerts. |
394 | | * |
395 | | * To avoid saturating clients with alerts (or even creating loops |
396 | | * of alerts), each alert is buffered. At the end of each iteration |
397 | | * of the event loop, groups that have caused performance alerts |
398 | | * are registered in a set of pending alerts, and the collection |
399 | | * timer hasn't been started yet, it is started. Once the timer |
400 | | * firers, we gather all the pending alerts, empty the set and |
401 | | * dispatch to observers. |
402 | | */ |
403 | | |
404 | | /** |
405 | | * Clear the set of pending alerts and dispatch the pending alerts |
406 | | * to observers. |
407 | | */ |
408 | | void NotifyJankObservers(const mozilla::Vector<uint64_t>& previousJankLevels); |
409 | | |
410 | | private: |
411 | | /** |
412 | | * The set of groups for which we know that an alert should be |
413 | | * raised. This set is cleared once `mPendingAlertsCollector` |
414 | | * fires. |
415 | | * |
416 | | * Invariant: no group may appear twice in this vector. |
417 | | */ |
418 | | GroupVector mPendingAlerts; |
419 | | |
420 | | /** |
421 | | * A timer callback in charge of collecting the groups in |
422 | | * `mPendingAlerts` and triggering `NotifyJankObservers` to dispatch |
423 | | * performance alerts. |
424 | | */ |
425 | | RefPtr<class PendingAlertsCollector> mPendingAlertsCollector; |
426 | | |
427 | | |
428 | | /** |
429 | | * Observation targets that are not attached to a specific group. |
430 | | */ |
431 | | struct UniversalTargets { |
432 | | UniversalTargets(); |
433 | | /** |
434 | | * A target for observers interested in watching all windows. |
435 | | */ |
436 | | RefPtr<nsPerformanceObservationTarget> mWindows; |
437 | | }; |
438 | | UniversalTargets mUniversalTargets; |
439 | | |
440 | | /** |
441 | | * The threshold, in microseconds, above which a performance group is |
442 | | * considered "slow" and should raise performance alerts. |
443 | | */ |
444 | | uint64_t mJankAlertThreshold; |
445 | | |
446 | | /** |
447 | | * A buffering delay, in milliseconds, used by the service to |
448 | | * regroup performance alerts, before observers are actually |
449 | | * noticed. Higher delays let the system avoid redundant |
450 | | * notifications for the same group, and are generally better for |
451 | | * performance. |
452 | | */ |
453 | | uint32_t mJankAlertBufferingDelay; |
454 | | |
455 | | /** |
456 | | * The threshold above which jank, as reported by the refresh drivers, |
457 | | * is considered user-visible. |
458 | | * |
459 | | * A value of n means that any jank above 2^n ms will be considered |
460 | | * user visible. |
461 | | */ |
462 | | short mJankLevelVisibilityThreshold; |
463 | | |
464 | | /** |
465 | | * The number of microseconds during which we assume that a |
466 | | * user-interaction can keep the code jank-critical. Any user |
467 | | * interaction that lasts longer than this duration is expected to |
468 | | * either have already caused jank or have caused a nested event |
469 | | * loop. |
470 | | * |
471 | | * In either case, we consider that monitoring |
472 | | * jank-during-interaction after this duration is useless. |
473 | | */ |
474 | | uint64_t mMaxExpectedDurationOfInteractionUS; |
475 | | }; |
476 | | |
477 | | |
478 | | |
479 | | /** |
480 | | * Container for performance data. |
481 | | * |
482 | | * All values are monotonic. |
483 | | * |
484 | | * All values are updated after running to completion. |
485 | | */ |
486 | | struct PerformanceData { |
487 | | /** |
488 | | * Number of times we have spent at least 2^n consecutive |
489 | | * milliseconds executing code in this group. |
490 | | * durations[0] is increased whenever we spend at least 1 ms |
491 | | * executing code in this group |
492 | | * durations[1] whenever we spend 2ms+ |
493 | | * ... |
494 | | * durations[i] whenever we spend 2^ims+ |
495 | | */ |
496 | | uint64_t mDurations[10]; |
497 | | |
498 | | /** |
499 | | * Total amount of time spent executing code in this group, in |
500 | | * microseconds. |
501 | | */ |
502 | | uint64_t mTotalUserTime; |
503 | | uint64_t mTotalSystemTime; |
504 | | uint64_t mTotalCPOWTime; |
505 | | |
506 | | /** |
507 | | * Total number of times code execution entered this group, since |
508 | | * process launch. This may be greater than the number of times we |
509 | | * have entered the event loop. |
510 | | */ |
511 | | uint64_t mTicks; |
512 | | |
513 | | PerformanceData(); |
514 | | PerformanceData(const PerformanceData& from) = default; |
515 | | PerformanceData& operator=(const PerformanceData& from) = default; |
516 | | }; |
517 | | |
518 | | |
519 | | |
520 | | /** |
521 | | * Identification information for an item that can hold performance |
522 | | * data. |
523 | | */ |
524 | | class nsPerformanceGroupDetails final: public nsIPerformanceGroupDetails { |
525 | | public: |
526 | | NS_DECL_ISUPPORTS |
527 | | NS_DECL_NSIPERFORMANCEGROUPDETAILS |
528 | | |
529 | | nsPerformanceGroupDetails(const nsAString& aName, |
530 | | const nsAString& aGroupId, |
531 | | const uint64_t aWindowId, |
532 | | const uint64_t aProcessId, |
533 | | const bool aIsSystem) |
534 | | : mName(aName) |
535 | | , mGroupId(aGroupId) |
536 | | , mWindowId(aWindowId) |
537 | | , mProcessId(aProcessId) |
538 | | , mIsSystem(aIsSystem) |
539 | 0 | { } |
540 | | public: |
541 | | const nsAString& Name() const; |
542 | | const nsAString& GroupId() const; |
543 | | uint64_t WindowId() const; |
544 | | uint64_t ProcessId() const; |
545 | | bool IsWindow() const; |
546 | | bool IsSystem() const; |
547 | | bool IsContentProcess() const; |
548 | | private: |
549 | 0 | ~nsPerformanceGroupDetails() {} |
550 | | |
551 | | const nsString mName; |
552 | | const nsString mGroupId; |
553 | | const uint64_t mWindowId; |
554 | | const uint64_t mProcessId; |
555 | | const bool mIsSystem; |
556 | | }; |
557 | | |
558 | | /** |
559 | | * The kind of compartments represented by this group. |
560 | | */ |
561 | | enum class PerformanceGroupScope { |
562 | | /** |
563 | | * This group represents the entire runtime (i.e. the thread). |
564 | | */ |
565 | | RUNTIME, |
566 | | |
567 | | /** |
568 | | * This group represents all the compartments executed in a window. |
569 | | */ |
570 | | WINDOW, |
571 | | |
572 | | /** |
573 | | * This group represents a single compartment. |
574 | | */ |
575 | | COMPARTMENT, |
576 | | }; |
577 | | |
578 | | /** |
579 | | * A concrete implementation of `js::PerformanceGroup`, also holding |
580 | | * performance data. Instances may represent individual compartments, |
581 | | * windows or the entire runtime. |
582 | | * |
583 | | * This class is intended to be the sole implementation of |
584 | | * `js::PerformanceGroup`. |
585 | | */ |
586 | | class nsPerformanceGroup final: public js::PerformanceGroup { |
587 | | public: |
588 | | |
589 | | // Ideally, we would define the enum class in nsPerformanceGroup, |
590 | | // but this seems to choke some versions of gcc. |
591 | | typedef PerformanceGroupScope GroupScope; |
592 | | |
593 | | /** |
594 | | * Construct a performance group. |
595 | | * |
596 | | * @param cx The container context. Used to generate a unique identifier. |
597 | | * @param service The performance service. Used during destruction to |
598 | | * cleanup the hash tables. |
599 | | * @param name A name for the group, designed mostly for debugging purposes, |
600 | | * so it should be at least somewhat human-readable. |
601 | | * @param windowId The identifier of the window. Should be 0 when the |
602 | | * group is not part of a window. |
603 | | * @param processId A unique identifier for the process. |
604 | | * @param isSystem `true` if the code of the group is executed with |
605 | | * system credentials, `false` otherwise. |
606 | | * @param scope the scope of this group. |
607 | | */ |
608 | | static nsPerformanceGroup* |
609 | | Make(nsPerformanceStatsService* service, |
610 | | const nsAString& name, |
611 | | uint64_t windowId, |
612 | | uint64_t processId, |
613 | | bool isSystem, |
614 | | GroupScope scope); |
615 | | |
616 | | /** |
617 | | * Utility: type-safer conversion from js::PerformanceGroup to nsPerformanceGroup. |
618 | | */ |
619 | 0 | static inline nsPerformanceGroup* Get(js::PerformanceGroup* self) { |
620 | 0 | return static_cast<nsPerformanceGroup*>(self); |
621 | 0 | } |
622 | 0 | static inline const nsPerformanceGroup* Get(const js::PerformanceGroup* self) { |
623 | 0 | return static_cast<const nsPerformanceGroup*>(self); |
624 | 0 | } |
625 | | |
626 | | /** |
627 | | * The performance data committed to this group. |
628 | | */ |
629 | | PerformanceData data; |
630 | | |
631 | | /** |
632 | | * The scope of this group. Used to determine whether the group |
633 | | * should be (de)activated. |
634 | | */ |
635 | | GroupScope Scope() const; |
636 | | |
637 | | /** |
638 | | * Identification details for this group. |
639 | | */ |
640 | | nsPerformanceGroupDetails* Details() const; |
641 | | |
642 | | /** |
643 | | * Cleanup any references. |
644 | | */ |
645 | | void Dispose(); |
646 | | |
647 | | /** |
648 | | * Set the observation target for this group. |
649 | | * |
650 | | * This method must be called exactly once, when the performance |
651 | | * group is attached to its `nsGroupHolder`. |
652 | | */ |
653 | | void SetObservationTarget(nsPerformanceObservationTarget*); |
654 | | |
655 | | |
656 | | /** |
657 | | * `true` if we have already noticed that a performance alert should |
658 | | * be raised for this group but we have not dispatched it yet, |
659 | | * `false` otherwise. |
660 | | */ |
661 | | bool HasPendingAlert() const; |
662 | | void SetHasPendingAlert(bool value); |
663 | | |
664 | | protected: |
665 | | nsPerformanceGroup(nsPerformanceStatsService* service, |
666 | | const nsAString& name, |
667 | | const nsAString& groupId, |
668 | | uint64_t windowId, |
669 | | uint64_t processId, |
670 | | bool isSystem, |
671 | | GroupScope scope); |
672 | | |
673 | | |
674 | | /** |
675 | | * Virtual implementation of `delete`, to make sure that objects are |
676 | | * destoyed with an implementation of `delete` compatible with the |
677 | | * implementation of `new` used to allocate them. |
678 | | * |
679 | | * Called by SpiderMonkey. |
680 | | */ |
681 | 0 | virtual void Delete() override { |
682 | 0 | delete this; |
683 | 0 | } |
684 | | ~nsPerformanceGroup(); |
685 | | |
686 | | private: |
687 | | /** |
688 | | * Identification details for this group. |
689 | | */ |
690 | | RefPtr<nsPerformanceGroupDetails> mDetails; |
691 | | |
692 | | /** |
693 | | * The stats service. Used to perform cleanup during destruction. |
694 | | */ |
695 | | RefPtr<nsPerformanceStatsService> mService; |
696 | | |
697 | | /** |
698 | | * The scope of this group. Used to determine whether the group |
699 | | * should be (de)activated. |
700 | | */ |
701 | | const GroupScope mScope; |
702 | | |
703 | | // Observing performance alerts. |
704 | | |
705 | | public: |
706 | | /** |
707 | | * The observation target, used to register observers. |
708 | | */ |
709 | | nsPerformanceObservationTarget* ObservationTarget() const; |
710 | | |
711 | | /** |
712 | | * Record a jank duration. |
713 | | * |
714 | | * Update the highest recent jank if necessary. |
715 | | */ |
716 | | void RecordJank(uint64_t jank); |
717 | | uint64_t HighestRecentJank(); |
718 | | |
719 | | /** |
720 | | * Record a CPOW duration. |
721 | | * |
722 | | * Update the highest recent CPOW if necessary. |
723 | | */ |
724 | | void RecordCPOW(uint64_t cpow); |
725 | | uint64_t HighestRecentCPOW(); |
726 | | |
727 | | /** |
728 | | * Record that this group has recently been involved in handling |
729 | | * user input. Note that heuristics are involved here, so the |
730 | | * result is not 100% accurate. |
731 | | */ |
732 | | void RecordUserInput(); |
733 | | bool HasRecentUserInput(); |
734 | | |
735 | | /** |
736 | | * Reset recent values (recent highest CPOW and jank, involvement in |
737 | | * user input). |
738 | | */ |
739 | | void ResetRecent(); |
740 | | private: |
741 | | /** |
742 | | * The target used by observers to register for watching slow |
743 | | * performance alerts caused by this group. |
744 | | * |
745 | | * May be nullptr for groups that cannot be watched (the top group). |
746 | | */ |
747 | | RefPtr<class nsPerformanceObservationTarget> mObservationTarget; |
748 | | |
749 | | /** |
750 | | * The highest jank encountered since jank observers for this group |
751 | | * were last called, in microseconds. |
752 | | */ |
753 | | uint64_t mHighestJank; |
754 | | |
755 | | /** |
756 | | * The highest CPOW encountered since jank observers for this group |
757 | | * were last called, in microseconds. |
758 | | */ |
759 | | uint64_t mHighestCPOW; |
760 | | |
761 | | /** |
762 | | * `true` if this group has been involved in handling user input, |
763 | | * `false` otherwise. |
764 | | * |
765 | | * Note that we use heuristics to determine whether a group is |
766 | | * involved in handling user input, so this value is not 100% |
767 | | * accurate. |
768 | | */ |
769 | | bool mHasRecentUserInput; |
770 | | |
771 | | /** |
772 | | * `true` if this group has caused a performance alert and this alert |
773 | | * hasn't been dispatched yet. |
774 | | * |
775 | | * We use this as part of the buffering of performance alerts. If |
776 | | * the group generates several alerts several times during the |
777 | | * buffering delay, we only wish to add the group once to the list |
778 | | * of alerts. |
779 | | */ |
780 | | bool mHasPendingAlert; |
781 | | }; |
782 | | |
783 | | #endif |