// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in // the documentation and/or other materials provided with the // distribution. // * Neither the name of Google, Inc. nor the names of its contributors // may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE.
// These are for MOZ_LOG="prof:3" or higher. It's the default logging level for // the profiler, and should be used sparingly. #define LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Info) #define LOG(arg, ...) \
MOZ_LOG(gProfilerLog, mozilla::LogLevel::Info, \
("[%" PRIu64 "] " arg, \
uint64_t(profiler_current_process_id().ToNumber()), ##__VA_ARGS__))
// These are for MOZ_LOG="prof:4" or higher. It should be used for logging that // is somewhat more verbose than LOG. #define DEBUG_LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Debug) #define DEBUG_LOG(arg, ...) \
MOZ_LOG(gProfilerLog, mozilla::LogLevel::Debug, \
("[%" PRIu64 "] " arg, \
uint64_t(profiler_current_process_id().ToNumber()), ##__VA_ARGS__))
typedef uint8_t* Address;
// Stringify the given JSON value, in the most compact format. // Note: Numbers are limited to a precision of 6 decimal digits, so that // timestamps in ms have a precision in ns.
Json::String ToCompactString(const Json::Value& aJsonValue);
// Profiling log stored in a Json::Value. The actual log only exists while the // profiler is running, and will be inserted at the end of the JSON profile. class ProfilingLog { public: // These will be called by ActivePS when the profiler starts/stops. staticvoid Init(); staticvoid Destroy();
// Access the profiling log JSON object, in order to modify it. // Only calls the given function if the profiler is active. // Thread-safe. But `aF` must not call other locking profiler functions. // This is intended to capture some internal logging that doesn't belong in // other places like markers. The log is accessible through the JS console on // profiler.firefox.com, in the `profile.profilingLog` object; the data format // is intentionally not defined, and not intended to be shown in the // front-end. // Please use caution not to output too much data. template <typename F> staticvoid Access(F&& aF) {
mozilla::baseprofiler::detail::BaseProfilerAutoLock lock{gMutex}; if (gLog) {
std::forward<F>(aF)(*gLog);
}
}
#define DURATION_JSON_SUFFIX "_ms"
// Convert a TimeDuration to the value to be stored in the log. // Use DURATION_JSON_SUFFIX as suffix in the property name. static Json::Value Duration(const mozilla::TimeDuration& aDuration) { return Json::Value{aDuration.ToMilliseconds()};
}
#define TIMESTAMP_JSON_SUFFIX "_TSms"
// Convert a TimeStamp to the value to be stored in the log. // Use TIMESTAMP_JSON_SUFFIX as suffix in the property name. static Json::Value Timestamp( const mozilla::TimeStamp& aTimestamp = mozilla::TimeStamp::Now()) { if (aTimestamp.IsNull()) { return Json::Value{0.0};
} return Duration(aTimestamp - mozilla::TimeStamp::ProcessCreation());
}
// If positive, skip stack-sampling in the sampler thread loop. // Users should increment it atomically when samplings should be avoided, and // later decrement it back. Multiple uses can overlap. // There could be a sampling in progress when this is first incremented, so if // it is critical to prevent any sampling, lock the profiler mutex instead. // Relaxed ordering, because it's used to request that the profiler pause // future sampling; this is not time critical, nor dependent on anything else. extern mozilla::Atomic<int, mozilla::MemoryOrdering::Relaxed> gSkipSampling;
// Convert the array of strings to a bitfield.
uint32_t ParseFeaturesFromStringArray(constchar** aFeatures,
uint32_t aFeatureCount, bool aIsStartup = false);
// Add the begin/end 'Awake' markers for the thread. void profiler_mark_thread_awake();
// Flags to conveniently track various JS instrumentations. enumclass JSInstrumentationFlags {
StackSampling = 0x1,
Allocations = 0x2,
};
// Write out the information of the active profiling configuration. void profiler_write_active_configuration(mozilla::JSONWriter& aWriter);
// Extract all received exit profiles that have not yet expired (i.e., they // still intersect with this process' buffer range).
mozilla::Vector<nsCString> profiler_move_exit_profiles();
// If the "MOZ_PROFILER_SYMBOLICATE" env-var is set, we return a new // ProfilerCodeAddressService object to use for local symbolication of profiles. // This is off by default, and mainly intended for local development.
mozilla::UniquePtr<ProfilerCodeAddressService>
profiler_code_address_service_for_presymbolication();
extern"C" { // This function is defined in the profiler rust module at // tools/profiler/rust-helper. mozilla::SymbolTable and CompactSymbolTable // have identical memory layout. bool profiler_get_symbol_table(constchar* debug_path, constchar* breakpad_id,
mozilla::SymbolTable* symbol_table);
// For each running times value, call MACRO(index, name, unit, jsonProperty) #define PROFILER_FOR_EACH_RUNNING_TIME(MACRO) \
MACRO(0, ThreadCPU, Delta, threadCPUDelta)
// This class contains all "running times" such as CPU usage measurements. // All measurements are listed in `PROFILER_FOR_EACH_RUNNING_TIME` above. // Each measurement is optional and only takes a value when explicitly set. // Two RunningTimes object may be subtracted, to get the difference between // known values. class RunningTimes { public:
constexpr RunningTimes() = default;
// Constructor with only a timestamp, useful when no measurements will be // taken.
constexpr explicit RunningTimes(const mozilla::TimeStamp& aTimeStamp)
: mPostMeasurementTimeStamp(aTimeStamp) {}
// This should be called right after CPU measurements have been taken. void SetPostMeasurementTimeStamp(const mozilla::TimeStamp& aTimeStamp) {
mPostMeasurementTimeStamp = aTimeStamp;
}
// Take values from another RunningTimes.
RunningTimes& TakeFrom(RunningTimes& aOther) { if (!aOther.IsEmpty()) { #define RUNNING_TIME_TAKE(index, name, unit, jsonProperty) \ if (aOther.Is##name##unit##Known()) { \
Set##name##unit(std::exchange(aOther.m##name##unit, 0)); \
}
PROFILER_FOR_EACH_RUNNING_TIME(RUNNING_TIME_TAKE)
#undef RUNNING_TIME_TAKE
aOther.mKnownBits = 0;
} return *this;
}
// Difference from `aBefore` to `this`. Any unknown makes the result unknown. // PostMeasurementTimeStamp set to `this` PostMeasurementTimeStamp, to keep // the most recent timestamp associated with the end of the interval over // which the difference applies.
RunningTimes operator-(const RunningTimes& aBefore) const {
RunningTimes diff;
diff.mPostMeasurementTimeStamp = mPostMeasurementTimeStamp; #define RUNNING_TIME_SUB(index, name, unit, jsonProperty) \ if (Is##name##unit##Known() && aBefore.Is##name##unit##Known()) { \
diff.Set##name##unit(m##name##unit - aBefore.m##name##unit); \
}
static RunningTimes Read(ProfileBufferEntryReader& aER) { // Start with empty running times, everything is cleared.
RunningTimes times;
// This sets all the bits into mKnownBits, we don't need to modify it // further.
times.mKnownBits = aER.ReadULEB128<uint32_t>();
// For each member that should be known, read its value. #define RUNNING_TIME_DESERIALIZE(index, name, unit, jsonProperty) \ if (times.Is##name##unit##Known()) { \
times.m##name##unit = aER.ReadULEB128<decltype(times.m##name##unit)>(); \
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.