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#include "flutter/shell/profiling/sampling_profiler.h"
6
7namespace flutter {
8
9SamplingProfiler::SamplingProfiler(
10 const char* thread_label,
11 fml::RefPtr<fml::TaskRunner> profiler_task_runner,
12 Sampler sampler,
13 int num_samples_per_sec)
14 : thread_label_(thread_label),
15 profiler_task_runner_(profiler_task_runner),
16 sampler_(std::move(sampler)),
17 num_samples_per_sec_(num_samples_per_sec) {}
18
19void SamplingProfiler::Start() const {
20 if (!profiler_task_runner_) {
21 return;
22 }
23 FML_CHECK(num_samples_per_sec_ > 0)
24 << "number of samples must be a positive integer, got: "
25 << num_samples_per_sec_;
26 double delay_between_samples = 1.0 / num_samples_per_sec_;
27 auto task_delay = fml::TimeDelta::FromSecondsF(delay_between_samples);
28 UpdateObservatoryThreadName();
29 SampleRepeatedly(task_delay);
30}
31
32void SamplingProfiler::SampleRepeatedly(fml::TimeDelta task_delay) const {
33 profiler_task_runner_->PostDelayedTask(
34 [profiler = this, task_delay = task_delay, sampler = sampler_]() {
35 // TODO(kaushikiska): consider buffering these every n seconds to
36 // avoid spamming the trace buffer.
37 const ProfileSample usage = sampler();
38 if (usage.cpu_usage) {
39 const auto& cpu_usage = usage.cpu_usage;
40 std::string total_cpu_usage =
41 std::to_string(cpu_usage->total_cpu_usage);
42 std::string num_threads = std::to_string(cpu_usage->num_threads);
43 TRACE_EVENT_INSTANT2("flutter::profiling", "CpuUsage",
44 "total_cpu_usage", total_cpu_usage.c_str(),
45 "num_threads", num_threads.c_str());
46 }
47 if (usage.memory_usage) {
48 std::string dirty_memory_usage =
49 std::to_string(usage.memory_usage->dirty_memory_usage);
50 std::string owned_shared_memory_usage =
51 std::to_string(usage.memory_usage->owned_shared_memory_usage);
52 TRACE_EVENT_INSTANT2("flutter::profiling", "MemoryUsage",
53 "dirty_memory_usage", dirty_memory_usage.c_str(),
54 "owned_shared_memory_usage",
55 owned_shared_memory_usage.c_str());
56 }
57 if (usage.gpu_usage) {
58 std::string gpu_usage =
59 std::to_string(usage.gpu_usage->percent_usage);
60 TRACE_EVENT_INSTANT1("flutter::profiling", "GpuUsage", "gpu_usage",
61 gpu_usage.c_str());
62 }
63 profiler->SampleRepeatedly(task_delay);
64 },
65 task_delay);
66}
67
68void SamplingProfiler::UpdateObservatoryThreadName() const {
69 FML_CHECK(profiler_task_runner_);
70
71 profiler_task_runner_->PostTask(
72 [label = thread_label_ + std::string{".profiler"}]() {
73 Dart_SetThreadName(label.c_str());
74 });
75}
76
77} // namespace flutter
78