1// Copyright (c) 2015, 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_TIMELINE_ANALYSIS_H_
6#define RUNTIME_VM_TIMELINE_ANALYSIS_H_
7
8#include "vm/growable_array.h"
9#include "vm/timeline.h"
10
11namespace dart {
12
13class TimelineAnalysisThread : public ZoneAllocated {
14 public:
15 explicit TimelineAnalysisThread(ThreadId id);
16 ~TimelineAnalysisThread();
17
18 ThreadId id() const { return id_; }
19
20 intptr_t NumBlocks() const { return blocks_.length(); }
21
22 TimelineEventBlock* At(intptr_t i) const { return blocks_.At(i); }
23
24 private:
25 void AddBlock(TimelineEventBlock* block);
26 void Finalize();
27
28 const ThreadId id_;
29 ZoneGrowableArray<TimelineEventBlock*> blocks_;
30
31 friend class TimelineAnalysis;
32};
33
34class TimelineAnalysisThreadEventIterator : public ValueObject {
35 public:
36 explicit TimelineAnalysisThreadEventIterator(TimelineAnalysisThread* thread);
37 ~TimelineAnalysisThreadEventIterator();
38
39 void Reset(TimelineAnalysisThread* thread);
40
41 bool HasNext() const;
42
43 TimelineEvent* Next();
44
45 private:
46 TimelineAnalysisThread* thread_;
47 TimelineEvent* current_;
48 intptr_t block_cursor_;
49 intptr_t event_cursor_;
50};
51
52// Base of all timeline analysis classes. Base functionality:
53// - discovery of all thread ids in a recording.
54// - collecting all ThreadEventBlocks by thread id.
55class TimelineAnalysis : public ValueObject {
56 public:
57 TimelineAnalysis(Zone* zone,
58 Isolate* isolate,
59 TimelineEventRecorder* recorder);
60 ~TimelineAnalysis();
61
62 void BuildThreads();
63
64 intptr_t NumThreads() const { return threads_.length(); }
65
66 TimelineAnalysisThread* At(intptr_t i) const { return threads_[i]; }
67
68 TimelineAnalysisThread* GetThread(ThreadId tid);
69
70 bool has_error() const { return has_error_; }
71
72 const char* error_msg() const { return error_msg_; }
73
74 protected:
75 TimelineAnalysisThread* GetOrAddThread(ThreadId tid);
76
77 void DiscoverThreads();
78 void FinalizeThreads();
79
80 void SetError(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
81
82 Zone* zone_;
83 Isolate* isolate_;
84 TimelineEventRecorder* recorder_;
85 bool has_error_;
86 const char* error_msg_;
87
88 ZoneGrowableArray<TimelineAnalysisThread*> threads_;
89};
90
91class TimelineLabelPauseInfo : public ZoneAllocated {
92 public:
93 explicit TimelineLabelPauseInfo(const char* name);
94
95 const char* name() const { return name_; }
96
97 int64_t inclusive_micros() const { return inclusive_micros_; }
98
99 int64_t exclusive_micros() const { return exclusive_micros_; }
100
101 int64_t max_inclusive_micros() const { return max_inclusive_micros_; }
102
103 int64_t max_exclusive_micros() const { return max_exclusive_micros_; }
104
105 private:
106 // Adjusts |inclusive_micros_| and |exclusive_micros_| by |micros|.
107 // Also, may adjust, max_inclusive_micros_.
108 void OnPush(int64_t micros, bool already_on_stack);
109
110 // Adjusts |exclusive_micros_| by |exclusive_micros|.
111 // Also, may adjust |max_exclusive_micros_|.
112 void OnPop(int64_t exclusive_micros);
113
114 // Adjusts |inclusive_micros_| and |exclusive_micros_| by |micros|.
115 // Also, may adjust, |max_inclusive_micros_|.
116 void OnBeginPop(int64_t inclusive_micros,
117 int64_t exclusive_micros,
118 bool already_on_stack);
119
120 void UpdateInclusiveMicros(int64_t inclusive_micros, bool already_on_stack);
121 void UpdateExclusiveMicros(int64_t exclusive_micros);
122
123 // Adjust inclusive micros.
124 void add_inclusive_micros(int64_t delta_micros) {
125 inclusive_micros_ += delta_micros;
126 ASSERT(inclusive_micros_ >= 0);
127 }
128
129 // Adjust exclusive micros.
130 void add_exclusive_micros(int64_t delta_micros) {
131 exclusive_micros_ += delta_micros;
132 ASSERT(exclusive_micros_ >= 0);
133 }
134
135 void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
136
137 const char* name_;
138 int64_t inclusive_micros_;
139 int64_t exclusive_micros_;
140 int64_t max_inclusive_micros_;
141 int64_t max_exclusive_micros_;
142
143 friend class TimelinePauses;
144 friend class TimelinePauseTrace;
145};
146
147class TimelinePauses : public TimelineAnalysis {
148 public:
149 TimelinePauses(Zone* zone, Isolate* isolate, TimelineEventRecorder* recorder);
150
151 void Setup();
152
153 void CalculatePauseTimesForThread(ThreadId tid);
154
155 TimelineLabelPauseInfo* GetLabelPauseInfo(const char* name) const;
156
157 int64_t InclusiveTime(const char* name) const;
158 int64_t ExclusiveTime(const char* name) const;
159 int64_t MaxInclusiveTime(const char* name) const;
160 int64_t MaxExclusiveTime(const char* name) const;
161
162 intptr_t NumPauseInfos() const { return labels_.length(); }
163
164 const TimelineLabelPauseInfo* PauseInfoAt(intptr_t i) const {
165 return labels_.At(i);
166 }
167
168 private:
169 struct StackItem {
170 TimelineEvent* event;
171 TimelineLabelPauseInfo* pause_info;
172 int64_t exclusive_micros;
173 };
174
175 void ProcessThread(TimelineAnalysisThread* thread);
176 bool CheckStack(TimelineEvent* event);
177 void PopFinishedDurations(int64_t start);
178 void PopBegin(const char* label, int64_t end);
179 void Push(TimelineEvent* event);
180 bool IsLabelOnStack(const char* label) const;
181 intptr_t StackDepth() const;
182 StackItem& GetStackTop();
183 TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
184
185 ZoneGrowableArray<StackItem> stack_;
186 ZoneGrowableArray<TimelineLabelPauseInfo*> labels_;
187};
188
189class TimelinePauseTrace : public ValueObject {
190 public:
191 TimelinePauseTrace();
192 ~TimelinePauseTrace();
193
194 void Print();
195
196 private:
197 TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
198 void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
199 void PrintPauseInfo(const TimelineLabelPauseInfo* pause_info);
200
201 ZoneGrowableArray<TimelineLabelPauseInfo*> isolate_labels_;
202};
203
204} // namespace dart
205
206#endif // RUNTIME_VM_TIMELINE_ANALYSIS_H_
207