Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
timeline.h
Go to the documentation of this file.
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_H_
6#define RUNTIME_VM_TIMELINE_H_
7
8#include <functional>
9#include <memory>
10
12
13#include "platform/assert.h"
14#include "platform/atomic.h"
15#include "platform/hashmap.h"
16#include "vm/allocation.h"
17#include "vm/bitfield.h"
18#include "vm/globals.h"
19#include "vm/growable_array.h"
20#include "vm/os.h"
21#include "vm/os_thread.h"
22
23#if defined(SUPPORT_TIMELINE) && defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
24#include "perfetto/protozero/scattered_heap_buffer.h"
26#endif // defined(SUPPORT_TIMELINE) && defined(SUPPORT_PERFETTO) && \
27 // !defined(PRODUCT)
28
29#if defined(FUCHSIA_SDK) || defined(DART_HOST_OS_FUCHSIA)
30#include <lib/trace-engine/context.h>
31#include <lib/trace-engine/instrumentation.h>
32#elif defined(DART_HOST_OS_MACOS)
33#include <os/signpost.h>
34#endif // defined(FUCHSIA_SDK) || defined(DART_HOST_OS_FUCHSIA)
35
36namespace dart {
37
38#if !defined(SUPPORT_TIMELINE)
39#define TIMELINE_DURATION(thread, stream, name)
40#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function)
41#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
42#endif // !defined(SUPPORT_TIMELINE)
43
44class JSONArray;
45class JSONBase64String;
46class JSONObject;
47class JSONStream;
48class JSONWriter;
49class Object;
50class ObjectPointerVisitor;
51class Isolate;
52class Thread;
53class TimelineEvent;
54class TimelineEventBlock;
55class TimelineEventRecorder;
56class TimelineStream;
57class VirtualMemory;
58class Zone;
59
60#if defined(SUPPORT_TIMELINE)
61#define CALLBACK_RECORDER_NAME "Callback"
62#define ENDLESS_RECORDER_NAME "Endless"
63#define FILE_RECORDER_NAME "File"
64#define FUCHSIA_RECORDER_NAME "Fuchsia"
65#define MACOS_RECORDER_NAME "Macos"
66#define PERFETTO_FILE_RECORDER_NAME "Perfettofile"
67#define RING_RECORDER_NAME "Ring"
68#define STARTUP_RECORDER_NAME "Startup"
69#define SYSTRACE_RECORDER_NAME "Systrace"
70
71// (name, fuchsia_name, has_static_labels).
72#define TIMELINE_STREAM_LIST(V) \
73 V(API, "dart:api", true) \
74 V(Compiler, "dart:compiler", true) \
75 V(CompilerVerbose, "dart:compiler.verbose", true) \
76 V(Dart, "dart:dart", false) \
77 V(Debugger, "dart:debugger", true) \
78 V(Embedder, "dart:embedder", true) \
79 V(GC, "dart:gc", true) \
80 V(Isolate, "dart:isolate", true) \
81 V(VM, "dart:vm", true)
82#endif // defined(SUPPORT_TIMELINE)
83
84// A stream of timeline events. A stream has a name and can be enabled or
85// disabled (globally and per isolate).
87 public:
88 TimelineStream(const char* name,
89 const char* fuchsia_name,
90 bool static_labels,
91 bool enabled);
92
93 const char* name() const { return name_; }
94 const char* fuchsia_name() const { return fuchsia_name_; }
95
96 bool enabled() {
97#if defined(DART_HOST_OS_FUCHSIA)
98#ifdef PRODUCT
99 return trace_is_category_enabled(fuchsia_name_);
100#else
101 return trace_is_category_enabled(fuchsia_name_) || enabled_ != 0;
102#endif // PRODUCT
103#else
104 return enabled_ != 0;
105#endif // defined(DART_HOST_OS_FUCHSIA)
106 }
107
108 void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; }
109
110 // Records an event. Will return |nullptr| if not enabled. The returned
111 // |TimelineEvent| is in an undefined state and must be initialized.
112 TimelineEvent* StartEvent();
113
114 static intptr_t enabled_offset() {
115 return OFFSET_OF(TimelineStream, enabled_);
116 }
117
118#if defined(DART_HOST_OS_FUCHSIA)
119 trace_site_t* trace_site() { return &trace_site_; }
120#elif defined(DART_HOST_OS_MACOS)
121 os_log_t macos_log() const { return macos_log_; }
122 bool has_static_labels() const { return has_static_labels_; }
123#endif
124
125 private:
126 const char* const name_;
127 const char* const fuchsia_name_;
128
129 // This field is accessed by generated code (intrinsic) and expects to see
130 // 0 or 1. If this becomes a BitField, the generated code must be updated.
131 uintptr_t enabled_;
132
133#if defined(DART_HOST_OS_FUCHSIA)
134 trace_site_t trace_site_ = {};
135#elif defined(DART_HOST_OS_MACOS)
136 os_log_t macos_log_ = {};
137 bool has_static_labels_ = false;
138#endif
139};
140
141#if defined(SUPPORT_TIMELINE)
142class RecorderSynchronizationLock : public AllStatic {
143 public:
144 static void Init() {
145 recorder_state_.store(kActive, std::memory_order_release);
146 outstanding_event_writes_.store(0);
147 }
148
149 static void EnterLock() {
150 outstanding_event_writes_.fetch_add(1, std::memory_order_acquire);
151 }
152
153 static void ExitLock() {
154 intptr_t count =
155 outstanding_event_writes_.fetch_sub(1, std::memory_order_release);
156 ASSERT(count >= 0);
157 }
158
159 static bool IsUninitialized() {
160 return (recorder_state_.load(std::memory_order_acquire) == kUninitialized);
161 }
162
163 static bool IsActive() {
164 return (recorder_state_.load(std::memory_order_acquire) == kActive);
165 }
166
167 static bool IsShuttingDown() {
168 return (recorder_state_.load(std::memory_order_acquire) == kShuttingDown);
169 }
170
171 static void WaitForShutdown() {
172 recorder_state_.store(kShuttingDown, std::memory_order_release);
173 // Spin waiting for outstanding events to be completed.
174 while (outstanding_event_writes_.load(std::memory_order_relaxed) > 0) {
175 }
176 }
177
178 private:
179 typedef enum { kUninitialized = 0, kActive, kShuttingDown } RecorderState;
180 static std::atomic<RecorderState> recorder_state_;
181 static std::atomic<intptr_t> outstanding_event_writes_;
182
183 DISALLOW_COPY_AND_ASSIGN(RecorderSynchronizationLock);
184};
185
186// Any modifications to the timeline must be guarded by a
187// |RecorderSynchronizationLockScope| to prevent the timeline from being
188// cleaned up in the middle of the modifications.
189class RecorderSynchronizationLockScope {
190 public:
191 RecorderSynchronizationLockScope() {
192 RecorderSynchronizationLock::EnterLock();
193 }
194
195 ~RecorderSynchronizationLockScope() {
196 RecorderSynchronizationLock::ExitLock();
197 }
198
199 bool IsUninitialized() const {
200 return RecorderSynchronizationLock::IsUninitialized();
201 }
202
203 bool IsActive() const { return RecorderSynchronizationLock::IsActive(); }
204
205 bool IsShuttingDown() const {
206 return RecorderSynchronizationLock::IsShuttingDown();
207 }
208
209 private:
210 DISALLOW_COPY_AND_ASSIGN(RecorderSynchronizationLockScope);
211};
212
213class Timeline : public AllStatic {
214 public:
215 // Initialize timeline system. Not thread safe.
216 static void Init();
217
218 // Cleanup timeline system. Not thread safe.
219 static void Cleanup();
220
221 // Access the global recorder. Not thread safe.
222 static TimelineEventRecorder* recorder() { return recorder_; }
223
224 static bool recorder_discards_clock_values() {
225 return recorder_discards_clock_values_;
226 }
227 static void set_recorder_discards_clock_values(bool value) {
228 recorder_discards_clock_values_ = value;
229 }
230
231 static Dart_TimelineRecorderCallback callback() { return callback_; }
232 static void set_callback(Dart_TimelineRecorderCallback callback) {
233 callback_ = callback;
234 }
235
236 // Reclaim all |TimelineEventBlocks|s that are cached by threads.
237 static void ReclaimCachedBlocksFromThreads();
238
239 static void Clear();
240
241#ifndef PRODUCT
242 // Print information about streams to JSON.
243 static void PrintFlagsToJSON(JSONStream* json);
244
245 // Output the recorded streams to a JSONS array.
246 static void PrintFlagsToJSONArray(JSONArray* arr);
247#endif
248
249#define TIMELINE_STREAM_ACCESSOR(name, ...) \
250 static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
251 TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
252#undef TIMELINE_STREAM_ACCESSOR
253
254#define TIMELINE_STREAM_FLAGS(name, ...) \
255 static void SetStream##name##Enabled(bool enabled) { \
256 stream_##name##_.set_enabled(enabled); \
257 }
258 TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAGS)
259#undef TIMELINE_STREAM_FLAGS
260
261 private:
262 static TimelineEventRecorder* recorder_;
263 static Dart_TimelineRecorderCallback callback_;
264 static MallocGrowableArray<char*>* enabled_streams_;
265 static bool recorder_discards_clock_values_;
266
267#define TIMELINE_STREAM_DECLARE(name, ...) \
268 static TimelineStream stream_##name##_;
269 TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
270#undef TIMELINE_STREAM_DECLARE
271
272 template <class>
273 friend class TimelineRecorderOverride;
274 friend class ReclaimBlocksIsolateVisitor;
275};
276
277struct TimelineEventArgument {
278 const char* name;
279 char* value;
280};
281
282class TimelineEventArguments {
283 public:
284 TimelineEventArguments() : buffer_(nullptr), length_(0) {}
285 ~TimelineEventArguments() { Free(); }
286 // Get/Set the number of arguments in the event.
287 void SetNumArguments(intptr_t length);
288 // |name| must be a compile time constant. Takes ownership of |argument|.
289 void SetArgument(intptr_t i, const char* name, char* argument);
290 // |name| must be a compile time constant. Copies |argument|.
291 void CopyArgument(intptr_t i, const char* name, const char* argument);
292 // |name| must be a compile time constant. Takes ownership of |args|
293 void FormatArgument(intptr_t i,
294 const char* name,
295 const char* fmt,
296 va_list args);
297
298 void StealArguments(TimelineEventArguments* arguments);
299
300 TimelineEventArgument* buffer() const { return buffer_; }
301
302 intptr_t length() const { return length_; }
303
304 void Free();
305
306 TimelineEventArgument& operator[](intptr_t index) const {
307 return buffer_[index];
308 }
309
310 bool IsEmpty() { return length_ == 0; }
311
312 bool IsNotEmpty() { return length_ != 0; }
313
314 private:
315 TimelineEventArgument* buffer_;
316 intptr_t length_;
317 DISALLOW_COPY_AND_ASSIGN(TimelineEventArguments);
318};
319
320// You should get a |TimelineEvent| from a |TimelineStream|.
321class TimelineEvent {
322 public:
323 // Keep in sync with StateBits below.
324 // Keep in sync with constants in sdk/lib/developer/timeline.dart.
325 enum EventType {
326 kNone = 0,
327 kBegin = 1,
328 kEnd = 2,
329 kDuration = 3,
330 kInstant = 4,
331 kAsyncBegin = 5,
332 kAsyncInstant = 6,
333 kAsyncEnd = 7,
334 kCounter = 8,
335 kFlowBegin = 9,
336 kFlowStep = 10,
337 kFlowEnd = 11,
338 kMetadata = 12,
339 kNumEventTypes,
340 };
341
342 // This value must be kept in sync with the value of _noFlowId in
343 // sdk/lib/developer/timeline.dart.
344 static const int64_t kNoFlowId = -1;
345
346 TimelineEvent();
347 ~TimelineEvent();
348
349 void Reset();
350
351 bool IsValid() const {
352 return (event_type() > kNone) && (event_type() < kNumEventTypes);
353 }
354
355 // Marks the beginning of an asynchronous operation with |async_id|.
356 void AsyncBegin(const char* label,
357 int64_t async_id,
358 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
359 // Marks an instantaneous event associated with |async_id|.
360 void AsyncInstant(
361 const char* label,
362 int64_t async_id,
363 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
364 // Marks the end of an asynchronous operation associated with |async_id|.
365 void AsyncEnd(const char* label,
366 int64_t async_id,
367 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
368
369 void DurationBegin(
370 const char* label,
371 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
372
373 void Instant(const char* label,
374 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
375
376 void Duration(const char* label, int64_t start_micros, int64_t end_micros);
377
378 void Begin(const char* label,
379 int64_t id,
380 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
381
382 void End(const char* label,
383 int64_t id,
384 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
385
386 void Counter(const char* label,
387 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
388
389 void FlowBegin(const char* label,
390 int64_t id,
391 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
392 void FlowStep(const char* label,
393 int64_t id,
394 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
395 void FlowEnd(const char* label,
396 int64_t id,
397 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
398
399 void Metadata(const char* label,
400 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
401
402 void CompleteWithPreSerializedArgs(char* args_json);
403
404 // Get/Set the number of arguments in the event.
405 intptr_t GetNumArguments() const { return arguments_.length(); }
406 void SetNumArguments(intptr_t length) { arguments_.SetNumArguments(length); }
407 // |name| must be a compile time constant. Takes ownership of |argument|.
408 void SetArgument(intptr_t i, const char* name, char* argument) {
409 arguments_.SetArgument(i, name, argument);
410 }
411 // |name| must be a compile time constant. Copies |argument|.
412 void CopyArgument(intptr_t i, const char* name, const char* argument) {
413 arguments_.CopyArgument(i, name, argument);
414 }
415 // |name| must be a compile time constant.
416 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...)
417 PRINTF_ATTRIBUTE(4, 5);
418
419 void StealArguments(TimelineEventArguments* arguments) {
420 arguments_.StealArguments(arguments);
421 }
422 // Mandatory to call when this event is completely filled out.
423 void Complete();
424
425 EventType event_type() const { return EventTypeField::decode(state_); }
426
427 TimelineStream* stream() const { return stream_; }
428
429 int64_t TimeOrigin() const { return timestamp0_; }
430 int64_t Id() const {
431 ASSERT(event_type() != kDuration && event_type() != kInstant &&
432 event_type() != kCounter);
433 return timestamp1_or_id_;
434 }
435 int64_t TimeDuration() const;
436 void SetTimeEnd(int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline()) {
437 ASSERT(event_type() == kDuration);
438 ASSERT(timestamp1_or_id_ == 0);
439 set_timestamp1_or_id(micros);
440 }
441 int64_t TimeEnd() const {
442 ASSERT(IsFinishedDuration());
443 return timestamp1_or_id_;
444 }
445
446 int64_t timestamp0() const { return timestamp0_; }
447 int64_t timestamp1_or_id() const { return timestamp1_or_id_; }
448
449 void SetFlowIds(intptr_t flow_id_count,
450 std::unique_ptr<const int64_t[]>& flow_ids) {
451 flow_id_count_ = flow_id_count;
452 flow_ids_.swap(flow_ids);
453 }
454 intptr_t flow_id_count() const { return flow_id_count_; }
455 const int64_t* FlowIds() const { return flow_ids_.get(); }
456
457 bool HasIsolateId() const;
458 bool HasIsolateGroupId() const;
459 std::unique_ptr<const char[]> GetFormattedIsolateId() const;
460 std::unique_ptr<const char[]> GetFormattedIsolateGroupId() const;
461
462 // The lowest time value stored in this event.
463 int64_t LowTime() const;
464 // The highest time value stored in this event.
465 int64_t HighTime() const;
466
467#ifndef PRODUCT
468 void PrintJSON(JSONStream* stream) const;
469#endif
470 void PrintJSON(JSONWriter* writer) const;
471#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
472 bool CanBeRepresentedByPerfettoTracePacket() const;
473 /*
474 * Populates the fields of |packet| with this event's data.
475 */
476 void PopulateTracePacket(perfetto::protos::pbzero::TracePacket* packet) const;
477#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
478
479 ThreadId thread() const { return thread_; }
480
481 void set_thread(ThreadId tid) { thread_ = tid; }
482
483 Dart_Port isolate_id() const { return isolate_id_; }
484
485 uint64_t isolate_group_id() const { return isolate_group_id_; }
486
487 void* isolate_data() const { return isolate_data_; }
488
489 void* isolate_group_data() const { return isolate_group_data_; }
490
491 const char* label() const { return label_; }
492
493 // Does this duration end before |micros| ?
494 bool DurationFinishedBefore(int64_t micros) const {
495 return TimeEnd() <= micros;
496 }
497
498 bool IsDuration() const { return (event_type() == kDuration); }
499
500 bool IsBegin() const { return (event_type() == kBegin); }
501
502 bool IsEnd() const { return (event_type() == kEnd); }
503
504 // Is this event a synchronous begin or end event?
505 bool IsBeginOrEnd() const { return IsBegin() || IsEnd(); }
506
507 // Does this duration fully contain |other| ?
508 bool DurationContains(TimelineEvent* other) const {
509 ASSERT(IsFinishedDuration());
510 if (other->IsBegin()) {
511 if (other->TimeOrigin() < TimeOrigin()) {
512 return false;
513 }
514 if (other->TimeOrigin() > TimeEnd()) {
515 return false;
516 }
517 return true;
518 } else {
519 ASSERT(other->IsFinishedDuration());
520 if (other->TimeOrigin() < TimeOrigin()) {
521 return false;
522 }
523 if (other->TimeEnd() < TimeOrigin()) {
524 return false;
525 }
526 if (other->TimeOrigin() > TimeEnd()) {
527 return false;
528 }
529 if (other->TimeEnd() > TimeEnd()) {
530 return false;
531 }
532 return true;
533 }
534 }
535
536 bool Within(int64_t time_origin_micros, int64_t time_extent_micros);
537
538 void set_owns_label(bool owns_label) {
539 state_ = OwnsLabelBit::update(owns_label, state_);
540 }
541
542 TimelineEventArgument* arguments() const { return arguments_.buffer(); }
543
544 intptr_t arguments_length() const { return arguments_.length(); }
545
546 bool ArgsArePreSerialized() const {
547 return PreSerializedArgsBit::decode(state_);
548 }
549
550 TimelineEvent* next() const { return next_; }
551 void set_next(TimelineEvent* next) { next_ = next; }
552
553 private:
554 void StreamInit(TimelineStream* stream) { stream_ = stream; }
555 void Init(EventType event_type, const char* label);
556
557 void set_event_type(EventType event_type) {
558 // We only reserve 4 bits to hold the event type.
559 COMPILE_ASSERT(kNumEventTypes < 16);
560 state_ = EventTypeField::update(event_type, state_);
561 }
562
563 void set_timestamp0(int64_t value) {
564 ASSERT(timestamp0_ == 0);
565 timestamp0_ = value;
566 }
567 void set_timestamp1_or_id(int64_t value) {
568 ASSERT(timestamp1_or_id_ == 0);
569 timestamp1_or_id_ = value;
570 }
571
572 bool IsFinishedDuration() const {
573 return (event_type() == kDuration) && (timestamp1_or_id_ > timestamp0_);
574 }
575
576 void set_pre_serialized_args(bool pre_serialized_args) {
577 state_ = PreSerializedArgsBit::update(pre_serialized_args, state_);
578 }
579
580 bool owns_label() const { return OwnsLabelBit::decode(state_); }
581
582 enum StateBits {
583 kEventTypeBit = 0, // reserve 4 bits for type.
584 kPreSerializedArgsBit = 4,
585 kOwnsLabelBit = 5,
586 kNextBit = 6,
587 };
588
589 class EventTypeField : public BitField<uword, EventType, kEventTypeBit, 4> {};
590 class PreSerializedArgsBit
591 : public BitField<uword, bool, kPreSerializedArgsBit, 1> {};
592 class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {};
593
594 int64_t timestamp0_;
595 // For an event of type |kDuration|, this is the end time. For an event of
596 // type |kFlowBegin|, |kFlowStep|, or |kFlowEnd| this is the flow ID. For an
597 // event of type |kBegin| or |kEnd|, this is the event ID (which is only
598 // referenced by the MacOS recorder). For an async event, this is the async
599 // ID.
600 int64_t timestamp1_or_id_;
601 intptr_t flow_id_count_;
602 // This field is needed to support trace serialization in Perfetto's proto
603 // format. Flow IDs must be associated with |TimelineEvent::kBegin|,
604 // |TimelineEvent::kDuration|, |TimelineEvent::kInstant|,
605 // |TimelineEvent::kAsyncBegin|, and |TimelineEvent::kAsyncInstant| events to
606 // serialize traces in Perfetto's format. Flow event information is serialized
607 // in Chrome's JSON trace format through events of type
608 // |TimelineEvent::kFlowBegin|, |TimelineEvent::kFlowStep|, and
609 // |TimelineEvent::kFlowEnd|.
610 std::unique_ptr<const int64_t[]> flow_ids_;
611 TimelineEventArguments arguments_;
612 uword state_;
613 const char* label_;
614 TimelineStream* stream_;
615 ThreadId thread_;
616 Dart_Port isolate_id_;
617 uint64_t isolate_group_id_;
618 void* isolate_data_;
619 void* isolate_group_data_;
620 TimelineEvent* next_;
621
622 friend class TimelineEventRecorder;
623 friend class TimelineEventEndlessRecorder;
624 friend class TimelineEventRingRecorder;
625 friend class TimelineEventStartupRecorder;
626 friend class TimelineEventPlatformRecorder;
627 friend class TimelineEventFuchsiaRecorder;
628 friend class TimelineEventMacosRecorder;
629#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
630 friend class TimelineEventPerfettoFileRecorder;
631#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
632 friend class TimelineStream;
633 friend class TimelineTestHelper;
634 DISALLOW_COPY_AND_ASSIGN(TimelineEvent);
635};
636
637class TimelineTrackMetadata {
638 public:
639 TimelineTrackMetadata(intptr_t pid,
640 intptr_t tid,
641 Utils::CStringUniquePtr&& track_name);
642 intptr_t pid() const { return pid_; }
643 intptr_t tid() const { return tid_; }
644 const char* track_name() const { return track_name_.get(); }
645 inline void set_track_name(Utils::CStringUniquePtr&& track_name);
646#if !defined(PRODUCT)
647 /*
648 * Prints a Chrome-format event representing the metadata stored by this
649 * object into |jsarr_events|.
650 */
651 void PrintJSON(const JSONArray& jsarr_events) const;
652#if defined(SUPPORT_PERFETTO)
653 /*
654 * Populates the fields of |track_descriptor_packet| with the metadata stored
655 * by this object.
656 */
657 void PopulateTracePacket(
658 perfetto::protos::pbzero::TracePacket* track_descriptor_packet) const;
659#endif // defined(SUPPORT_PERFETTO)
660#endif // !defined(PRODUCT)
661
662 private:
663 // The ID of the process that this track is associated with.
664 intptr_t pid_;
665 // The trace ID of the thread that this track is associated with.
666 intptr_t tid_;
667 // The name of this track.
668 Utils::CStringUniquePtr track_name_;
669};
670
671class AsyncTimelineTrackMetadata {
672 public:
673 AsyncTimelineTrackMetadata(intptr_t pid, intptr_t async_id);
674 intptr_t pid() const { return pid_; }
675 intptr_t async_id() const { return async_id_; }
676#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
677 /*
678 * Populates the fields of |track_descriptor_packet| with the metadata stored
679 * by this object.
680 */
681 void PopulateTracePacket(
682 perfetto::protos::pbzero::TracePacket* track_descriptor_packet) const;
683#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
684
685 private:
686 // The ID of the process that this track is associated with.
687 intptr_t pid_;
688 // The async ID that this track is associated with.
689 intptr_t async_id_;
690};
691
692#define TIMELINE_DURATION(thread, stream, name) \
693 TimelineBeginEndScope tbes(thread, Timeline::Get##stream##Stream(), name);
694#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) \
695 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(), name); \
696 if (tbes.enabled()) { \
697 tbes.SetNumArguments(1); \
698 tbes.CopyArgument(0, "function", function.ToQualifiedCString()); \
699 }
700
701#define TIMELINE_FUNCTION_GC_DURATION(thread, name) \
702 TimelineBeginEndScope tbes(thread, Timeline::GetGCStream(), name);
703
704// See |TimelineBeginEndScope|.
705class TimelineEventScope : public StackResource {
706 public:
707 bool enabled() const { return enabled_; }
708
709 intptr_t GetNumArguments() { return arguments_.length(); }
710 void SetNumArguments(intptr_t length);
711
712 void SetArgument(intptr_t i, const char* name, char* argument);
713
714 void CopyArgument(intptr_t i, const char* name, const char* argument);
715
716 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...)
717 PRINTF_ATTRIBUTE(4, 5);
718
719 protected:
720 TimelineEventScope(TimelineStream* stream, const char* label);
721
722 TimelineEventScope(Thread* thread, TimelineStream* stream, const char* label);
723
724 bool ShouldEmitEvent() const { return enabled_; }
725
726 void set_enabled(bool enabled) { enabled_ = enabled; }
727
728 const char* label() const { return label_; }
729
730 int64_t id() const { return id_; }
731
732 TimelineEventArgument* arguments() const { return arguments_.buffer(); }
733
734 intptr_t arguments_length() const { return arguments_.length(); }
735
736 TimelineStream* stream() const { return stream_; }
737
738 virtual ~TimelineEventScope();
739
740 void StealArguments(TimelineEvent* event);
741
742 private:
743 void Init();
744
745 TimelineStream* stream_;
746 const char* label_;
747 int64_t id_;
748 TimelineEventArguments arguments_;
749 bool enabled_;
750
751 DISALLOW_COPY_AND_ASSIGN(TimelineEventScope);
752};
753
754class TimelineBeginEndScope : public TimelineEventScope {
755 public:
756 TimelineBeginEndScope(TimelineStream* stream, const char* label);
757
758 TimelineBeginEndScope(Thread* thread,
759 TimelineStream* stream,
760 const char* label);
761
762 virtual ~TimelineBeginEndScope();
763
764 private:
765 void EmitBegin();
766 void EmitEnd();
767
768 DISALLOW_COPY_AND_ASSIGN(TimelineBeginEndScope);
769};
770
771// A block of |TimelineEvent|s. Not thread safe.
772class TimelineEventBlock : public MallocAllocated {
773 public:
774 static constexpr intptr_t kBlockSize = 64;
775
776 explicit TimelineEventBlock(intptr_t index);
777 ~TimelineEventBlock();
778
779 TimelineEventBlock* next() const { return next_; }
780 void set_next(TimelineEventBlock* next) { next_ = next; }
781
782 intptr_t length() const { return length_; }
783
784 intptr_t block_index() const { return block_index_; }
785
786 bool IsEmpty() const { return length_ == 0; }
787
788 bool IsFull() const { return length_ == kBlockSize; }
789
790 TimelineEvent* At(intptr_t index) {
791 ASSERT(index >= 0);
792 ASSERT(index < kBlockSize);
793 return &events_[index];
794 }
795
796 const TimelineEvent* At(intptr_t index) const {
797 ASSERT(index >= 0);
798 ASSERT(index < kBlockSize);
799 return &events_[index];
800 }
801
802 // Attempt to sniff the timestamp from the first event.
803 int64_t LowerTimeBound() const;
804
805 // Call Reset on all events and set length to 0.
806 void Reset();
807
808 // Only safe to access under the recorder's lock.
809 inline bool InUseLocked() const;
810
811 // Only safe to access under the recorder's lock.
812 inline bool ContainsEventsThatCanBeSerializedLocked() const;
813
814 protected:
815#ifndef PRODUCT
816 void PrintJSON(JSONStream* stream) const;
817#endif
818
819 // Only safe to call from the thread that owns this block, while the thread is
820 // holding its block lock.
821 TimelineEvent* StartEventLocked();
822
823 TimelineEvent events_[kBlockSize];
824 TimelineEventBlock* next_;
825 intptr_t length_;
826 intptr_t block_index_;
827
828 // Only safe to access under the recorder's lock.
829 OSThread* current_owner_;
830 bool in_use_;
831
832 void Open();
833
834 friend class Thread;
835 friend class TimelineEventRecorder;
836 friend class TimelineEventEndlessRecorder;
837 friend class TimelineEventRingRecorder;
838 friend class TimelineEventStartupRecorder;
839 friend class TimelineEventPlatformRecorder;
840 friend class TimelineTestHelper;
841 friend class JSONStream;
842
843 private:
844 void Finish();
845
846 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock);
847};
848
849class TimelineEventFilter : public ValueObject {
850 public:
851 TimelineEventFilter(int64_t time_origin_micros = -1,
852 int64_t time_extent_micros = -1);
853
854 virtual ~TimelineEventFilter();
855
856 virtual bool IncludeEvent(TimelineEvent* event) const {
857 if (event == nullptr) {
858 return false;
859 }
860 return event->IsValid();
861 }
862
863 int64_t time_origin_micros() const { return time_origin_micros_; }
864
865 int64_t time_extent_micros() const { return time_extent_micros_; }
866
867 private:
868 int64_t time_origin_micros_;
869 int64_t time_extent_micros_;
870};
871
872class IsolateTimelineEventFilter : public TimelineEventFilter {
873 public:
874 explicit IsolateTimelineEventFilter(Dart_Port isolate_id,
875 int64_t time_origin_micros = -1,
876 int64_t time_extent_micros = -1);
877
878 bool IncludeEvent(TimelineEvent* event) const final {
879 return event->IsValid() && (event->isolate_id() == isolate_id_);
880 }
881
882 private:
883 Dart_Port isolate_id_;
884};
885
886// Recorder of |TimelineEvent|s.
887class TimelineEventRecorder : public MallocAllocated {
888 public:
889 TimelineEventRecorder();
890 virtual ~TimelineEventRecorder();
891
892 // Interface method(s) which must be implemented.
893#ifndef PRODUCT
894 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
895#if defined(SUPPORT_PERFETTO)
896 /*
897 * Prints a PerfettoTimeline service response into |js|.
898 */
899 virtual void PrintPerfettoTimeline(JSONStream* js,
900 const TimelineEventFilter& filter) = 0;
901#endif // defined(SUPPORT_PERFETTO)
902 virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0;
903#endif // !defined(PRODUCT)
904 virtual const char* name() const = 0;
905 virtual intptr_t Size() = 0;
906 // Only safe to call when holding |lock_|.
907 virtual TimelineEventBlock* GetNewBlockLocked() = 0;
908 void FinishBlock(TimelineEventBlock* block);
909 // This function must be called at least once for each thread that corresponds
910 // to a track in the trace.
911 void AddTrackMetadataBasedOnThread(const intptr_t process_id,
912 const intptr_t trace_id,
913 const char* thread_name);
914 void AddAsyncTrackMetadataBasedOnEvent(const TimelineEvent& event);
915
916 protected:
917 SimpleHashMap& track_uuid_to_track_metadata() {
918 return track_uuid_to_track_metadata_;
919 }
920 SimpleHashMap& async_track_uuid_to_track_metadata() {
921 return async_track_uuid_to_track_metadata_;
922 }
923#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
924 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>& packet() {
925 return packet_;
926 }
927#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
928
929#ifndef PRODUCT
930 void WriteTo(const char* directory);
931#endif
932
933 // Interface method(s) which must be implemented.
934 virtual TimelineEvent* StartEvent() = 0;
935 virtual void CompleteEvent(TimelineEvent* event) = 0;
936 // Only safe to call when holding |lock_|.
937 virtual TimelineEventBlock* GetHeadBlockLocked() = 0;
938 // Only safe to call when holding |lock_|.
939 virtual void ClearLocked() = 0;
940
941 // Utility method(s).
942#ifndef PRODUCT
943 void PrintJSONMeta(const JSONArray& jsarr_events);
944#if defined(SUPPORT_PERFETTO)
945 /*
946 * Appends metadata about the timeline in Perfetto's proto format to
947 * |jsonBase64String|.
948 */
949 void PrintPerfettoMeta(JSONBase64String* jsonBase64String);
950#endif // defined(SUPPORT_PERFETTO)
951#endif // !defined(PRODUCT)
952 TimelineEvent* ThreadBlockStartEvent();
953 void ThreadBlockCompleteEvent(TimelineEvent* event);
954
955 void ResetTimeTracking();
956 void ReportTime(int64_t micros);
957 int64_t TimeOriginMicros() const;
958 int64_t TimeExtentMicros() const;
959
960 Mutex lock_;
961 int64_t time_low_micros_;
962 int64_t time_high_micros_;
963
964 friend class TimelineEvent;
965 friend class TimelineEventBlock;
966 friend class TimelineStream;
967 friend class TimelineTestHelper;
968 friend class Timeline;
969 friend class OSThread;
970
971 private:
972 static constexpr intptr_t kTrackUuidToTrackMetadataInitialCapacity = 1 << 4;
973 Mutex track_uuid_to_track_metadata_lock_;
974 SimpleHashMap track_uuid_to_track_metadata_;
975 Mutex async_track_uuid_to_track_metadata_lock_;
976 SimpleHashMap async_track_uuid_to_track_metadata_;
977#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
978 // We allocate one heap-buffered packet as a class member, because it lets us
979 // continuously follow a cycle of resetting the buffer and writing its
980 // contents.
981 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet_;
982#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
983
984 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
985};
986
987// An abstract recorder that stores events in a buffer of fixed capacity.
988class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
989 public:
990 static constexpr intptr_t kDefaultCapacity = 32 * KB; // Number of events.
991
992 explicit TimelineEventFixedBufferRecorder(intptr_t capacity);
993 virtual ~TimelineEventFixedBufferRecorder();
994
995#ifndef PRODUCT
996 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
997#if defined(SUPPORT_PERFETTO)
998 void PrintPerfettoTimeline(JSONStream* js,
999 const TimelineEventFilter& filter) final;
1000#endif // defined(SUPPORT_PERFETTO)
1001 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1002#endif // !defined(PRODUCT)
1003
1004 intptr_t Size();
1005
1006 protected:
1007 TimelineEvent* StartEvent();
1008 void CompleteEvent(TimelineEvent* event);
1009 TimelineEventBlock* GetHeadBlockLocked();
1010 // Only safe to call when holding |lock_|.
1011 intptr_t FindOldestBlockIndexLocked() const;
1012 void ClearLocked();
1013
1014#ifndef PRODUCT
1015 void PrintJSONEvents(const JSONArray& array,
1016 const TimelineEventFilter& filter);
1017#if defined(SUPPORT_PERFETTO)
1018 void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
1019 const TimelineEventFilter& filter);
1020#endif // defined(SUPPORT_PERFETTO)
1021#endif // !defined(PRODUCT)
1022
1023 VirtualMemory* memory_;
1024 TimelineEventBlock* blocks_;
1025 intptr_t capacity_;
1026 intptr_t num_blocks_;
1027 intptr_t block_cursor_;
1028
1029 private:
1030#if !defined(PRODUCT)
1031 inline void PrintEventsCommon(
1032 const TimelineEventFilter& filter,
1033 std::function<void(const TimelineEvent&)>&& print_impl);
1034#endif // !defined(PRODUCT)
1035};
1036
1037// A recorder that stores events in a buffer of fixed capacity. When the buffer
1038// is full, new events overwrite old events.
1039class TimelineEventRingRecorder : public TimelineEventFixedBufferRecorder {
1040 public:
1041 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity)
1042 : TimelineEventFixedBufferRecorder(capacity) {}
1043 virtual ~TimelineEventRingRecorder() {}
1044
1045 const char* name() const { return RING_RECORDER_NAME; }
1046
1047 protected:
1048 TimelineEventBlock* GetNewBlockLocked();
1049};
1050
1051// A recorder that stores events in a buffer of fixed capacity. When the buffer
1052// is full, new events are dropped.
1053class TimelineEventStartupRecorder : public TimelineEventFixedBufferRecorder {
1054 public:
1055 explicit TimelineEventStartupRecorder(intptr_t capacity = kDefaultCapacity)
1056 : TimelineEventFixedBufferRecorder(capacity) {}
1057 virtual ~TimelineEventStartupRecorder() {}
1058
1059 const char* name() const { return STARTUP_RECORDER_NAME; }
1060
1061 protected:
1062 TimelineEventBlock* GetNewBlockLocked();
1063};
1064
1065// An abstract recorder that calls |OnEvent| whenever an event is complete.
1066// This should only be used for testing.
1067class TimelineEventCallbackRecorder : public TimelineEventRecorder {
1068 public:
1069 TimelineEventCallbackRecorder();
1070 virtual ~TimelineEventCallbackRecorder();
1071
1072#ifndef PRODUCT
1073 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1074#if defined(SUPPORT_PERFETTO)
1075 void PrintPerfettoTimeline(JSONStream* js,
1076 const TimelineEventFilter& filter) final;
1077#endif // defined(SUPPORT_PERFETTO)
1078 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1079#endif // !defined(PRODUCT)
1080
1081 // Called when |event| is completed. It is unsafe to keep a reference to
1082 // |event| as it may be freed as soon as this function returns.
1083 virtual void OnEvent(TimelineEvent* event) = 0;
1084
1085 const char* name() const { return CALLBACK_RECORDER_NAME; }
1086 intptr_t Size() { return 0; }
1087
1088 protected:
1089 TimelineEventBlock* GetNewBlockLocked() { UNREACHABLE(); }
1090 TimelineEventBlock* GetHeadBlockLocked() { UNREACHABLE(); }
1091 void ClearLocked() { ASSERT(lock_.IsOwnedByCurrentThread()); }
1092 TimelineEvent* StartEvent();
1093 void CompleteEvent(TimelineEvent* event);
1094};
1095
1096// A recorder that forwards completed events to the callback provided by
1097// Dart_SetTimelineRecorderCallback.
1098class TimelineEventEmbedderCallbackRecorder
1099 : public TimelineEventCallbackRecorder {
1100 public:
1101 TimelineEventEmbedderCallbackRecorder() {}
1102 virtual ~TimelineEventEmbedderCallbackRecorder() {}
1103
1104 virtual void OnEvent(TimelineEvent* event);
1105};
1106
1107// A recorder that does nothing.
1108class TimelineEventNopRecorder : public TimelineEventCallbackRecorder {
1109 public:
1110 TimelineEventNopRecorder() {}
1111 virtual ~TimelineEventNopRecorder() {}
1112
1113 virtual void OnEvent(TimelineEvent* event);
1114};
1115
1116// A recorder that stores events in chains of blocks of events.
1117// NOTE: This recorder will continue to allocate blocks until it exhausts
1118// memory.
1119class TimelineEventEndlessRecorder : public TimelineEventRecorder {
1120 public:
1121 TimelineEventEndlessRecorder();
1122 virtual ~TimelineEventEndlessRecorder();
1123
1124#ifndef PRODUCT
1125 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1126#if defined(SUPPORT_PERFETTO)
1127 void PrintPerfettoTimeline(JSONStream* js,
1128 const TimelineEventFilter& filter) final;
1129#endif // defined(SUPPORT_PERFETTO)
1130 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1131#endif // !defined(PRODUCT)
1132
1133 const char* name() const { return ENDLESS_RECORDER_NAME; }
1134 intptr_t Size() { return block_index_ * sizeof(TimelineEventBlock); }
1135
1136 protected:
1137 TimelineEvent* StartEvent();
1138 void CompleteEvent(TimelineEvent* event);
1139 TimelineEventBlock* GetNewBlockLocked();
1140 TimelineEventBlock* GetHeadBlockLocked();
1141 void ClearLocked();
1142
1143#ifndef PRODUCT
1144 void PrintJSONEvents(const JSONArray& array,
1145 const TimelineEventFilter& filter);
1146#if defined(SUPPORT_PERFETTO)
1147 void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
1148 const TimelineEventFilter& filter);
1149#endif // defined(SUPPORT_PERFETTO)
1150#endif // !defined(PRODUCT)
1151
1152 TimelineEventBlock* head_;
1153 TimelineEventBlock* tail_;
1154 intptr_t block_index_;
1155
1156 private:
1157#if !defined(PRODUCT)
1158 inline void PrintEventsCommon(
1159 const TimelineEventFilter& filter,
1160 std::function<void(const TimelineEvent&)>&& print_impl);
1161#endif // !defined(PRODUCT)
1162
1163 friend class TimelineTestHelper;
1164};
1165
1166// The TimelineEventPlatformRecorder records timeline events to a platform
1167// specific destination. It's implementation is in the timeline_{linux,...}.cc
1168// files.
1169class TimelineEventPlatformRecorder : public TimelineEventRecorder {
1170 public:
1171 TimelineEventPlatformRecorder();
1172 virtual ~TimelineEventPlatformRecorder();
1173
1174#ifndef PRODUCT
1175 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1176#if defined(SUPPORT_PERFETTO)
1177 void PrintPerfettoTimeline(JSONStream* js,
1178 const TimelineEventFilter& filter) final;
1179#endif // defined(SUPPORT_PERFETTO)
1180 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1181#endif // !defined(PRODUCT)
1182
1183 // Called when |event| is completed. It is unsafe to keep a reference to
1184 // |event| as it may be freed as soon as this function returns.
1185 virtual void OnEvent(TimelineEvent* event) = 0;
1186
1187 virtual const char* name() const = 0;
1188
1189 protected:
1190 TimelineEventBlock* GetNewBlockLocked() { UNREACHABLE(); }
1191 TimelineEventBlock* GetHeadBlockLocked() { UNREACHABLE(); }
1192 void ClearLocked() { ASSERT(lock_.IsOwnedByCurrentThread()); }
1193 TimelineEvent* StartEvent();
1194 void CompleteEvent(TimelineEvent* event);
1195};
1196
1197#if defined(DART_HOST_OS_FUCHSIA)
1198// A recorder that sends events to Fuchsia's tracing app.
1199class TimelineEventFuchsiaRecorder : public TimelineEventPlatformRecorder {
1200 public:
1201 TimelineEventFuchsiaRecorder() {}
1202 virtual ~TimelineEventFuchsiaRecorder() {}
1203
1204 const char* name() const { return FUCHSIA_RECORDER_NAME; }
1205 intptr_t Size() { return 0; }
1206
1207 private:
1208 void OnEvent(TimelineEvent* event);
1209};
1210#endif // defined(DART_HOST_OS_FUCHSIA)
1211
1212#if defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
1213// A recorder that writes events to Android Systrace. This class is exposed in
1214// this header file only so that PrintSystrace can be visible to
1215// timeline_test.cc.
1216class TimelineEventSystraceRecorder : public TimelineEventPlatformRecorder {
1217 public:
1218 TimelineEventSystraceRecorder();
1219 virtual ~TimelineEventSystraceRecorder();
1220
1221 static intptr_t PrintSystrace(TimelineEvent* event,
1222 char* buffer,
1223 intptr_t buffer_size);
1224
1225 const char* name() const { return SYSTRACE_RECORDER_NAME; }
1226 intptr_t Size() { return 0; }
1227
1228 private:
1229 void OnEvent(TimelineEvent* event);
1230
1231 int systrace_fd_;
1232};
1233#endif // defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
1234
1235#if defined(DART_HOST_OS_MACOS)
1236// A recorder that sends events to macOS's tracing app. See:
1237// https://developer.apple.com/documentation/os/logging?language=objc
1238class TimelineEventMacosRecorder : public TimelineEventPlatformRecorder {
1239 public:
1240 TimelineEventMacosRecorder();
1241 virtual ~TimelineEventMacosRecorder();
1242
1243 const char* name() const { return MACOS_RECORDER_NAME; }
1244 intptr_t Size() { return 0; }
1245
1246 private:
1247 void OnEvent(TimelineEvent* event);
1248};
1249#endif // defined(DART_HOST_OS_MACOS)
1250
1251class TimelineEventFileRecorderBase : public TimelineEventPlatformRecorder {
1252 public:
1253 explicit TimelineEventFileRecorderBase(const char* path);
1254 virtual ~TimelineEventFileRecorderBase();
1255
1256 intptr_t Size() final { return 0; }
1257 void OnEvent(TimelineEvent* event) final { UNREACHABLE(); }
1258 void Drain();
1259
1260 protected:
1261 void Write(const char* buffer, intptr_t len) const;
1262 void Write(const char* buffer) const { Write(buffer, strlen(buffer)); }
1263 void CompleteEvent(TimelineEvent* event) final;
1264 void ShutDown();
1265
1266 private:
1267 virtual void DrainImpl(const TimelineEvent& event) = 0;
1268
1269 Monitor monitor_;
1270 TimelineEvent* head_;
1271 TimelineEvent* tail_;
1272 void* file_;
1273 bool shutting_down_;
1274 bool drained_;
1275 ThreadJoinId thread_id_;
1276};
1277
1278class TimelineEventFileRecorder : public TimelineEventFileRecorderBase {
1279 public:
1280 explicit TimelineEventFileRecorder(const char* path);
1281 virtual ~TimelineEventFileRecorder();
1282
1283 const char* name() const final { return FILE_RECORDER_NAME; }
1284
1285 private:
1286 void DrainImpl(const TimelineEvent& event) final;
1287
1288 bool first_;
1289};
1290
1291#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
1292class TimelineEventPerfettoFileRecorder : public TimelineEventFileRecorderBase {
1293 public:
1294 explicit TimelineEventPerfettoFileRecorder(const char* path);
1295 virtual ~TimelineEventPerfettoFileRecorder();
1296
1297 const char* name() const final { return PERFETTO_FILE_RECORDER_NAME; }
1298
1299 private:
1300 void WritePacket(
1301 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* packet)
1302 const;
1303 void DrainImpl(const TimelineEvent& event) final;
1304};
1305#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
1306
1307class DartTimelineEventHelpers : public AllStatic {
1308 public:
1309 // When reporting an event of type |kAsyncBegin|, |kAsyncEnd|, or
1310 // |kAsyncInstant|, the async ID associated with the event should be passed
1311 // through |id|. When reporting an event of type |kFlowBegin|, |kFlowStep|,
1312 // or |kFlowEnd|, the flow ID associated with the event should be passed
1313 // through |id|. When reporting an event of type |kBegin| or |kEnd|, the event
1314 // ID associated with the event should be passed through |id|. Note that this
1315 // event ID will only be used by the MacOS recorder.
1316 static void ReportTaskEvent(TimelineEvent* event,
1317 int64_t id,
1318 intptr_t flow_id_count,
1319 std::unique_ptr<const int64_t[]>& flow_ids,
1320 intptr_t type,
1321 char* name,
1322 char* args);
1323};
1324#endif // defined(SUPPORT_TIMELINE)
1325
1326} // namespace dart
1327
1328#endif // RUNTIME_VM_TIMELINE_H_
int count
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
static float next(float f)
ax::mojom::Event event_type
#define UNREACHABLE()
Definition assert.h:248
#define COMPILE_ASSERT(expr)
Definition assert.h:339
const char * name() const
Definition timeline.h:93
static intptr_t enabled_offset()
Definition timeline.h:114
TimelineEvent * StartEvent()
void set_enabled(bool enabled)
Definition timeline.h:108
TimelineStream(const char *name, const char *fuchsia_name, bool static_labels, bool enabled)
const char * fuchsia_name() const
Definition timeline.h:94
int64_t Dart_Port
Definition dart_api.h:1524
void(* Dart_TimelineRecorderCallback)(Dart_TimelineRecorderEvent *event)
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
static const uint8_t buffer[]
uint8_t value
const char * name
Definition fuchsia.cc:50
void Init()
size_t length
std::variant< Lower, Cross, Upper > EventType
Definition EventQueue.h:47
pthread_t ThreadId
Definition thread_absl.h:21
pthread_t ThreadJoinId
constexpr intptr_t KB
Definition globals.h:528
uintptr_t uword
Definition globals.h:501
void Reset(SkPath *path)
Definition path_ops.cc:40
TSize< Scalar > Size
Definition size.h:137
static SkString fmt(SkColor4f c)
Definition p3.cpp:43
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition globals.h:697
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
const uintptr_t id
#define OFFSET_OF(type, field)
Definition globals.h:138