| // Copyright 2013 The Flutter 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 FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_ | |
| #define FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_ | |
| #include <functional> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include "flutter/fml/task_runner.h" | |
| #include "flutter/fml/trace_event.h" | |
| namespace flutter { | |
| /** | |
| * @brief CPU usage stats. `num_threads` is the number of threads owned by the | |
| * process. It is to be noted that this is not per shell, there can be multiple | |
| * shells within the process. `total_cpu_usage` is the percentage (between [0, | |
| * 100]) cpu usage of the application. This is across all the cores, for example | |
| * an application using 100% of all the core will report `total_cpu_usage` as | |
| * `100`, if it has 100% across 2 cores and 0% across the other cores, embedder | |
| * must report `total_cpu_usage` as `50`. | |
| */ | |
| struct CpuUsageInfo { | |
| uint32_t num_threads; | |
| double total_cpu_usage; | |
| }; | |
| /** | |
| * @brief Container for the metrics we collect during each run of `Sampler`. | |
| * This currently holds `CpuUsageInfo` but the intent is to expand it to other | |
| * metrics. | |
| * | |
| * @see flutter::Sampler | |
| */ | |
| struct ProfileSample { | |
| std::optional<CpuUsageInfo> cpu_usage; | |
| }; | |
| /** | |
| * @brief Sampler is run during `SamplingProfiler::SampleRepeatedly`. Each | |
| * platform should implement its version of a `Sampler` if they decide to | |
| * participate in gathering profiling metrics. | |
| * | |
| * @see flutter::SamplingProfiler::SampleRepeatedly | |
| */ | |
| using Sampler = std::function<ProfileSample(void)>; | |
| /** | |
| * @brief a Sampling Profiler that runs peridically and calls the `Sampler` | |
| * which servers as a value function to gather various profiling metrics as | |
| * represented by `ProfileSample`. These profiling metrics are then posted to | |
| * the observatory timeline. | |
| * | |
| */ | |
| class SamplingProfiler { | |
| public: | |
| /** | |
| * @brief Construct a new Sampling Profiler object | |
| * | |
| * @param thread_label observatory prefix to be set for the profiling task | |
| * runner. | |
| * @param profiler_task_runner the task runner to service sampling requests. | |
| * @param sampler the value function to collect the profiling metrics. | |
| * @param num_samples_per_sec number of times you wish to run the sampler per | |
| * second. | |
| * | |
| * @see fml::TaskRunner | |
| */ | |
| SamplingProfiler(const char* thread_label, | |
| fml::RefPtr<fml::TaskRunner> profiler_task_runner, | |
| Sampler sampler, | |
| int num_samples_per_sec); | |
| /** | |
| * @brief Starts the SamplingProfiler by triggering `SampleRepeatedly`. | |
| * | |
| */ | |
| void Start() const; | |
| private: | |
| const std::string thread_label_; | |
| const fml::RefPtr<fml::TaskRunner> profiler_task_runner_; | |
| const Sampler sampler_; | |
| const uint32_t num_samples_per_sec_; | |
| void SampleRepeatedly(fml::TimeDelta task_delay) const; | |
| /** | |
| * @brief This doesn't update the underlying OS thread name for the thread | |
| * backing `profiler_task_runner_`. Instead, this is just additional metadata | |
| * for the Observatory to show the thread name of the isolate. | |
| * | |
| */ | |
| void UpdateObservatoryThreadName() const; | |
| FML_DISALLOW_COPY_AND_ASSIGN(SamplingProfiler); | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_ |