// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_PROFILER_SAMPLE_METADATA_H_ #define BASE_PROFILER_SAMPLE_METADATA_H_ #include "base/optional.h" #include "base/profiler/metadata_recorder.h" #include "base/strings/string_piece.h" // ----------------------------------------------------------------------------- // Usage documentation // ----------------------------------------------------------------------------- // // Overview: // These functions provide a means to control the metadata attached to samples // collected by the stack sampling profiler. Metadata state is shared between // all threads within a process. // // Any samples collected by the sampling profiler will include the active // metadata. This enables us to later analyze targeted subsets of samples // (e.g. those collected during paint or layout). // // For example: // // void DidStartLoad() { // is_loading_metadata_.Set(1); // } // // void DidFinishLoad() { // is_loading_metadata_.Remove(); // } // // base::SampleMetadata is_loading_metadata_; // // Alternatively, ScopedSampleMetadata can be used to ensure that the metadata // is removed correctly. // // For example: // // void DoExpensiveWork() { // base::ScopedSampleMetadata metadata("xyz", 1); // if (...) { // ... // if (...) { // ... // return; // } // } // ... // } namespace base { class BASE_EXPORT SampleMetadata { public: // Set the metadata value associated with |name|. explicit SampleMetadata(StringPiece name); SampleMetadata(const SampleMetadata&) = default; ~SampleMetadata() = default; SampleMetadata& operator=(const SampleMetadata&) = delete; // Set the metadata value associated with |name| in the process-global stack // sampling profiler metadata, overwriting any previous value set for that // |name|. void Set(int64_t value); // Set the metadata value associated with the pair (|name|, |key|) in the // process-global stack sampling profiler metadata, overwriting any previous // value set for that (|name|, |key|) pair. This constructor allows the // metadata to be associated with an additional user-defined key. One might // supply a key based on the frame id, for example, to distinguish execution // in service of scrolling between different frames. Prefer the previous // function if no user-defined metadata is required. Note: values specified // for a name and key are stored separately from values specified with only a // name. void Set(int64_t key, int64_t value); // Removes the metadata item with the specified name from the process-global // stack sampling profiler metadata. // // If such an item doesn't exist, this has no effect. void Remove(); // Removes the metadata item with the specified (|name|, |key|) pair from the // process-global stack sampling profiler metadata. This function does not // alter values set with the name |name| but no key. // // If such an item doesn't exist, this has no effect. void Remove(int64_t key); private: const uint64_t name_hash_; }; class BASE_EXPORT ScopedSampleMetadata { public: // Set the metadata value associated with |name|. ScopedSampleMetadata(StringPiece name, int64_t value); // Set the metadata value associated with the pair (|name|, |key|). This // constructor allows the metadata to be associated with an additional // user-defined key. One might supply a key based on the frame id, for // example, to distinguish execution in service of scrolling between different // frames. Prefer the previous constructor if no user-defined metadata is // required. Note: values specified for a name and key are stored separately // from values specified with only a name. ScopedSampleMetadata(StringPiece name, int64_t key, int64_t value); ScopedSampleMetadata(const ScopedSampleMetadata&) = delete; ~ScopedSampleMetadata(); ScopedSampleMetadata& operator=(const ScopedSampleMetadata&) = delete; private: const uint64_t name_hash_; Optional key_; }; // Applies the specified metadata to samples already recorded between // |period_start| and |period_end| in all thread's active profiles, subject to // the condition that the profile fully encompasses the period and the profile // has not already completed. The condition ensures that the metadata is applied // only if all execution during its scope was seen in the profile. This avoids // biasng the samples towards the 'middle' of the execution seen during the // metadata scope (i.e. because the start or end of execution was missed), at // the cost of missing execution that are longer than the profiling period, or // extend before or after it. |period_end| must be <= TimeTicks::Now(). BASE_EXPORT void ApplyMetadataToPastSamples(TimeTicks period_start, TimeTicks period_end, StringPiece name, int64_t value); BASE_EXPORT void ApplyMetadataToPastSamples(TimeTicks period_start, TimeTicks period_end, StringPiece name, int64_t key, int64_t value); // Returns the process-global metadata recorder instance used for tracking // sampling profiler metadata. // // This function should not be called by non-profiler related code. BASE_EXPORT MetadataRecorder* GetSampleMetadataRecorder(); } // namespace base #endif // BASE_PROFILER_SAMPLE_METADATA_H_