[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-debug / BaseProfiler.h
blob8f9257c5177bfcc9258b57bf8c76812cda0d64b9
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/. */
7 // The Gecko Profiler is an always-on profiler that takes fast and low overhead
8 // samples of the program execution using only userspace functionality for
9 // portability. The goal of this module is to provide performance data in a
10 // generic cross-platform way without requiring custom tools or kernel support.
12 // Samples are collected to form a timeline with optional timeline event
13 // (markers) used for filtering. The samples include both native stacks and
14 // platform-independent "label stack" frames.
16 #ifndef BaseProfiler_h
17 #define BaseProfiler_h
19 // This file is safe to include unconditionally, and only defines
20 // empty macros if MOZ_GECKO_PROFILER is not set.
22 // These headers are also safe to include unconditionally, with empty macros if
23 // MOZ_GECKO_PROFILER is not set.
24 // If your file only uses particular APIs (e.g., only markers), please consider
25 // including only the needed headers instead of this one, to reduce compilation
26 // dependencies.
27 #include "mozilla/BaseProfilerCounts.h"
28 #include "mozilla/BaseProfilerLabels.h"
29 #include "mozilla/BaseProfilerMarkers.h"
30 #include "mozilla/BaseProfilerState.h"
32 #ifndef MOZ_GECKO_PROFILER
34 # include "mozilla/UniquePtr.h"
36 // This file can be #included unconditionally. However, everything within this
37 // file must be guarded by a #ifdef MOZ_GECKO_PROFILER, *except* for the
38 // following macros and functions, which encapsulate the most common operations
39 // and thus avoid the need for many #ifdefs.
41 # define AUTO_BASE_PROFILER_INIT
43 # define BASE_PROFILER_REGISTER_THREAD(name)
44 # define BASE_PROFILER_UNREGISTER_THREAD()
45 # define AUTO_BASE_PROFILER_REGISTER_THREAD(name)
47 # define AUTO_BASE_PROFILER_THREAD_SLEEP
48 # define AUTO_BASE_PROFILER_THREAD_WAKE
50 // Function stubs for when MOZ_GECKO_PROFILER is not defined.
52 namespace mozilla {
54 namespace baseprofiler {
55 // This won't be used, it's just there to allow the empty definition of
56 // `profiler_get_backtrace`.
57 struct ProfilerBacktrace {};
58 using UniqueProfilerBacktrace = UniquePtr<ProfilerBacktrace>;
60 // Get/Capture-backtrace functions can return nullptr or false, the result
61 // should be fed to another empty macro or stub anyway.
63 static inline UniqueProfilerBacktrace profiler_get_backtrace() {
64 return nullptr;
67 static inline bool profiler_capture_backtrace_into(
68 ProfileChunkedBuffer& aChunkedBuffer, StackCaptureOptions aCaptureOptions) {
69 return false;
72 static inline UniquePtr<ProfileChunkedBuffer> profiler_capture_backtrace() {
73 return nullptr;
75 } // namespace baseprofiler
76 } // namespace mozilla
78 #else // !MOZ_GECKO_PROFILER
80 # include "BaseProfilingStack.h"
82 # include "mozilla/Assertions.h"
83 # include "mozilla/Atomics.h"
84 # include "mozilla/Attributes.h"
85 # include "mozilla/Maybe.h"
86 # include "mozilla/PowerOfTwo.h"
87 # include "mozilla/TimeStamp.h"
88 # include "mozilla/UniquePtr.h"
90 # include <functional>
91 # include <stdint.h>
92 # include <string>
94 namespace mozilla {
96 class MallocAllocPolicy;
97 class ProfileChunkedBuffer;
98 enum class StackCaptureOptions;
99 template <class T, size_t MinInlineCapacity, class AllocPolicy>
100 class Vector;
102 namespace baseprofiler {
104 class ProfilerBacktrace;
105 class SpliceableJSONWriter;
107 //---------------------------------------------------------------------------
108 // Start and stop the profiler
109 //---------------------------------------------------------------------------
111 static constexpr PowerOfTwo32 BASE_PROFILER_DEFAULT_ENTRIES =
112 # if !defined(GP_PLAT_arm_android)
113 MakePowerOfTwo32<1024 * 1024>(); // 1M entries = 8MB
114 # else
115 MakePowerOfTwo32<128 * 1024>(); // 128k entries = 1MB
116 # endif
118 // Startup profiling usually need to capture more data, especially on slow
119 // systems.
120 static constexpr PowerOfTwo32 BASE_PROFILER_DEFAULT_STARTUP_ENTRIES =
121 # if !defined(GP_PLAT_arm_android)
122 MakePowerOfTwo32<4 * 1024 * 1024>(); // 4M entries = 32MB
123 # else
124 MakePowerOfTwo32<256 * 1024>(); // 256k entries = 2MB
125 # endif
127 # define BASE_PROFILER_DEFAULT_DURATION 20
128 # define BASE_PROFILER_DEFAULT_INTERVAL 1
130 // Initialize the profiler. If MOZ_PROFILER_STARTUP is set the profiler will
131 // also be started. This call must happen before any other profiler calls
132 // (except profiler_start(), which will call profiler_init() if it hasn't
133 // already run).
134 MFBT_API void profiler_init(void* stackTop);
136 # define AUTO_BASE_PROFILER_INIT \
137 ::mozilla::baseprofiler::AutoProfilerInit BASE_PROFILER_RAII
139 // Clean up the profiler module, stopping it if required. This function may
140 // also save a shutdown profile if requested. No profiler calls should happen
141 // after this point and all profiling stack labels should have been popped.
142 MFBT_API void profiler_shutdown();
144 // Start the profiler -- initializing it first if necessary -- with the
145 // selected options. Stops and restarts the profiler if it is already active.
146 // After starting the profiler is "active". The samples will be recorded in a
147 // circular buffer.
148 // "aCapacity" is the maximum number of 8-byte entries in the profiler's
149 // circular buffer.
150 // "aInterval" the sampling interval, measured in millseconds.
151 // "aFeatures" is the feature set. Features unsupported by this
152 // platform/configuration are ignored.
153 // "aFilters" is the list of thread filters. Threads that do not match any
154 // of the filters are not profiled. A filter matches a thread if
155 // (a) the thread name contains the filter as a case-insensitive
156 // substring, or
157 // (b) the filter is of the form "pid:<n>" where n is the process
158 // id of the process that the thread is running in.
159 // "aDuration" is the duration of entries in the profiler's circular buffer.
160 MFBT_API void profiler_start(PowerOfTwo32 aCapacity, double aInterval,
161 uint32_t aFeatures, const char** aFilters,
162 uint32_t aFilterCount,
163 const Maybe<double>& aDuration = Nothing());
165 // Stop the profiler and discard the profile without saving it. A no-op if the
166 // profiler is inactive. After stopping the profiler is "inactive".
167 MFBT_API void profiler_stop();
169 // If the profiler is inactive, start it. If it's already active, restart it if
170 // the requested settings differ from the current settings. Both the check and
171 // the state change are performed while the profiler state is locked.
172 // The only difference to profiler_start is that the current buffer contents are
173 // not discarded if the profiler is already running with the requested settings.
174 MFBT_API void profiler_ensure_started(
175 PowerOfTwo32 aCapacity, double aInterval, uint32_t aFeatures,
176 const char** aFilters, uint32_t aFilterCount,
177 const Maybe<double>& aDuration = Nothing());
179 //---------------------------------------------------------------------------
180 // Control the profiler
181 //---------------------------------------------------------------------------
183 // Register/unregister threads with the profiler. Both functions operate the
184 // same whether the profiler is active or inactive.
185 # define BASE_PROFILER_REGISTER_THREAD(name) \
186 do { \
187 char stackTop; \
188 ::mozilla::baseprofiler::profiler_register_thread(name, &stackTop); \
189 } while (0)
190 # define BASE_PROFILER_UNREGISTER_THREAD() \
191 ::mozilla::baseprofiler::profiler_unregister_thread()
192 MFBT_API ProfilingStack* profiler_register_thread(const char* name,
193 void* guessStackTop);
194 MFBT_API void profiler_unregister_thread();
196 // Registers a DOM Window (the JS global `window`) with the profiler. Each
197 // Window _roughly_ corresponds to a single document loaded within a
198 // browsing context. Both the Window Id and Browser Id are recorded to allow
199 // correlating different Windows loaded within the same tab or frame element.
201 // We register pages for each navigations but we do not register
202 // history.pushState or history.replaceState since they correspond to the same
203 // Inner Window ID. When a browsing context is first loaded, the first url
204 // loaded in it will be about:blank. Because of that, this call keeps the first
205 // non-about:blank registration of window and discards the previous one.
207 // "aTabID" is the BrowserId of that document belongs to.
208 // That's used to determine the tab of that page.
209 // "aInnerWindowID" is the ID of the `window` global object of that
210 // document.
211 // "aUrl" is the URL of the page.
212 // "aEmbedderInnerWindowID" is the inner window id of embedder. It's used to
213 // determine sub documents of a page.
214 MFBT_API void profiler_register_page(uint64_t aTabD, uint64_t aInnerWindowID,
215 const std::string& aUrl,
216 uint64_t aEmbedderInnerWindowID);
217 // Unregister page with the profiler.
219 // Take a Inner Window ID and unregister the page entry that has the same ID.
220 MFBT_API void profiler_unregister_page(uint64_t aRegisteredInnerWindowID);
222 // Remove all registered and unregistered pages in the profiler.
223 void profiler_clear_all_pages();
225 class BaseProfilerCount;
226 MFBT_API void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
227 MFBT_API void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
229 // Register and unregister a thread within a scope.
230 # define AUTO_BASE_PROFILER_REGISTER_THREAD(name) \
231 ::mozilla::baseprofiler::AutoProfilerRegisterThread BASE_PROFILER_RAII(name)
233 // Pause and resume the profiler. No-ops if the profiler is inactive. While
234 // paused the profile will not take any samples and will not record any data
235 // into its buffers. The profiler remains fully initialized in this state.
236 // This feature will keep JavaScript profiling enabled, thus allowing toggling
237 // the profiler without invalidating the JIT.
238 MFBT_API void profiler_pause();
239 MFBT_API void profiler_resume();
241 // Only pause and resume the periodic sampling loop, including stack sampling,
242 // counters, and profiling overheads.
243 MFBT_API void profiler_pause_sampling();
244 MFBT_API void profiler_resume_sampling();
246 // These functions tell the profiler that a thread went to sleep so that we can
247 // avoid sampling it while it's sleeping. Calling profiler_thread_sleep()
248 // twice without an intervening profiler_thread_wake() is an error. All three
249 // functions operate the same whether the profiler is active or inactive.
250 MFBT_API void profiler_thread_sleep();
251 MFBT_API void profiler_thread_wake();
253 // Mark a thread as asleep/awake within a scope.
254 # define AUTO_BASE_PROFILER_THREAD_SLEEP \
255 ::mozilla::baseprofiler::AutoProfilerThreadSleep BASE_PROFILER_RAII
256 # define AUTO_BASE_PROFILER_THREAD_WAKE \
257 ::mozilla::baseprofiler::AutoProfilerThreadWake BASE_PROFILER_RAII
259 //---------------------------------------------------------------------------
260 // Get information from the profiler
261 //---------------------------------------------------------------------------
263 // Get the params used to start the profiler. Returns 0 and an empty vector
264 // (via outparams) if the profile is inactive. It's possible that the features
265 // returned may be slightly different to those requested due to required
266 // adjustments.
267 MFBT_API void profiler_get_start_params(
268 int* aEntrySize, Maybe<double>* aDuration, double* aInterval,
269 uint32_t* aFeatures, Vector<const char*, 0, MallocAllocPolicy>* aFilters);
271 // The number of milliseconds since the process started. Operates the same
272 // whether the profiler is active or inactive.
273 MFBT_API double profiler_time();
275 // An object of this class is passed to profiler_suspend_and_sample_thread().
276 // For each stack frame, one of the Collect methods will be called.
277 class ProfilerStackCollector {
278 public:
279 // Some collectors need to worry about possibly overwriting previous
280 // generations of data. If that's not an issue, this can return Nothing,
281 // which is the default behaviour.
282 virtual Maybe<uint64_t> SamplePositionInBuffer() { return Nothing(); }
283 virtual Maybe<uint64_t> BufferRangeStart() { return Nothing(); }
285 // This method will be called once if the thread being suspended is the main
286 // thread. Default behaviour is to do nothing.
287 virtual void SetIsMainThread() {}
289 // WARNING: The target thread is suspended when the Collect methods are
290 // called. Do not try to allocate or acquire any locks, or you could
291 // deadlock. The target thread will have resumed by the time this function
292 // returns.
294 virtual void CollectNativeLeafAddr(void* aAddr) = 0;
296 virtual void CollectProfilingStackFrame(
297 const ProfilingStackFrame& aFrame) = 0;
300 // This method suspends the thread identified by aThreadId, samples its
301 // profiling stack, JS stack, and (optionally) native stack, passing the
302 // collected frames into aCollector. aFeatures dictates which compiler features
303 // are used. |Leaf| is the only relevant one.
304 // Use `aThreadId`=0 to sample the current thread.
305 MFBT_API void profiler_suspend_and_sample_thread(
306 int aThreadId, uint32_t aFeatures, ProfilerStackCollector& aCollector,
307 bool aSampleNative = true);
309 struct ProfilerBacktraceDestructor {
310 MFBT_API void operator()(ProfilerBacktrace*);
313 using UniqueProfilerBacktrace =
314 UniquePtr<ProfilerBacktrace, ProfilerBacktraceDestructor>;
316 // Immediately capture the current thread's call stack, store it in the provided
317 // buffer (usually to avoid allocations if you can construct the buffer on the
318 // stack). Returns false if unsuccessful, if the profiler is inactive, or if
319 // aCaptureOptions is NoStack.
320 MFBT_API bool profiler_capture_backtrace_into(
321 ProfileChunkedBuffer& aChunkedBuffer, StackCaptureOptions aCaptureOptions);
323 // Immediately capture the current thread's call stack, and return it in a
324 // ProfileChunkedBuffer (usually for later use in MarkerStack::TakeBacktrace()).
325 // May be null if unsuccessful, or if the profiler is inactive.
326 MFBT_API UniquePtr<ProfileChunkedBuffer> profiler_capture_backtrace();
328 // Immediately capture the current thread's call stack, and return it in a
329 // ProfilerBacktrace (usually for later use in marker function that take a
330 // ProfilerBacktrace). May be null if unsuccessful, or if the profiler is
331 // inactive.
332 MFBT_API UniqueProfilerBacktrace profiler_get_backtrace();
334 struct ProfilerStats {
335 unsigned n = 0;
336 double sum = 0;
337 double min = std::numeric_limits<double>::max();
338 double max = 0;
339 void Count(double v) {
340 ++n;
341 sum += v;
342 if (v < min) {
343 min = v;
345 if (v > max) {
346 max = v;
351 struct ProfilerBufferInfo {
352 // Index of the oldest entry.
353 uint64_t mRangeStart;
354 // Index of the newest entry.
355 uint64_t mRangeEnd;
356 // Buffer capacity in number of 8-byte entries.
357 uint32_t mEntryCount;
358 // Sampling stats: Interval (us) between successive samplings.
359 ProfilerStats mIntervalsUs;
360 // Sampling stats: Total duration (us) of each sampling. (Split detail below.)
361 ProfilerStats mOverheadsUs;
362 // Sampling stats: Time (us) to acquire the lock before sampling.
363 ProfilerStats mLockingsUs;
364 // Sampling stats: Time (us) to discard expired data.
365 ProfilerStats mCleaningsUs;
366 // Sampling stats: Time (us) to collect counter data.
367 ProfilerStats mCountersUs;
368 // Sampling stats: Time (us) to sample thread stacks.
369 ProfilerStats mThreadsUs;
372 // Get information about the current buffer status.
373 // Returns Nothing() if the profiler is inactive.
375 // This information may be useful to a user-interface displaying the current
376 // status of the profiler, allowing the user to get a sense for how fast the
377 // buffer is being written to, and how much data is visible.
378 MFBT_API Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
380 } // namespace baseprofiler
381 } // namespace mozilla
383 namespace mozilla {
384 namespace baseprofiler {
386 //---------------------------------------------------------------------------
387 // Put profiling data into the profiler (markers)
388 //---------------------------------------------------------------------------
390 MFBT_API void profiler_add_js_marker(const char* aMarkerName,
391 const char* aMarkerText);
393 //---------------------------------------------------------------------------
394 // Output profiles
395 //---------------------------------------------------------------------------
397 // Set a user-friendly process name, used in JSON stream.
398 MFBT_API void profiler_set_process_name(const std::string& aProcessName,
399 const std::string* aETLDplus1);
401 // Get the profile encoded as a JSON string. A no-op (returning nullptr) if the
402 // profiler is inactive.
403 // If aIsShuttingDown is true, the current time is included as the process
404 // shutdown time in the JSON's "meta" object.
405 MFBT_API UniquePtr<char[]> profiler_get_profile(double aSinceTime = 0,
406 bool aIsShuttingDown = false,
407 bool aOnlyThreads = false);
409 // Write the profile for this process (excluding subprocesses) into aWriter.
410 // Returns false if the profiler is inactive.
411 MFBT_API bool profiler_stream_json_for_this_process(
412 SpliceableJSONWriter& aWriter, double aSinceTime = 0,
413 bool aIsShuttingDown = false, bool aOnlyThreads = false);
415 // Get the profile and write it into a file. A no-op if the profile is
416 // inactive.
417 MFBT_API void profiler_save_profile_to_file(const char* aFilename);
419 //---------------------------------------------------------------------------
420 // RAII classes
421 //---------------------------------------------------------------------------
423 class MOZ_RAII AutoProfilerInit {
424 public:
425 explicit AutoProfilerInit() { profiler_init(this); }
427 ~AutoProfilerInit() { profiler_shutdown(); }
429 private:
432 // Convenience class to register and unregister a thread with the profiler.
433 // Needs to be the first object on the stack of the thread.
434 class MOZ_RAII AutoProfilerRegisterThread final {
435 public:
436 explicit AutoProfilerRegisterThread(const char* aName) {
437 profiler_register_thread(aName, this);
440 ~AutoProfilerRegisterThread() { profiler_unregister_thread(); }
442 private:
443 AutoProfilerRegisterThread(const AutoProfilerRegisterThread&) = delete;
444 AutoProfilerRegisterThread& operator=(const AutoProfilerRegisterThread&) =
445 delete;
448 class MOZ_RAII AutoProfilerThreadSleep {
449 public:
450 explicit AutoProfilerThreadSleep() { profiler_thread_sleep(); }
452 ~AutoProfilerThreadSleep() { profiler_thread_wake(); }
454 private:
457 // Temporarily wake up the profiling of a thread while servicing events such as
458 // Asynchronous Procedure Calls (APCs).
459 class MOZ_RAII AutoProfilerThreadWake {
460 public:
461 explicit AutoProfilerThreadWake()
462 : mIssuedWake(profiler_thread_is_sleeping()) {
463 if (mIssuedWake) {
464 profiler_thread_wake();
468 ~AutoProfilerThreadWake() {
469 if (mIssuedWake) {
470 MOZ_ASSERT(!profiler_thread_is_sleeping());
471 profiler_thread_sleep();
475 private:
476 bool mIssuedWake;
479 // Get the MOZ_PROFILER_STARTUP* environment variables that should be
480 // supplied to a child process that is about to be launched, in order
481 // to make that child process start with the same profiler settings as
482 // in the current process. The given function is invoked once for
483 // each variable to be set.
484 MFBT_API void GetProfilerEnvVarsForChildProcess(
485 std::function<void(const char* key, const char* value)>&& aSetEnv);
487 } // namespace baseprofiler
488 } // namespace mozilla
490 #endif // !MOZ_GECKO_PROFILER
492 #endif // BaseProfiler_h