Flutter Engine
The Flutter Engine
timer.h
Go to the documentation of this file.
1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_TIMER_H_
6#define RUNTIME_VM_TIMER_H_
7
8#include "platform/atomic.h"
9#include "platform/utils.h"
10#include "vm/allocation.h"
11#include "vm/flags.h"
12#include "vm/os.h"
13
14namespace dart {
15
17 static inline int64_t Now() { return OS::GetCurrentMonotonicMicros(); }
18};
19
20struct MeasureCpu {
21 static inline int64_t Now() { return OS::GetCurrentThreadCPUMicros(); }
22};
23
24// Timer class allows timing of specific operations in the VM.
25template <typename Measure>
26class TimerImpl : public ValueObject {
27 public:
30
31 // Start timer.
32 void Start() {
33 start_ = Measure::Now();
34 running_ = true;
35 }
36
37 // Stop timer.
38 void Stop() {
39 ASSERT(running());
40 stop_ = Measure::Now();
41 int64_t elapsed = ElapsedMicros();
42 max_contiguous_ = Utils::Maximum(max_contiguous_.load(), elapsed);
43 // Make increment atomic in case it occurs in parallel with aggregation.
44 total_.fetch_add(elapsed);
45 running_ = false;
46 }
47
48 // Get total cumulative elapsed time in micros.
49 int64_t TotalElapsedTime() const {
50 int64_t result = total_;
51 if (running_) {
52 int64_t now = Measure::Now();
53 result += (now - start_);
54 }
55 return result;
56 }
57
58 int64_t MaxContiguous() const {
59 int64_t result = max_contiguous_;
60 if (running_) {
61 int64_t now = Measure::Now();
62 result = Utils::Maximum(result, now - start_);
63 }
64 return result;
65 }
66
67 void Reset() {
68 start_ = 0;
69 stop_ = 0;
70 total_ = 0;
71 max_contiguous_ = 0;
72 running_ = false;
73 }
74
75 bool IsReset() const {
76 return (start_ == 0) && (stop_ == 0) && (total_ == 0) &&
77 (max_contiguous_ == 0) && !running_;
78 }
79
80 void AddTotal(const TimerImpl& other) { total_.fetch_add(other.total_); }
81
82 // Accessors.
83 bool running() const { return running_; }
84
85 private:
86 friend class Timer;
87
88 explicit TimerImpl(int64_t elapsed)
89 : total_(elapsed), max_contiguous_(elapsed) {}
90
91 int64_t ElapsedMicros() const { return stop_ - start_; }
92
93 RelaxedAtomic<int64_t> start_;
94 RelaxedAtomic<int64_t> stop_;
95 RelaxedAtomic<int64_t> total_;
96 RelaxedAtomic<int64_t> max_contiguous_;
97
98 bool running_ = false;
99
101};
102
103class Timer : public ValueObject {
104 public:
105 Timer(int64_t elapsed, int64_t elapsed_cpu)
106 : monotonic_(elapsed), cpu_(elapsed) {}
107 Timer() { Reset(); }
109
110 // Start timer.
111 void Start() {
112 cpu_.Start();
113 monotonic_.Start();
114 }
115
116 // Stop timer.
117 void Stop() {
118 cpu_.Stop();
119 monotonic_.Stop();
120 }
121
122 // Get total cumulative elapsed time in micros.
123 int64_t TotalElapsedTime() const { return monotonic_.TotalElapsedTime(); }
124 int64_t TotalElapsedTimeCpu() const { return cpu_.TotalElapsedTime(); }
125
126 int64_t MaxContiguous() const { return monotonic_.MaxContiguous(); }
127
128 void Reset() {
129 monotonic_.Reset();
130 cpu_.Reset();
131 }
132
133 bool IsReset() const { return monotonic_.IsReset(); }
134
135 void AddTotal(const Timer& other) {
136 monotonic_.AddTotal(other.monotonic_);
137 cpu_.AddTotal(other.cpu_);
138 }
139
140 const char* FormatElapsedHumanReadable(Zone* zone) const {
143 }
144
145 static const char* FormatTime(Zone* zone, int64_t total) {
146 if (total > kMicrosecondsPerSecond) {
147 return OS::SCreate(zone, "%6.2f s", MicrosecondsToSeconds(total));
148 } else if (total > kMicrosecondsPerMillisecond) {
149 return OS::SCreate(zone, "%6.2f ms", MicrosecondsToMilliseconds(total));
150 } else {
151 return OS::SCreate(zone, "%6" Pd64 " \u00B5s", total);
152 }
153 }
154
155 static constexpr double kCpuTimeReportingThreshold = 0.05;
156
157 // Formats the given monotonic and CPU times as a human readable string.
158 //
159 // CPU time is included into the formated string only if
160 // it is |kCpuTimeReportingThreshold| percent different from the monotonic
161 // time.
162 static const char* FormatElapsedHumanReadable(Zone* zone,
163 int64_t total_elapsed,
164 int64_t total_elapsed_cpu) {
165 if ((total_elapsed == 0) ||
166 static_cast<double>(Utils::Abs(total_elapsed - total_elapsed_cpu) /
167 total_elapsed) < kCpuTimeReportingThreshold) {
168 return FormatTime(zone, total_elapsed);
169 } else {
170 return OS::SCreate(zone, "%s (cpu %s)", FormatTime(zone, total_elapsed),
171 FormatTime(zone, total_elapsed_cpu));
172 }
173 }
174
175 private:
178
179 DISALLOW_COPY_AND_ASSIGN(Timer);
180};
181
182class TimerScope : public StackResource {
183 public:
185 : StackResource(thread), timer_(timer) {
186 if (timer_ != nullptr) timer_->Start();
187 }
189 if (timer_ != nullptr) timer_->Stop();
190 }
191
192 private:
193 Timer* const timer_;
194};
195
197 public:
198 explicit PrintTimeScope(const char* name) : name_(name) { timer_.Start(); }
200
201 private:
202 Timer timer_;
203 const char* name_;
204};
205
206} // namespace dart
207
208#endif // RUNTIME_VM_TIMER_H_
static int64_t GetCurrentMonotonicMicros()
static int64_t GetCurrentThreadCPUMicros()
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
PrintTimeScope(const char *name)
Definition: timer.h:198
T load(std::memory_order order=std::memory_order_relaxed) const
Definition: atomic.h:21
T fetch_add(T arg, std::memory_order order=std::memory_order_relaxed)
Definition: atomic.h:35
ThreadState * thread() const
Definition: allocation.h:33
bool IsReset() const
Definition: timer.h:75
bool running() const
Definition: timer.h:83
int64_t MaxContiguous() const
Definition: timer.h:58
void Reset()
Definition: timer.h:67
int64_t TotalElapsedTime() const
Definition: timer.h:49
void AddTotal(const TimerImpl &other)
Definition: timer.h:80
void Stop()
Definition: timer.h:38
void Start()
Definition: timer.h:32
TimerScope(ThreadState *thread, Timer *timer)
Definition: timer.h:184
const char * FormatElapsedHumanReadable(Zone *zone) const
Definition: timer.h:140
static const char * FormatElapsedHumanReadable(Zone *zone, int64_t total_elapsed, int64_t total_elapsed_cpu)
Definition: timer.h:162
static const char * FormatTime(Zone *zone, int64_t total)
Definition: timer.h:145
void AddTotal(const Timer &other)
Definition: timer.h:135
~Timer()
Definition: timer.h:108
void Stop()
Definition: timer.h:117
bool IsReset() const
Definition: timer.h:133
int64_t MaxContiguous() const
Definition: timer.h:126
void Reset()
Definition: timer.h:128
int64_t TotalElapsedTimeCpu() const
Definition: timer.h:124
static constexpr double kCpuTimeReportingThreshold
Definition: timer.h:155
void Start()
Definition: timer.h:111
int64_t TotalElapsedTime() const
Definition: timer.h:123
Timer(int64_t elapsed, int64_t elapsed_cpu)
Definition: timer.h:105
static T Abs(T x)
Definition: utils.h:49
static constexpr T Maximum(T x, T y)
Definition: utils.h:41
#define ASSERT(E)
GAsyncResult * result
Definition: dart_vm.cc:33
constexpr intptr_t kMicrosecondsPerMillisecond
Definition: globals.h:561
const char *const name
constexpr double MicrosecondsToSeconds(int64_t micros)
Definition: globals.h:571
constexpr intptr_t kMicrosecondsPerSecond
Definition: globals.h:562
constexpr double MicrosecondsToMilliseconds(int64_t micros)
Definition: globals.h:574
#define Pd64
Definition: globals.h:416
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
static int64_t Now()
Definition: timer.h:21
static int64_t Now()
Definition: timer.h:17