Line data Source code
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 0 : 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 0 : class nsGroupHolder {
77 : public:
78 0 : nsGroupHolder()
79 0 : : mGroup(nullptr)
80 0 : , 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 JSCompartment 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 0 : struct WindowIdToGroup: public nsUint64HashKey,
211 : public nsGroupHolder {
212 0 : explicit WindowIdToGroup(const uint64_t* key)
213 0 : : nsUint64HashKey(key)
214 0 : {}
215 : };
216 : nsTHashtable<WindowIdToGroup> mWindowIdToGroup;
217 :
218 : /**
219 : * Set of all performance groups.
220 : */
221 0 : struct Groups: public nsPtrHashKey<nsPerformanceGroup> {
222 0 : explicit Groups(const nsPerformanceGroup* key)
223 0 : : 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 0 : 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 0 : nsPerformanceGroupDetails(const nsAString& aName,
530 : const nsAString& aGroupId,
531 : const uint64_t aWindowId,
532 : const uint64_t aProcessId,
533 : const bool aIsSystem)
534 0 : : mName(aName)
535 : , mGroupId(aGroupId)
536 : , mWindowId(aWindowId)
537 : , mProcessId(aProcessId)
538 0 : , 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 : }
622 0 : static inline const nsPerformanceGroup* Get(const js::PerformanceGroup* self) {
623 0 : return static_cast<const nsPerformanceGroup*>(self);
624 : }
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
|