From 56422401d0d0bc819a8b8946de088393e571a510 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Fri, 15 Mar 2013 15:17:50 -0400 Subject: [PATCH] Bug 851611 - Part 1: Refactor profiler interface. r=jrmuizel --HG-- extra : rebase_source : a48e103dd5b31d620dd5ba67dc835ea9dc90864d --- tools/profiler/TableTicker.cpp | 2 +- tools/profiler/sampler.h | 117 ++++++++---- tools/profiler/sps_sampler.h | 321 +++++++++++++++++++-------------- 3 files changed, 271 insertions(+), 169 deletions(-) diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 40005bb01cb..44acc470577 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -1223,7 +1223,7 @@ bool mozilla_sampler_is_active1() static double sResponsivenessTimes[100]; static unsigned int sResponsivenessLoc = 0; -void mozilla_sampler_responsiveness1(TimeStamp aTime) +void mozilla_sampler_responsiveness1(const TimeStamp& aTime) { if (!sLastTracerEvent.IsNull()) { if (sResponsivenessLoc == 100) { diff --git a/tools/profiler/sampler.h b/tools/profiler/sampler.h index 99663c9b7ca..9eeeab7378f 100644 --- a/tools/profiler/sampler.h +++ b/tools/profiler/sampler.h @@ -49,42 +49,95 @@ #ifndef SAMPLER_H #define SAMPLER_H -// Redefine the macros for platforms where SPS is supported. -#ifdef MOZ_ENABLE_PROFILER_SPS +#include "jsfriendapi.h" +#include "mozilla/NullPtr.h" +#include "mozilla/TimeStamp.h" -#include "sps_sampler.h" +#ifndef MOZ_ENABLE_PROFILER_SPS + +// Insert a RAII in this scope to active a pseudo label. Any samples collected +// in this scope will contain this annotation. For dynamic strings use +// PROFILER_LABEL_PRINTF. Arguments must be string literals. +#define PROFILER_LABEL(name_space, info) do {} while (0) + +// Format a dynamic string as a pseudo label. These labels will a considerable +// storage size in the circular buffer compared to regular labels. This function +// can be used to annotate custom information such as URL for the resource being +// decoded or the size of the paint. +#define PROFILER_LABEL_PRINTF(name_space, info, format, ...) do {} while (0) + +// Insert a marker in the profile timeline. This is useful to delimit something +// important happening such as the first paint. Unlike profiler_label that are +// only recorded if a sample is collected while it is active, marker will always +// be collected. +#define PROFILER_MARKER(info) do {} while (0) + +// Main thread specilization to avoid TLS lookup for performance critical use. +#define PROFILER_MAIN_THREAD_LABEL(name_space, info) do {} while (0) +#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, format, ...) do {} while (0) + +// Initilize the profiler TLS, signal handlers on linux. If MOZ_PROFILER_STARTUP +// is set the profiler will be started. This call must happen before any other +// sampler calls. Particularly sampler_label/sampler_marker. +static inline void profiler_init() {}; + +// Clean up the profiler module, stopping it if required. This function may +// also save a shutdown profile if requested. No profiler calls should happen +// after this point and all pseudo labels should have been popped. +static inline void profiler_shutdown() {}; + +// Start the profiler with the selected options. The samples will be +// recorded in a circular buffer. +// "aProfileEntries" is an abstract size indication of how big +// the profile's circular buffer should be. Multiply by 4 +// words to get the cost. +// "aInterval" the sampling interval. The profiler will do its +// best to sample at this interval. The profiler visualization +// should represent the actual sampling accuracy. +static inline void profiler_start(int aProfileEntries, int aInterval, + const char** aFeatures, uint32_t aFeatureCount) {} + +// Stop the profiler and discard the profile. Call 'profiler_save' before this +// to retrieve the profile. +static inline void profiler_stop() {} + +static inline bool profiler_is_active() { return false; } + +// Internal-only. Used by the event tracer. +static inline void profiler_responsinveness(const TimeStamp& aTime) {} + +// Internal-only. Used by the event tracer. +static inline double* profiler_get_responsiveness() { return nullptr; } + +// Internal-only. +static inline void profile_set_frame_number(int frameNumber) {} + +// Get the profile encoded as a JSON string. +static inline char* profiler_get_profile() { return nullptr; } + +// Get the profile encoded as a JSON object. +static inline JSObject* profiler_get_profile_object() { return nullptr; } + +// Get the features supported by the profiler that are accepted by profiler_init. +// Returns a null terminated char* array. +static inline char** profiler_get_features() { return nullptr; } + +// Print the current location to the console. This functill will do it best effort +// to show the profiler's combined js/c++ if the profiler is running. Note that +// printing the location require symbolicating which is very slow. +static inline void profiler_print_location() {} + +// Discard the profile, throw away the profile and notify 'profiler-locked'. +// This function is to be used when entering private browsing to prevent +// the profiler from collecting sensitive data. +static inline void profiler_lock() {} + +// Re-enable the profiler and notify 'profiler-unlocked'. +static inline void profiler_unlock() {} #else -// Initialize the sampler. Any other calls will be silently discarded -// before the sampler has been initialized (i.e. early start-up code) -#define SAMPLER_INIT() -#define SAMPLER_SHUTDOWN() -#define SAMPLER_START(entries, interval, features, featureCount) -#define SAMPLER_STOP() -#define SAMPLER_IS_ACTIVE() false -#define SAMPLER_SAVE() -// Returned string must be free'ed -#define SAMPLER_GET_PROFILE() NULL -#define SAMPLER_GET_PROFILE_DATA(ctx) NULL -#define SAMPLER_RESPONSIVENESS(time) NULL -#define SAMPLER_FRAME_NUMBER(frameNumber) -#define SAMPLER_GET_RESPONSIVENESS() NULL -#define SAMPLER_GET_FEATURES() NULL -#define SAMPLE_LABEL(name_space, info) -// Provide a default literal string to use if profiling is disabled -// and a printf argument to be computed if profiling is enabled. -// NOTE: This will store the formated string on the stack and consume -// over 128 bytes on the stack. -#define SAMPLE_LABEL_PRINTF(name_space, info, format, ...) -#define SAMPLE_LABEL_FN(name_space, info) -#define SAMPLE_MARKER(info) -#define SAMPLE_MAIN_THREAD_LABEL_PRINTF(name_space, info, format, ...) -#define SAMPLE_MAIN_THREAD_LABEL_FN(name_space, info) -#define SAMPLE_MAIN_THREAD_MARKER(info) - -// Tracing features -#define SAMPLER_PRINT_LOCATION() +#include "sps_sampler.h" #endif diff --git a/tools/profiler/sps_sampler.h b/tools/profiler/sps_sampler.h index 9acaa1d2515..03166a8cf34 100644 --- a/tools/profiler/sps_sampler.h +++ b/tools/profiler/sps_sampler.h @@ -46,72 +46,197 @@ extern bool stack_key_initialized; # endif #endif +// Returns a handle to pass on exit. This can check that we are popping the +// correct callstack. +inline void* mozilla_sampler_call_enter(const char *aInfo, void *aFrameAddress = NULL, + bool aCopy = false, uint32_t line = 0); +inline void mozilla_sampler_call_exit(void* handle); +inline void mozilla_sampler_add_marker(const char *aInfo); + +void mozilla_sampler_start1(int aEntries, int aInterval, const char** aFeatures, + uint32_t aFeatureCount); +void mozilla_sampler_start2(int aEntries, int aInterval, const char** aFeatures, + uint32_t aFeatureCount); + +void mozilla_sampler_stop1(); +void mozilla_sampler_stop2(); + +bool mozilla_sampler_is_active1(); +bool mozilla_sampler_is_active2(); + +void mozilla_sampler_responsiveness1(TimeStamp time); +void mozilla_sampler_responsiveness2(TimeStamp time); + +void mozilla_sampler_frame_number1(int frameNumber); +void mozilla_sampler_frame_number2(int frameNumber); + +const double* mozilla_sampler_get_responsiveness1(); +const double* mozilla_sampler_get_responsiveness2(); + +void mozilla_sampler_save1(); +void mozilla_sampler_save2(); + +char* mozilla_sampler_get_profile1(); +char* mozilla_sampler_get_profile2(); + +JSObject *mozilla_sampler_get_profile_data1(JSContext *aCx); +JSObject *mozilla_sampler_get_profile_data2(JSContext *aCx); + +const char** mozilla_sampler_get_features1(); +const char** mozilla_sampler_get_features2(); + +void mozilla_sampler_init1(); +void mozilla_sampler_init2(); + +void mozilla_sampler_shutdown1(); +void mozilla_sampler_shutdown2(); + +void mozilla_sampler_print_location1(); +void mozilla_sampler_print_location2(); + +// Lock the profiler. When locked the profiler is (1) stopped, +// (2) profile data is cleared, (3) profiler-locked is fired. +// This is used to lock down the profiler during private browsing +void mozilla_sampler_lock1(); +void mozilla_sampler_lock2(); + +// Unlock the profiler, leaving it stopped and fires profiler-unlocked. +void mozilla_sampler_unlock1(); +void mozilla_sampler_unlock2(); + /* Returns true if env var SPS_NEW is set to anything, else false. */ extern bool sps_version2(); -#define SAMPLER_INIT() \ - do { \ - if (!sps_version2()) mozilla_sampler_init1(); \ - else mozilla_sampler_init2(); \ - } while (0) +static inline +void profiler_init() +{ + if (!sps_version2()) { + mozilla_sampler_init1(); + } else { + mozilla_sampler_init2(); + } +} -#define SAMPLER_SHUTDOWN() \ - do { \ - if (!sps_version2()) mozilla_sampler_shutdown1(); \ - else mozilla_sampler_shutdown2(); \ - } while (0) +static inline +void profiler_shutdown() +{ + if (!sps_version2()) { + mozilla_sampler_shutdown1(); + } else { + mozilla_sampler_shutdown2(); + } +} -#define SAMPLER_START(entries, interval, features, featureCount) \ - do { \ - if (!sps_version2()) \ - mozilla_sampler_start1(entries, interval, features, featureCount); \ - else \ - mozilla_sampler_start2(entries, interval, features, featureCount); \ - } while (0) +static inline +void profiler_start(int aProfileEntries, int aInterval, + const char** aFeatures, uint32_t aFeatureCount) +{ + if (!sps_version2()) { + mozilla_sampler_start1(aProfileEntries, aInterval, aFeatures, aFeatureCount); + } else { + mozilla_sampler_start2(aProfileEntries, aInterval, aFeatures, aFeatureCount); + } +} -#define SAMPLER_STOP() \ - do { \ - if (!sps_version2()) mozilla_sampler_stop1(); \ - else mozilla_sampler_stop2(); \ - } while (0) +static inline +void profiler_stop() +{ + if (!sps_version2()) { + mozilla_sampler_stop1(); + } else { + mozilla_sampler_stop2(); + } +} -#define SAMPLER_IS_ACTIVE() \ - (!sps_version2() ? mozilla_sampler_is_active1() \ - : mozilla_sampler_is_active2() ) +static inline +bool profiler_is_active() +{ + if (!sps_version2()) { + return mozilla_sampler_is_active1(); + } else { + return mozilla_sampler_is_active2(); + } +} -#define SAMPLER_RESPONSIVENESS(time) \ - do { \ - if (!sps_version2()) mozilla_sampler_responsiveness1(time); \ - else mozilla_sampler_responsiveness2(time); \ - } while (0) +static inline +void profiler_responsiveness(const TimeStamp& aTime) +{ + if (!sps_version2()) { + mozilla_sampler_responsiveness1(aTime); + } else { + mozilla_sampler_responsiveness2(aTime); + } +} -#define SAMPLER_GET_RESPONSIVENESS() \ - (!sps_version2() ? mozilla_sampler_get_responsiveness1() \ - : mozilla_sampler_get_responsiveness2() ) +static inline +const double* profiler_get_responsiveness() +{ + if (!sps_version2()) { + return mozilla_sampler_get_responsiveness1(); + } else { + return mozilla_sampler_get_responsiveness2(); + } +} -#define SAMPLER_FRAME_NUMBER(frameNumber) \ - do { \ - if (!sps_version2()) mozilla_sampler_frame_number1(frameNumber); \ - else mozilla_sampler_frame_number2(frameNumber); \ - } while (0) +static inline +void profiler_set_frame_number(int frameNumber) +{ + if (!sps_version2()) { + return mozilla_sampler_frame_number1(frameNumber); + } else { + return mozilla_sampler_frame_number2(frameNumber); + } +} -#define SAMPLER_SAVE() \ - do { \ - if (!sps_version2()) mozilla_sampler_save1(); \ - else mozilla_sampler_save2(); \ - } while (0) +static inline +char* profiler_get_profile() +{ + if (!sps_version2()) { + return mozilla_sampler_get_profile1(); + } else { + return mozilla_sampler_get_profile2(); + } +} -#define SAMPLER_GET_PROFILE() \ - (!sps_version2() ? mozilla_sampler_get_profile1() \ - : mozilla_sampler_get_profile2() ) +static inline +const char** profiler_get_features() +{ + if (!sps_version2()) { + return mozilla_sampler_get_features1(); + } else { + return mozilla_sampler_get_features2(); + } +} -#define SAMPLER_GET_PROFILE_DATA(ctx) \ - (!sps_version2() ? mozilla_sampler_get_profile_data1(ctx) \ - : mozilla_sampler_get_profile_data2(ctx) ) +static inline +void profiler_print_location() +{ + if (!sps_version2()) { + return mozilla_sampler_print_location1(); + } else { + return mozilla_sampler_print_location2(); + } +} -#define SAMPLER_GET_FEATURES() \ - (!sps_version2() ? mozilla_sampler_get_features1() \ - : mozilla_sampler_get_features2() ) +static inline +void profiler_lock() +{ + if (!sps_version2()) { + return mozilla_sampler_lock1(); + } else { + return mozilla_sampler_lock2(); + } +} + +static inline +void profiler_unlock() +{ + if (!sps_version2()) { + return mozilla_sampler_unlock1(); + } else { + return mozilla_sampler_unlock2(); + } +} // we want the class and function name but can't easily get that using preprocessor macros // __func__ doesn't have the class name and __PRETTY_FUNCTION__ has the parameters @@ -120,30 +245,12 @@ extern bool sps_version2(); #define SAMPLER_APPEND_LINE_NUMBER_EXPAND(id, line) SAMPLER_APPEND_LINE_NUMBER_PASTE(id, line) #define SAMPLER_APPEND_LINE_NUMBER(id) SAMPLER_APPEND_LINE_NUMBER_EXPAND(id, __LINE__) -#define SAMPLE_LABEL(name_space, info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__) -#define SAMPLE_LABEL_PRINTF(name_space, info, ...) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__) -#define SAMPLE_MARKER(info) mozilla_sampler_add_marker(info) -#define SAMPLE_MAIN_THREAD_LABEL(name_space, info) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__) -#define SAMPLE_MAIN_THREAD_LABEL_PRINTF(name_space, info, ...) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__) -#define SAMPLE_MAIN_THREAD_MARKER(info) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla_sampler_add_marker(info) - -#define SAMPLER_PRINT_LOCATION() \ - do { \ - if (!sps_version2()) mozilla_sampler_print_location1(); \ - else mozilla_sampler_print_location2(); \ - } while (0) - -#define SAMPLER_LOCK() \ - do { \ - if (!sps_version2()) mozilla_sampler_lock1(); \ - else mozilla_sampler_lock2(); \ - } while (0) - -#define SAMPLER_UNLOCK() \ - do { \ - if (!sps_version2()) mozilla_sampler_unlock1(); \ - else mozilla_sampler_unlock2(); \ - } while (0) +#define PROFILER_LABEL(name_space, info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__) +#define PROFILER_LABEL_PRINTF(name_space, info, ...) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__) +#define PROFILER_MARKER(info) mozilla_sampler_add_marker(info) +#define PROFILER_MAIN_THREAD_LABEL(name_space, info) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__) +#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, ...) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__) +#define PROFILER_MAIN_THREAD_MARKER(info) MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla_sampler_add_marker(info) /* we duplicate this code here to avoid header dependencies * which make it more difficult to include in other places */ @@ -238,64 +345,6 @@ LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = # error "Memory clobber not supported for your platform." #endif -// Returns a handle to pass on exit. This can check that we are popping the -// correct callstack. -inline void* mozilla_sampler_call_enter(const char *aInfo, void *aFrameAddress = NULL, - bool aCopy = false, uint32_t line = 0); -inline void mozilla_sampler_call_exit(void* handle); -inline void mozilla_sampler_add_marker(const char *aInfo); - -void mozilla_sampler_start1(int aEntries, int aInterval, const char** aFeatures, - uint32_t aFeatureCount); -void mozilla_sampler_start2(int aEntries, int aInterval, const char** aFeatures, - uint32_t aFeatureCount); - -void mozilla_sampler_stop1(); -void mozilla_sampler_stop2(); - -bool mozilla_sampler_is_active1(); -bool mozilla_sampler_is_active2(); - -void mozilla_sampler_responsiveness1(TimeStamp time); -void mozilla_sampler_responsiveness2(TimeStamp time); - -void mozilla_sampler_frame_number1(int frameNumber); -void mozilla_sampler_frame_number2(int frameNumber); - -const double* mozilla_sampler_get_responsiveness1(); -const double* mozilla_sampler_get_responsiveness2(); - -void mozilla_sampler_save1(); -void mozilla_sampler_save2(); - -char* mozilla_sampler_get_profile1(); -char* mozilla_sampler_get_profile2(); - -JSObject *mozilla_sampler_get_profile_data1(JSContext *aCx); -JSObject *mozilla_sampler_get_profile_data2(JSContext *aCx); - -const char** mozilla_sampler_get_features1(); -const char** mozilla_sampler_get_features2(); - -void mozilla_sampler_init1(); -void mozilla_sampler_init2(); - -void mozilla_sampler_shutdown1(); -void mozilla_sampler_shutdown2(); - -void mozilla_sampler_print_location1(); -void mozilla_sampler_print_location2(); - -// Lock the profiler. When locked the profiler is (1) stopped, -// (2) profile data is cleared, (3) profiler-locked is fired. -// This is used to lock down the profiler during private browsing -void mozilla_sampler_lock1(); -void mozilla_sampler_lock2(); - -// Unlock the profiler, leaving it stopped and fires profiler-unlocked. -void mozilla_sampler_unlock1(); -void mozilla_sampler_unlock2(); - namespace mozilla { class NS_STACK_CLASS SamplerStackFrameRAII { @@ -316,7 +365,7 @@ class NS_STACK_CLASS SamplerStackFramePrintfRAII { public: // we only copy the strings at save time, so to take multiple parameters we'd need to copy them then. SamplerStackFramePrintfRAII(const char *aDefault, uint32_t line, const char *aFormat, ...) { - if (SAMPLER_IS_ACTIVE()) { + if (profiler_is_active()) { va_list args; va_start(args, aFormat); char buff[SAMPLER_MAX_STRING]; @@ -575,7 +624,7 @@ inline void mozilla_sampler_add_marker(const char *aMarker) // Don't insert a marker if we're not profiling to avoid // the heap copy (malloc). - if (!SAMPLER_IS_ACTIVE()) { + if (!profiler_is_active()) { return; }