1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // APIs that control the lifetime of the profiler: Initialization, start, pause,
8 // resume, stop, and shutdown.
9 
10 #ifndef ProfilerControl_h
11 #define ProfilerControl_h
12 
13 // Everything in here is also safe to include unconditionally, and only defines
14 // empty macros if MOZ_GECKO_PROFILER is unset.
15 // If your file only uses particular APIs (e.g., only markers), please consider
16 // including only the needed headers instead of this one, to reduce compilation
17 // dependencies.
18 
19 enum class IsFastShutdown {
20   No,
21   Yes,
22 };
23 
24 #ifndef MOZ_GECKO_PROFILER
25 
26 // This file can be #included unconditionally. However, everything within this
27 // file must be guarded by a #ifdef MOZ_GECKO_PROFILER, *except* for the
28 // following macros and functions, which encapsulate the most common operations
29 // and thus avoid the need for many #ifdefs.
30 
31 #  define AUTO_PROFILER_INIT ::profiler_init_main_thread_id()
32 #  define AUTO_PROFILER_INIT2
33 
34 // Function stubs for when MOZ_GECKO_PROFILER is not defined.
35 
profiler_init(void * stackTop)36 static inline void profiler_init(void* stackTop) {}
37 
38 static inline void profiler_shutdown(
39     IsFastShutdown aIsFastShutdown = IsFastShutdown::No) {}
40 
41 #else  // !MOZ_GECKO_PROFILER
42 
43 #  include "mozilla/Attributes.h"
44 #  include "mozilla/Maybe.h"
45 #  include "mozilla/MozPromise.h"
46 #  include "mozilla/PowerOfTwo.h"
47 #  include "mozilla/Vector.h"
48 
49 // Macros used by the AUTO_PROFILER_* macros below.
50 #  define PROFILERCTRL_RAII_PASTE(id, line) id##line
51 #  define PROFILERCTRL_RAII_EXPAND(id, line) PROFILERCTRL_RAII_PASTE(id, line)
52 #  define PROFILERCTRL_RAII PROFILERCTRL_RAII_EXPAND(raiiObject, __LINE__)
53 
54 //---------------------------------------------------------------------------
55 // Start and stop the profiler
56 //---------------------------------------------------------------------------
57 
58 static constexpr mozilla::PowerOfTwo32 PROFILER_DEFAULT_ENTRIES =
59 #  if !defined(GP_PLAT_arm_android)
60     mozilla::MakePowerOfTwo32<8 * 1024 * 1024>();  // 8M entries = 64MB
61 #  else
62     mozilla::MakePowerOfTwo32<2 * 1024 * 1024>();  // 2M entries = 16MB
63 #  endif
64 
65 // Startup profiling usually need to capture more data, especially on slow
66 // systems.
67 // Note: Keep in sync with GeckoThread.maybeStartGeckoProfiler:
68 // https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
69 static constexpr mozilla::PowerOfTwo32 PROFILER_DEFAULT_STARTUP_ENTRIES =
70 #  if !defined(GP_PLAT_arm_android)
71     mozilla::MakePowerOfTwo32<64 * 1024 * 1024>();  // 64M entries = 512MB
72 #  else
73     mozilla::MakePowerOfTwo32<8 * 1024 * 1024>();  // 8M entries = 64MB
74 #  endif
75 
76 #  define PROFILER_DEFAULT_DURATION 20 /* seconds, for tests only */
77 // Note: Keep in sync with GeckoThread.maybeStartGeckoProfiler:
78 // https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
79 #  define PROFILER_DEFAULT_INTERVAL 1  /* millisecond */
80 #  define PROFILER_MAX_INTERVAL 5000   /* milliseconds */
81 #  define PROFILER_DEFAULT_ACTIVE_TAB_ID 0
82 
83 // Initialize the profiler. If MOZ_PROFILER_STARTUP is set the profiler will
84 // also be started. This call must happen before any other profiler calls
85 // (except profiler_start(), which will call profiler_init() if it hasn't
86 // already run).
87 void profiler_init(void* stackTop);
88 void profiler_init_threadmanager();
89 
90 // Call this as early as possible
91 #  define AUTO_PROFILER_INIT mozilla::AutoProfilerInit PROFILERCTRL_RAII
92 // Call this after the nsThreadManager is Init()ed
93 #  define AUTO_PROFILER_INIT2 mozilla::AutoProfilerInit2 PROFILERCTRL_RAII
94 
95 // Clean up the profiler module, stopping it if required. This function may
96 // also save a shutdown profile if requested. No profiler calls should happen
97 // after this point and all profiling stack labels should have been popped.
98 void profiler_shutdown(IsFastShutdown aIsFastShutdown = IsFastShutdown::No);
99 
100 // Start the profiler -- initializing it first if necessary -- with the
101 // selected options. Stops and restarts the profiler if it is already active.
102 // After starting the profiler is "active". The samples will be recorded in a
103 // circular buffer.
104 //   "aCapacity" is the maximum number of 8-bytes entries in the profiler's
105 //               circular buffer.
106 //   "aInterval" the sampling interval, measured in millseconds.
107 //   "aFeatures" is the feature set. Features unsupported by this
108 //               platform/configuration are ignored.
109 //   "aFilters" is the list of thread filters. Threads that do not match any
110 //              of the filters are not profiled. A filter matches a thread if
111 //              (a) the thread name contains the filter as a case-insensitive
112 //                  substring, or
113 //              (b) the filter is of the form "pid:<n>" where n is the process
114 //                  id of the process that the thread is running in.
115 //   "aActiveTabID" BrowserId of the active browser screen's active tab.
116 //               It's being used to determine the profiled tab. It's "0" if
117 //               we failed to get the ID.
118 //   "aDuration" is the duration of entries in the profiler's circular buffer.
119 // Returns as soon as this process' profiler has started, the returned promise
120 // gets resolved when profilers in sub-processes (if any) have started.
121 RefPtr<mozilla::GenericPromise> profiler_start(
122     mozilla::PowerOfTwo32 aCapacity, double aInterval, uint32_t aFeatures,
123     const char** aFilters, uint32_t aFilterCount, uint64_t aActiveTabID,
124     const mozilla::Maybe<double>& aDuration = mozilla::Nothing());
125 
126 // Stop the profiler and discard the profile without saving it. A no-op if the
127 // profiler is inactive. After stopping the profiler is "inactive".
128 // Returns as soon as this process' profiler has stopped, the returned promise
129 // gets resolved when profilers in sub-processes (if any) have stopped.
130 RefPtr<mozilla::GenericPromise> profiler_stop();
131 
132 // If the profiler is inactive, start it. If it's already active, restart it if
133 // the requested settings differ from the current settings. Both the check and
134 // the state change are performed while the profiler state is locked.
135 // The only difference to profiler_start is that the current buffer contents are
136 // not discarded if the profiler is already running with the requested settings.
137 void profiler_ensure_started(
138     mozilla::PowerOfTwo32 aCapacity, double aInterval, uint32_t aFeatures,
139     const char** aFilters, uint32_t aFilterCount, uint64_t aActiveTabID,
140     const mozilla::Maybe<double>& aDuration = mozilla::Nothing());
141 
142 //---------------------------------------------------------------------------
143 // Control the profiler
144 //---------------------------------------------------------------------------
145 
146 // Pause and resume the profiler. No-ops if the profiler is inactive. While
147 // paused the profile will not take any samples and will not record any data
148 // into its buffers. The profiler remains fully initialized in this state.
149 // Timeline markers will still be stored. This feature will keep JavaScript
150 // profiling enabled, thus allowing toggling the profiler without invalidating
151 // the JIT.
152 // Returns as soon as this process' profiler has paused/resumed, the returned
153 // promise gets resolved when profilers in sub-processes (if any) have
154 // paused/resumed.
155 RefPtr<mozilla::GenericPromise> profiler_pause();
156 RefPtr<mozilla::GenericPromise> profiler_resume();
157 
158 // Only pause and resume the periodic sampling loop, including stack sampling,
159 // counters, and profiling overheads.
160 // Returns as soon as this process' profiler has paused/resumed sampling, the
161 // returned promise gets resolved when profilers in sub-processes (if any) have
162 // paused/resumed sampling.
163 RefPtr<mozilla::GenericPromise> profiler_pause_sampling();
164 RefPtr<mozilla::GenericPromise> profiler_resume_sampling();
165 
166 //---------------------------------------------------------------------------
167 // Get information from the profiler
168 //---------------------------------------------------------------------------
169 
170 // Get the params used to start the profiler. Returns 0 and an empty vector
171 // (via outparams) if the profile is inactive. It's possible that the features
172 // returned may be slightly different to those requested due to required
173 // adjustments.
174 void profiler_get_start_params(
175     int* aEntrySize, mozilla::Maybe<double>* aDuration, double* aInterval,
176     uint32_t* aFeatures,
177     mozilla::Vector<const char*, 0, mozilla::MallocAllocPolicy>* aFilters,
178     uint64_t* aActiveTabID);
179 
180 //---------------------------------------------------------------------------
181 // RAII classes
182 //---------------------------------------------------------------------------
183 
184 namespace mozilla {
185 
186 class MOZ_RAII AutoProfilerInit {
187  public:
AutoProfilerInit()188   explicit AutoProfilerInit() { profiler_init(this); }
189 
~AutoProfilerInit()190   ~AutoProfilerInit() { profiler_shutdown(); }
191 
192  private:
193 };
194 
195 class MOZ_RAII AutoProfilerInit2 {
196  public:
AutoProfilerInit2()197   explicit AutoProfilerInit2() { profiler_init_threadmanager(); }
198 
199  private:
200 };
201 
202 }  // namespace mozilla
203 
204 #endif  // !MOZ_GECKO_PROFILER
205 
206 #endif  // ProfilerControl_h
207