michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* *************** SPS Sampler Information **************** michael@0: * michael@0: * SPS is an always on profiler that takes fast and low overheads samples michael@0: * of the program execution using only userspace functionity for portability. michael@0: * The goal of this module is to provide performance data in a generic michael@0: * cross platform way without requiring custom tools or kernel support. michael@0: * michael@0: * Non goals: Support features that are platform specific or replace michael@0: * platform specific profilers. michael@0: * michael@0: * Samples are collected to form a timeline with optional timeline event (markers) michael@0: * used for filtering. michael@0: * michael@0: * SPS collects samples in a platform independant way by using a speudo stack abstraction michael@0: * of the real program stack by using 'sample stack frames'. When a sample is collected michael@0: * all active sample stack frames and the program counter are recorded. michael@0: */ michael@0: michael@0: /* *************** SPS Sampler File Format **************** michael@0: * michael@0: * Simple new line seperated tag format: michael@0: * S -> BOF tags EOF michael@0: * tags -> tag tags michael@0: * tag -> CHAR - STRING michael@0: * michael@0: * Tags: michael@0: * 's' - Sample tag followed by the first stack frame followed by 0 or more 'c' tags. michael@0: * 'c' - Continue Sample tag gives remaining tag element. If a 'c' tag is seen without michael@0: * a preceding 's' tag it should be ignored. This is to support the behavior michael@0: * of circular buffers. michael@0: * If the 'stackwalk' feature is enabled this tag will have the format michael@0: * 'l-@' and will expect an external tool to translate michael@0: * the tag into something readable through a symbolication processing step. michael@0: * 'm' - Timeline marker. Zero or more may appear before a 's' tag. michael@0: * 'l' - Information about the program counter library and address. Post processing michael@0: * can include function and source line. If built with leaf data enabled michael@0: * this tag will describe the last 'c' tag. michael@0: * 'r' - Responsiveness tag following an 's' tag. Gives an indication on how well the michael@0: * application is responding to the event loop. Lower is better. michael@0: * 't' - Elapse time since recording started. michael@0: * michael@0: */ michael@0: michael@0: #ifndef SAMPLER_H michael@0: #define SAMPLER_H michael@0: michael@0: #include "mozilla/NullPtr.h" michael@0: #include "js/TypeDecls.h" michael@0: michael@0: namespace mozilla { michael@0: class TimeStamp; michael@0: } michael@0: michael@0: enum TracingMetadata { michael@0: TRACING_DEFAULT, michael@0: TRACING_INTERVAL_START, michael@0: TRACING_INTERVAL_END michael@0: }; michael@0: michael@0: #ifndef MOZ_ENABLE_PROFILER_SPS michael@0: michael@0: #include michael@0: michael@0: // Insert a RAII in this scope to active a pseudo label. Any samples collected michael@0: // in this scope will contain this annotation. For dynamic strings use michael@0: // PROFILER_LABEL_PRINTF. Arguments must be string literals. michael@0: #define PROFILER_LABEL(name_space, info) do {} while (0) michael@0: michael@0: // Format a dynamic string as a pseudo label. These labels will a considerable michael@0: // storage size in the circular buffer compared to regular labels. This function michael@0: // can be used to annotate custom information such as URL for the resource being michael@0: // decoded or the size of the paint. michael@0: #define PROFILER_LABEL_PRINTF(name_space, info, format, ...) do {} while (0) michael@0: michael@0: // Insert a marker in the profile timeline. This is useful to delimit something michael@0: // important happening such as the first paint. Unlike profiler_label that are michael@0: // only recorded if a sample is collected while it is active, marker will always michael@0: // be collected. michael@0: #define PROFILER_MARKER(info) do {} while (0) michael@0: #define PROFILER_MARKER_PAYLOAD(info, payload) do {} while (0) michael@0: michael@0: // Main thread specilization to avoid TLS lookup for performance critical use. michael@0: #define PROFILER_MAIN_THREAD_LABEL(name_space, info) do {} while (0) michael@0: #define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, format, ...) do {} while (0) michael@0: michael@0: static inline void profiler_tracing(const char* aCategory, const char* aInfo, michael@0: TracingMetadata metaData = TRACING_DEFAULT) {} michael@0: michael@0: // Initilize the profiler TLS, signal handlers on linux. If MOZ_PROFILER_STARTUP michael@0: // is set the profiler will be started. This call must happen before any other michael@0: // sampler calls. Particularly sampler_label/sampler_marker. michael@0: static inline void profiler_init(void* stackTop) {}; michael@0: michael@0: // Clean up the profiler module, stopping it if required. This function may michael@0: // also save a shutdown profile if requested. No profiler calls should happen michael@0: // after this point and all pseudo labels should have been popped. michael@0: static inline void profiler_shutdown() {}; michael@0: michael@0: // Start the profiler with the selected options. The samples will be michael@0: // recorded in a circular buffer. michael@0: // "aProfileEntries" is an abstract size indication of how big michael@0: // the profile's circular buffer should be. Multiply by 4 michael@0: // words to get the cost. michael@0: // "aInterval" the sampling interval. The profiler will do its michael@0: // best to sample at this interval. The profiler visualization michael@0: // should represent the actual sampling accuracy. michael@0: static inline void profiler_start(int aProfileEntries, double aInterval, michael@0: const char** aFeatures, uint32_t aFeatureCount, michael@0: const char** aThreadNameFilters, uint32_t aFilterCount) {} michael@0: michael@0: // Stop the profiler and discard the profile. Call 'profiler_save' before this michael@0: // to retrieve the profile. michael@0: static inline void profiler_stop() {} michael@0: michael@0: // These functions pause and resume the profiler. While paused the profile will not michael@0: // take any samples and will not record any data into its buffers. The profiler michael@0: // remains fully initialized in this state. Timeline markers will still be stored. michael@0: // This feature will keep javascript profiling enabled, thus allowing toggling the michael@0: // profiler without invalidating the JIT. michael@0: static inline bool profiler_is_paused() { return false; } michael@0: static inline void profiler_pause() {} michael@0: static inline void profiler_resume() {} michael@0: michael@0: class ProfilerBacktrace; michael@0: michael@0: // Immediately capture the current thread's call stack and return it michael@0: static inline ProfilerBacktrace* profiler_get_backtrace() { return nullptr; } michael@0: michael@0: // Free a ProfilerBacktrace returned by profiler_get_backtrace() michael@0: static inline void profiler_free_backtrace(ProfilerBacktrace* aBacktrace) {} michael@0: michael@0: static inline bool profiler_is_active() { return false; } michael@0: michael@0: // Internal-only. Used by the event tracer. michael@0: static inline void profiler_responsiveness(const mozilla::TimeStamp& aTime) {} michael@0: michael@0: // Internal-only. Used by the event tracer. michael@0: static inline double* profiler_get_responsiveness() { return nullptr; } michael@0: michael@0: // Internal-only. michael@0: static inline void profiler_set_frame_number(int frameNumber) {} michael@0: michael@0: // Get the profile encoded as a JSON string. michael@0: static inline char* profiler_get_profile() { return nullptr; } michael@0: michael@0: // Get the profile encoded as a JSON object. michael@0: static inline JSObject* profiler_get_profile_jsobject(JSContext* aCx) { return nullptr; } michael@0: michael@0: // Get the profile and write it into a file michael@0: static inline void profiler_save_profile_to_file(char* aFilename) { } michael@0: michael@0: // Get the features supported by the profiler that are accepted by profiler_init. michael@0: // Returns a null terminated char* array. michael@0: static inline char** profiler_get_features() { return nullptr; } michael@0: michael@0: // Print the current location to the console. This functill will do it best effort michael@0: // to show the profiler's combined js/c++ if the profiler is running. Note that michael@0: // printing the location require symbolicating which is very slow. michael@0: static inline void profiler_print_location() {} michael@0: michael@0: // Discard the profile, throw away the profile and notify 'profiler-locked'. michael@0: // This function is to be used when entering private browsing to prevent michael@0: // the profiler from collecting sensitive data. michael@0: static inline void profiler_lock() {} michael@0: michael@0: // Re-enable the profiler and notify 'profiler-unlocked'. michael@0: static inline void profiler_unlock() {} michael@0: michael@0: static inline void profiler_register_thread(const char* name, void* stackTop) {} michael@0: static inline void profiler_unregister_thread() {} michael@0: michael@0: // These functions tell the profiler that a thread went to sleep so that we can avoid michael@0: // sampling it while it's sleeping. Calling profiler_sleep_start() twice without michael@0: // profiler_sleep_end() is an error. michael@0: static inline void profiler_sleep_start() {} michael@0: static inline void profiler_sleep_end() {} michael@0: michael@0: // Call by the JSRuntime's operation callback. This is used to enable michael@0: // profiling on auxilerary threads. michael@0: static inline void profiler_js_operation_callback() {} michael@0: michael@0: static inline double profiler_time() { return 0; } michael@0: static inline double profiler_time(const mozilla::TimeStamp& aTime) { return 0; } michael@0: michael@0: static inline bool profiler_in_privacy_mode() { return false; } michael@0: michael@0: #else michael@0: michael@0: #include "GeckoProfilerImpl.h" michael@0: michael@0: #endif michael@0: michael@0: class GeckoProfilerInitRAII { michael@0: public: michael@0: GeckoProfilerInitRAII(void* stackTop) { michael@0: profiler_init(stackTop); michael@0: } michael@0: ~GeckoProfilerInitRAII() { michael@0: profiler_shutdown(); michael@0: } michael@0: }; michael@0: michael@0: class GeckoProfilerSleepRAII { michael@0: public: michael@0: GeckoProfilerSleepRAII() { michael@0: profiler_sleep_start(); michael@0: } michael@0: ~GeckoProfilerSleepRAII() { michael@0: profiler_sleep_end(); michael@0: } michael@0: }; michael@0: michael@0: #endif // ifndef SAMPLER_H