1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_
6#define FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_
7
8#include <functional>
9#include <memory>
10#include <optional>
11#include <string>
12
13#include "flutter/fml/task_runner.h"
14#include "flutter/fml/trace_event.h"
15
16namespace flutter {
17
18/**
19 * @brief CPU usage stats. `num_threads` is the number of threads owned by the
20 * process. It is to be noted that this is not per shell, there can be multiple
21 * shells within the process. `total_cpu_usage` is the percentage (between [0,
22 * 100]) cpu usage of the application. This is across all the cores, for example
23 * an application using 100% of all the core will report `total_cpu_usage` as
24 * `100`, if it has 100% across 2 cores and 0% across the other cores, embedder
25 * must report `total_cpu_usage` as `50`.
26 */
27struct CpuUsageInfo {
28 uint32_t num_threads;
29 double total_cpu_usage;
30};
31
32/**
33 * @brief Memory usage stats. `dirty_memory_usage` is the the memory usage (in
34 * MB) such that the app uses its physical memory for dirty memory. Dirty memory
35 * is the memory data that cannot be paged to disk. `owned_shared_memory_usage`
36 * is the memory usage (in MB) such that the app uses its physicaal memory for
37 * shared memory, including loaded frameworks and executables. On iOS, it's
38 * `physical memory - dirty memory`.
39 */
40struct MemoryUsageInfo {
41 double dirty_memory_usage;
42 double owned_shared_memory_usage;
43};
44
45/**
46 * @brief Polled information related to the usage of the GPU.
47 */
48struct GpuUsageInfo {
49 double percent_usage;
50};
51
52/**
53 * @brief Container for the metrics we collect during each run of `Sampler`.
54 * This currently holds `CpuUsageInfo` and `MemoryUsageInfo` but the intent
55 * is to expand it to other metrics.
56 *
57 * @see flutter::Sampler
58 */
59struct ProfileSample {
60 std::optional<CpuUsageInfo> cpu_usage;
61 std::optional<MemoryUsageInfo> memory_usage;
62 std::optional<GpuUsageInfo> gpu_usage;
63};
64
65/**
66 * @brief Sampler is run during `SamplingProfiler::SampleRepeatedly`. Each
67 * platform should implement its version of a `Sampler` if they decide to
68 * participate in gathering profiling metrics.
69 *
70 * @see flutter::SamplingProfiler::SampleRepeatedly
71 */
72using Sampler = std::function<ProfileSample(void)>;
73
74/**
75 * @brief a Sampling Profiler that runs peridically and calls the `Sampler`
76 * which servers as a value function to gather various profiling metrics as
77 * represented by `ProfileSample`. These profiling metrics are then posted to
78 * the observatory timeline.
79 *
80 */
81class SamplingProfiler {
82 public:
83 /**
84 * @brief Construct a new Sampling Profiler object
85 *
86 * @param thread_label observatory prefix to be set for the profiling task
87 * runner.
88 * @param profiler_task_runner the task runner to service sampling requests.
89 * @param sampler the value function to collect the profiling metrics.
90 * @param num_samples_per_sec number of times you wish to run the sampler per
91 * second.
92 *
93 * @see fml::TaskRunner
94 */
95 SamplingProfiler(const char* thread_label,
96 fml::RefPtr<fml::TaskRunner> profiler_task_runner,
97 Sampler sampler,
98 int num_samples_per_sec);
99
100 /**
101 * @brief Starts the SamplingProfiler by triggering `SampleRepeatedly`.
102 *
103 */
104 void Start() const;
105
106 private:
107 const std::string thread_label_;
108 const fml::RefPtr<fml::TaskRunner> profiler_task_runner_;
109 const Sampler sampler_;
110 const uint32_t num_samples_per_sec_;
111
112 void SampleRepeatedly(fml::TimeDelta task_delay) const;
113
114 /**
115 * @brief This doesn't update the underlying OS thread name for the thread
116 * backing `profiler_task_runner_`. Instead, this is just additional metadata
117 * for the Observatory to show the thread name of the isolate.
118 *
119 */
120 void UpdateObservatoryThreadName() const;
121
122 FML_DISALLOW_COPY_AND_ASSIGN(SamplingProfiler);
123};
124
125} // namespace flutter
126
127#endif // FLUTTER_SHELL_PROFILING_SAMPLING_PROFILER_H_
128