Flutter Engine
The Flutter Engine
sampling_profiler.cc
Go to the documentation of this file.
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
7#include <utility>
8
9namespace flutter {
10
12 const char* thread_label,
13 fml::RefPtr<fml::TaskRunner> profiler_task_runner,
14 Sampler sampler,
15 int num_samples_per_sec)
16 : thread_label_(thread_label),
17 profiler_task_runner_(std::move(profiler_task_runner)),
18 sampler_(std::move(sampler)),
19 num_samples_per_sec_(num_samples_per_sec) {}
20
22 if (is_running_) {
23 Stop();
24 }
25}
26
28 if (!profiler_task_runner_) {
29 return;
30 }
31 FML_CHECK(num_samples_per_sec_ > 0)
32 << "number of samples must be a positive integer, got: "
33 << num_samples_per_sec_;
34 double delay_between_samples = 1.0 / num_samples_per_sec_;
35 auto task_delay = fml::TimeDelta::FromSecondsF(delay_between_samples);
36 UpdateDartVMServiceThreadName();
37 is_running_ = true;
38 SampleRepeatedly(task_delay);
39}
40
42 FML_DCHECK(is_running_);
43 auto latch = std::make_unique<fml::AutoResetWaitableEvent>();
44 shutdown_latch_.store(latch.get());
45 latch->Wait();
46 shutdown_latch_.store(nullptr);
47 is_running_ = false;
48}
49
50void SamplingProfiler::SampleRepeatedly(fml::TimeDelta task_delay) const {
51 profiler_task_runner_->PostDelayedTask(
52 [profiler = this, task_delay = task_delay, sampler = sampler_,
53 &shutdown_latch = shutdown_latch_]() {
54 // TODO(kaushikiska): consider buffering these every n seconds to
55 // avoid spamming the trace buffer.
56 const ProfileSample usage = sampler();
57 if (usage.cpu_usage) {
58 const auto& cpu_usage = usage.cpu_usage;
59 std::string total_cpu_usage =
60 std::to_string(cpu_usage->total_cpu_usage);
61 std::string num_threads = std::to_string(cpu_usage->num_threads);
62 TRACE_EVENT_INSTANT2("flutter::profiling", "CpuUsage",
63 "total_cpu_usage", total_cpu_usage.c_str(),
64 "num_threads", num_threads.c_str());
65 }
66 if (usage.memory_usage) {
67 std::string dirty_memory_usage =
68 std::to_string(usage.memory_usage->dirty_memory_usage);
69 std::string owned_shared_memory_usage =
70 std::to_string(usage.memory_usage->owned_shared_memory_usage);
71 TRACE_EVENT_INSTANT2("flutter::profiling", "MemoryUsage",
72 "dirty_memory_usage", dirty_memory_usage.c_str(),
73 "owned_shared_memory_usage",
74 owned_shared_memory_usage.c_str());
75 }
76 if (usage.gpu_usage) {
77 std::string gpu_usage =
78 std::to_string(usage.gpu_usage->percent_usage);
79 TRACE_EVENT_INSTANT1("flutter::profiling", "GpuUsage", "gpu_usage",
80 gpu_usage.c_str());
81 }
82 if (shutdown_latch.load()) {
83 shutdown_latch.load()->Signal();
84 } else {
85 profiler->SampleRepeatedly(task_delay);
86 }
87 },
88 task_delay);
89}
90
91void SamplingProfiler::UpdateDartVMServiceThreadName() const {
92 FML_CHECK(profiler_task_runner_);
93
94 profiler_task_runner_->PostTask(
95 [label = thread_label_ + std::string{".profiler"}]() {
96 Dart_SetThreadName(label.c_str());
97 });
98}
99
100} // namespace flutter
SamplingProfiler(const char *thread_label, fml::RefPtr< fml::TaskRunner > profiler_task_runner, Sampler sampler, int num_samples_per_sec)
Construct a new Sampling Profiler object.
void Start()
Starts the SamplingProfiler by triggering SampleRepeatedly.
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
virtual void PostDelayedTask(const fml::closure &task, fml::TimeDelta delay)
Definition: task_runner.cc:33
static constexpr TimeDelta FromSecondsF(double seconds)
Definition: time_delta.h:53
DART_EXPORT void Dart_SetThreadName(const char *name)
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_DCHECK(condition)
Definition: logging.h:103
std::function< ProfileSample(void)> Sampler
Sampler is run during SamplingProfiler::SampleRepeatedly. Each platform should implement its version ...
Definition: ref_ptr.h:256
static SkString to_string(int n)
Definition: nanobench.cpp:119
static void usage(char *argv0)
Container for the metrics we collect during each run of Sampler. This currently holds CpuUsageInfo an...
#define TRACE_EVENT_INSTANT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
Definition: trace_event.h:184
#define TRACE_EVENT_INSTANT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:179