Flutter Engine
The Flutter Engine
profiler.h
Go to the documentation of this file.
1// Copyright (c) 2013, 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_PROFILER_H_
6#define RUNTIME_VM_PROFILER_H_
7
8#include "platform/atomic.h"
9
10#include "vm/allocation.h"
11#include "vm/bitfield.h"
12#include "vm/code_observers.h"
13#include "vm/globals.h"
14#include "vm/growable_array.h"
15#include "vm/native_symbol.h"
16#include "vm/object.h"
17#include "vm/tags.h"
19
20// Profiler sampling and stack walking support.
21// NOTE: For service related code, see profile_service.h.
22
23namespace dart {
24
25// Forward declarations.
26class ProcessedSample;
27class ProcessedSampleBuffer;
28
29class Sample;
30class SampleBlock;
31
32#define PROFILER_COUNTERS(V) \
33 V(bail_out_unknown_task) \
34 V(bail_out_jump_to_exception_handler) \
35 V(bail_out_check_isolate) \
36 V(single_frame_sample_deoptimizing) \
37 V(single_frame_sample_get_and_validate_stack_bounds) \
38 V(stack_walker_native) \
39 V(stack_walker_dart_exit) \
40 V(stack_walker_dart) \
41 V(stack_walker_none) \
42 V(incomplete_sample_fp_bounds) \
43 V(incomplete_sample_fp_step) \
44 V(incomplete_sample_bad_pc) \
45 V(sample_allocation_failure)
46
48#define DECLARE_PROFILER_COUNTER(name) RelaxedAtomic<int64_t> name;
50#undef DECLARE_PROFILER_COUNTER
51};
52
53class Profiler : public AllStatic {
54 public:
55 static void Init();
56 static void Cleanup();
57
58 static void SetSampleDepth(intptr_t depth);
59 static void SetSamplePeriod(intptr_t period);
60 // Restarts sampling with a given profile period. This is called after the
61 // profile period is changed via the service protocol.
62 static void UpdateSamplePeriod();
63 // Starts or shuts down the profiler after --profiler is changed via the
64 // service protocol.
65 static void UpdateRunningState();
66
68 return sample_block_buffer_;
69 }
71 sample_block_buffer_ = buffer;
72 }
73
74 static void DumpStackTrace(void* context);
75 static void DumpStackTrace(bool for_crash = true);
76
77 static void SampleAllocation(Thread* thread,
78 intptr_t cid,
79 uint32_t identity_hash);
80
81 // SampleThread is called from inside the signal handler and hence it is very
82 // critical that the implementation of SampleThread does not do any of the
83 // following:
84 // * Accessing TLS -- Because on Fuchsia, Mac and Windows the callback will
85 // be running in a different thread.
86 // * Allocating memory -- Because this takes locks which may already be
87 // held, resulting in a dead lock.
88 // * Taking a lock -- See above.
89 static void SampleThread(Thread* thread, const InterruptedThreadState& state);
90
92 // Copies the counter values.
93 return counters_;
94 }
95 inline static intptr_t Size();
96
97 static void ProcessCompletedBlocks(Isolate* isolate);
98 static void IsolateShutdown(Thread* thread);
99
100 private:
101 static void DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash);
102
103 // Calculates the sample buffer capacity. Returns
104 // SampleBuffer::kDefaultBufferCapacity if --sample-buffer-duration is not
105 // provided. Otherwise, the capacity is based on the sample rate, maximum
106 // sample stack depth, and the number of seconds of samples the sample buffer
107 // should be able to accomodate.
108 static intptr_t CalculateSampleBufferCapacity();
109
110 // Does not walk the thread's stack.
111 static void SampleThreadSingleFrame(Thread* thread,
112 Sample* sample,
113 uintptr_t pc);
114 static RelaxedAtomic<bool> initialized_;
115
116 static SampleBlockBuffer* sample_block_buffer_;
117
118 static ProfilerCounters counters_;
119
120 friend class Thread;
121};
122
124 public:
125 explicit SampleVisitor(Dart_Port port) : port_(port), visited_(0) {}
126 virtual ~SampleVisitor() {}
127
128 virtual void VisitSample(Sample* sample) = 0;
129
130 virtual void Reset() { visited_ = 0; }
131
132 intptr_t visited() const { return visited_; }
133
134 void IncrementVisited() { visited_++; }
135
136 Dart_Port port() const { return port_; }
137
138 private:
139 Dart_Port port_;
140 intptr_t visited_;
141
142 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor);
143};
144
145class SampleFilter : public ValueObject {
146 public:
148 intptr_t thread_task_mask,
149 int64_t time_origin_micros,
150 int64_t time_extent_micros,
151 bool take_samples = false)
152 : port_(port),
153 thread_task_mask_(thread_task_mask),
154 time_origin_micros_(time_origin_micros),
155 time_extent_micros_(time_extent_micros),
156 take_samples_(take_samples) {
157 ASSERT(thread_task_mask != 0);
158 ASSERT(time_origin_micros_ >= -1);
159 ASSERT(time_extent_micros_ >= -1);
160 }
161 virtual ~SampleFilter() {}
162
163 // Override this function.
164 // Return |true| if |sample| passes the filter.
165 virtual bool FilterSample(Sample* sample) { return true; }
166
167 Dart_Port port() const { return port_; }
168
169 // Returns |true| if |sample| passes the time filter.
170 bool TimeFilterSample(Sample* sample);
171
172 // Returns |true| if |sample| passes the thread task filter.
173 bool TaskFilterSample(Sample* sample);
174
175 bool take_samples() const { return take_samples_; }
176
177 static constexpr intptr_t kNoTaskFilter = -1;
178
179 private:
180 Dart_Port port_;
181 intptr_t thread_task_mask_;
182 int64_t time_origin_micros_;
183 int64_t time_extent_micros_;
184 bool take_samples_;
185};
186
188 public:
189 explicit ClearProfileVisitor(Isolate* isolate);
190
191 virtual void VisitSample(Sample* sample);
192};
193
194// Each Sample holds a stack trace from an isolate.
195class Sample {
196 public:
197 Sample() = default;
198
200 Clear();
201 timestamp_ = timestamp;
202 tid_ = tid;
203 port_ = port;
204 next_ = nullptr;
205 }
206
207 Dart_Port port() const { return port_; }
208
209 // Thread sample was taken on.
210 ThreadId tid() const { return tid_; }
211
212 void Clear() {
213 timestamp_ = 0;
214 port_ = ILLEGAL_PORT;
216 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) {
217 stack_buffer_[i] = 0;
218 }
219 for (intptr_t i = 0; i < kPCArraySizeInWords; i++) {
220 pc_array_[i] = 0;
221 }
222 vm_tag_ = VMTag::kInvalidTagId;
223 user_tag_ = UserTags::kDefaultUserTag;
224 state_ = 0;
225 next_ = nullptr;
226 allocation_identity_hash_ = 0;
227 set_head_sample(true);
228 }
229
230 // Timestamp sample was taken at.
231 int64_t timestamp() const { return timestamp_; }
232
233 // Top most pc.
234 uword pc() const { return At(0); }
235
236 // Get stack trace entry.
237 uword At(intptr_t i) const {
238 ASSERT(i >= 0);
240 return pc_array_[i];
241 }
242
243 // Set stack trace entry.
244 void SetAt(intptr_t i, uword pc) {
245 ASSERT(i >= 0);
247 pc_array_[i] = pc;
248 }
249
251 for (intptr_t i = 0; i < kPCArraySizeInWords; ++i) {
252 uintptr_t start = 0;
253 uword pc = At(i);
254 const char* native_symbol_name =
256 if (native_symbol_name == nullptr) {
257 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc);
258 } else {
259 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name);
260 NativeSymbolResolver::FreeSymbolName(native_symbol_name);
261 }
262 }
263 }
264
265 uword vm_tag() const { return vm_tag_; }
266 void set_vm_tag(uword tag) {
268 vm_tag_ = tag;
269 }
270
271 uword user_tag() const { return user_tag_; }
272 void set_user_tag(uword tag) { user_tag_ = tag; }
273
274 bool leaf_frame_is_dart() const { return LeafFrameIsDart::decode(state_); }
275
278 }
279
280 bool ignore_sample() const { return IgnoreBit::decode(state_); }
281
283 state_ = IgnoreBit::update(ignore_sample, state_);
284 }
285
286 bool exit_frame_sample() const { return ExitFrameBit::decode(state_); }
287
289 state_ = ExitFrameBit::update(exit_frame_sample, state_);
290 }
291
293 return MissingFrameInsertedBit::decode(state_);
294 }
295
298 }
299
300 bool truncated_trace() const { return TruncatedTraceBit::decode(state_); }
301
304 }
305
306 bool is_allocation_sample() const {
308 }
309
310 void set_is_allocation_sample(bool allocation_sample) {
311 state_ = ClassAllocationSampleBit::update(allocation_sample, state_);
312 }
313
314 uint32_t allocation_identity_hash() const {
315 return allocation_identity_hash_;
316 }
317
319 allocation_identity_hash_ = hash;
320 }
321
323
325 state_ = ThreadTaskBit::update(task, state_);
326 }
327
329 return ContinuationSampleBit::decode(state_);
330 }
331
334 ASSERT(next_ == nullptr);
335 state_ = ContinuationSampleBit::update(true, state_);
336 next_ = next;
337 }
338
339 Sample* continuation_sample() const { return next_; }
340
341 intptr_t allocation_cid() const {
343 return metadata();
344 }
345
347 state_ = HeadSampleBit::update(head_sample, state_);
348 }
349
350 bool head_sample() const { return HeadSampleBit::decode(state_); }
351
352 intptr_t metadata() const { return MetadataBits::decode(state_); }
353 void set_metadata(intptr_t metadata) {
354 state_ = MetadataBits::update(metadata, state_);
355 }
356
357 void SetAllocationCid(intptr_t cid) {
360 }
361
362 static constexpr int kPCArraySizeInWords = 32;
363 uword* GetPCArray() { return &pc_array_[0]; }
364
365 static constexpr int kStackBufferSizeInWords = 2;
366 uword* GetStackBuffer() { return &stack_buffer_[0]; }
367
368 private:
369 int64_t timestamp_;
370 Dart_Port port_;
371 ThreadId tid_;
372 uword stack_buffer_[kStackBufferSizeInWords];
373 uword pc_array_[kPCArraySizeInWords];
374 uword vm_tag_;
375 uword user_tag_;
376 uint32_t state_;
377 Sample* next_;
378 uint32_t allocation_identity_hash_;
379
380 using HeadSampleBit = BitField<decltype(state_), bool, 0, 1>;
381 using LeafFrameIsDart =
382 BitField<decltype(state_), bool, HeadSampleBit::kNextBit, 1>;
383 using IgnoreBit =
384 BitField<decltype(state_), bool, LeafFrameIsDart::kNextBit, 1>;
386 using MissingFrameInsertedBit =
387 BitField<decltype(state_), bool, ExitFrameBit::kNextBit, 1>;
388 using TruncatedTraceBit =
389 BitField<decltype(state_), bool, MissingFrameInsertedBit::kNextBit, 1>;
390 using ClassAllocationSampleBit =
391 BitField<decltype(state_), bool, TruncatedTraceBit::kNextBit, 1>;
392 using ContinuationSampleBit =
393 BitField<decltype(state_), bool, ClassAllocationSampleBit::kNextBit, 1>;
394 using ThreadTaskBit = BitField<decltype(state_),
397 4>;
398 using MetadataBits = BitField<decltype(state_),
399 intptr_t,
402
403 DISALLOW_COPY_AND_ASSIGN(Sample);
404};
405
407 public:
408 explicit AbstractCode(ObjectPtr code) : code_(Object::Handle(code)) {
409 ASSERT(code_.IsNull() || code_.IsCode());
410 }
411
412 ObjectPtr ptr() const { return code_.ptr(); }
413 const Object* handle() const { return &code_; }
414
416 ASSERT(code_.IsCode());
417 return Code::Cast(code_).PayloadStart();
418 }
419
420 uword Size() const {
421 ASSERT(code_.IsCode());
422 return Code::Cast(code_).Size();
423 }
424
425 int64_t compile_timestamp() const {
426 if (code_.IsCode()) {
427 return Code::Cast(code_).compile_timestamp();
428 } else {
429 return 0;
430 }
431 }
432
433 const char* Name() const {
434 if (code_.IsCode()) {
435 return Code::Cast(code_).Name();
436 } else {
437 return "";
438 }
439 }
440
441 const char* QualifiedName() const {
442 if (code_.IsCode()) {
443 return Code::Cast(code_).QualifiedName(
445 } else {
446 return "";
447 }
448 }
449
450 bool IsStubCode() const {
451 if (code_.IsCode()) {
452 return Code::Cast(code_).IsStubCode();
453 } else {
454 return false;
455 }
456 }
457
458 bool IsAllocationStubCode() const {
459 if (code_.IsCode()) {
460 return Code::Cast(code_).IsAllocationStubCode();
461 } else {
462 return false;
463 }
464 }
465
466 bool IsTypeTestStubCode() const {
467 if (code_.IsCode()) {
468 return Code::Cast(code_).IsTypeTestStubCode();
469 } else {
470 return false;
471 }
472 }
473
474 ObjectPtr owner() const {
475 if (code_.IsCode()) {
476 return Code::Cast(code_).owner();
477 } else {
478 return Object::null();
479 }
480 }
481
482 bool IsNull() const { return code_.IsNull(); }
483 bool IsCode() const { return code_.IsCode(); }
484
485 bool is_optimized() const {
486 if (code_.IsCode()) {
487 return Code::Cast(code_).is_optimized();
488 } else {
489 return false;
490 }
491 }
492
493 private:
494 const Object& code_;
495};
496
497// A Code object descriptor.
499 public:
500 explicit CodeDescriptor(const AbstractCode code);
501
502 uword Start() const;
503
504 uword Size() const;
505
506 int64_t CompileTimestamp() const;
507
508 const AbstractCode code() const { return code_; }
509
510 const char* Name() const { return code_.Name(); }
511
512 bool Contains(uword pc) const {
513 uword end = Start() + Size();
514 return (pc >= Start()) && (pc < end);
515 }
516
517 static int Compare(CodeDescriptor* const* a, CodeDescriptor* const* b) {
518 ASSERT(a != nullptr);
519 ASSERT(b != nullptr);
520
521 uword a_start = (*a)->Start();
522 uword b_start = (*b)->Start();
523
524 if (a_start < b_start) {
525 return -1;
526 } else if (a_start > b_start) {
527 return 1;
528 } else {
529 return 0;
530 }
531 }
532
533 private:
534 const AbstractCode code_;
535
536 DISALLOW_COPY_AND_ASSIGN(CodeDescriptor);
537};
538
539// Fast lookup of Dart code objects.
541 public:
542 explicit CodeLookupTable(Thread* thread);
543
544 intptr_t length() const { return code_objects_.length(); }
545
546 const CodeDescriptor* At(intptr_t index) const {
547 return code_objects_.At(index);
548 }
549
550 const CodeDescriptor* FindCode(uword pc) const;
551
552 private:
553 void Build(Thread* thread);
554
555 void Add(const Object& code);
556
557 // Code objects sorted by entry.
559
561
563};
564
566 public:
567 SampleBuffer() = default;
568 virtual ~SampleBuffer() = default;
569
570 virtual void Init(Sample* samples, intptr_t capacity) {
571 ASSERT(samples != nullptr);
572 ASSERT(capacity > 0);
573 samples_ = samples;
575 }
576
578 ASSERT(visitor != nullptr);
579 const intptr_t length = capacity();
580 for (intptr_t i = 0; i < length; i++) {
581 Sample* sample = At(i);
582 if (!sample->head_sample()) {
583 // An inner sample in a chain of samples.
584 continue;
585 }
586 if (sample->ignore_sample()) {
587 // Bad sample.
588 continue;
589 }
590 if (sample->port() != visitor->port()) {
591 // Another isolate.
592 continue;
593 }
594 if (sample->timestamp() == 0) {
595 // Empty.
596 continue;
597 }
598 if (sample->At(0) == 0) {
599 // No frames.
600 continue;
601 }
602 visitor->IncrementVisited();
603 visitor->VisitSample(sample);
604 }
605 }
606
607 virtual Sample* ReserveSample() = 0;
608 virtual Sample* ReserveSampleAndLink(Sample* previous) = 0;
609
610 Sample* At(intptr_t idx) const {
611 ASSERT(idx >= 0);
612 ASSERT(idx < capacity_);
613 return &samples_[idx];
614 }
615
616 intptr_t capacity() const { return capacity_; }
617
619 SampleFilter* filter,
620 ProcessedSampleBuffer* buffer = nullptr);
621
622 protected:
623 Sample* Next(Sample* sample);
624
626 const CodeLookupTable& clt);
627
629 intptr_t capacity_;
630
632};
633
634class SampleBlock : public SampleBuffer {
635 public:
636 // The default number of samples per block. Overridden by some tests.
637 static constexpr intptr_t kSamplesPerBlock = 100;
638
639 SampleBlock() = default;
640 virtual ~SampleBlock() = default;
641
642 // Returns the number of samples contained within this block.
643 intptr_t capacity() const { return capacity_; }
644
645 Isolate* owner() const { return owner_; }
646 void set_owner(Isolate* isolate) { owner_ = isolate; }
647
648 virtual Sample* ReserveSample();
649 virtual Sample* ReserveSampleAndLink(Sample* previous);
650
652 State expected = kFree;
653 State desired = kSampling;
654 std::memory_order success_order = std::memory_order_acquire;
655 std::memory_order failure_order = std::memory_order_relaxed;
656 return state_.compare_exchange_strong(expected, desired, success_order,
657 failure_order);
658 }
660 State expected = kCompleted;
661 State desired = kSampling;
662 std::memory_order success_order = std::memory_order_acquire;
663 std::memory_order failure_order = std::memory_order_relaxed;
664 if (state_.compare_exchange_strong(expected, desired, success_order,
665 failure_order)) {
666 owner_ = nullptr;
667 cursor_ = 0;
668 return true;
669 }
670 return false;
671 }
673 ASSERT(state_.load(std::memory_order_relaxed) == kSampling);
674 state_.store(kCompleted, std::memory_order_release);
675 }
677 if (state_.load(std::memory_order_relaxed) != kCompleted) return false;
678 if (owner_ != isolate) return false;
679
680 State expected = kCompleted;
681 State desired = kStreaming;
682 std::memory_order success_order = std::memory_order_acquire;
683 std::memory_order failure_order = std::memory_order_relaxed;
684 return state_.compare_exchange_strong(expected, desired, success_order,
685 failure_order);
686 }
688 ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
689 state_.store(kCompleted, std::memory_order_relaxed);
690 }
692 ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
693 owner_ = nullptr;
694 cursor_ = 0;
695 state_.store(kFree, std::memory_order_release);
696 }
698 State expected = kCompleted;
699 State desired = kStreaming;
700 std::memory_order success_order = std::memory_order_acquire;
701 std::memory_order failure_order = std::memory_order_relaxed;
702 if (state_.compare_exchange_strong(expected, desired, success_order,
703 failure_order)) {
705 }
706 }
707
708 protected:
709 bool HasStreamableSamples(const GrowableObjectArray& tag_table, UserTag* tag);
710
711 enum State : uint32_t {
713 kSampling, // I.e., writing.
715 kStreaming, // I.e., reading.
716 };
717 std::atomic<State> state_ = kFree;
719 Isolate* owner_ = nullptr;
720
721 private:
723 friend class SampleBlockBuffer;
724
726};
727
729 public:
730 static constexpr intptr_t kDefaultBlockCount = 600;
731
732 // Creates a SampleBlockBuffer with a predetermined number of blocks.
733 //
734 // Defaults to kDefaultBlockCount blocks. Block size is fixed to
735 // SampleBlock::kSamplesPerBlock samples per block, except for in tests.
736 explicit SampleBlockBuffer(
737 intptr_t blocks = kDefaultBlockCount,
738 intptr_t samples_per_block = SampleBlock::kSamplesPerBlock);
739
740 virtual ~SampleBlockBuffer();
741
743 ASSERT(visitor != nullptr);
744 for (intptr_t i = 0; i < capacity_; ++i) {
745 blocks_[i].VisitSamples(visitor);
746 }
747 }
748
749 void FreeCompletedBlocks();
750
751 // Reserves a sample for a CPU profile.
752 //
753 // Returns nullptr when a sample can't be reserved.
755
756 // Reserves a sample for a Dart object allocation profile.
757 //
758 // Returns nullptr when a sample can't be reserved.
760
761 intptr_t Size() const { return memory_->size(); }
762
764 Isolate* isolate,
765 SampleFilter* filter,
766 ProcessedSampleBuffer* buffer = nullptr);
767
768 private:
769 Sample* ReserveSampleImpl(Isolate* isolate, bool allocation_sample);
770
771 // Returns nullptr if there are no available blocks.
772 SampleBlock* ReserveSampleBlock();
773
774 // Sample block management.
775 RelaxedAtomic<int> cursor_;
776 SampleBlock* blocks_;
777 intptr_t capacity_;
778
779 // Sample buffer management.
780 VirtualMemory* memory_;
781 Sample* sample_buffer_;
782
783 friend class Isolate;
785};
786
787intptr_t Profiler::Size() {
788 intptr_t size = 0;
789 if (sample_block_buffer_ != nullptr) {
790 size += sample_block_buffer_->Size();
791 }
792 return size;
793}
794
795// A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have
796// been merged into a logical sample. The raw data may have been processed to
797// improve the quality of the stack trace.
799 public:
801
802 // Add |pc| to stack trace.
803 void Add(uword pc) { pcs_.Add(pc); }
804
805 // Insert |pc| at |index|.
806 void InsertAt(intptr_t index, uword pc) { pcs_.InsertAt(index, pc); }
807
808 // Number of pcs in stack trace.
809 intptr_t length() const { return pcs_.length(); }
810
811 // Get |pc| at |index|.
812 uword At(intptr_t index) const {
813 ASSERT(index >= 0);
814 ASSERT(index < length());
815 return pcs_[index];
816 }
817
818 // Timestamp sample was taken at.
819 int64_t timestamp() const { return timestamp_; }
820 void set_timestamp(int64_t timestamp) { timestamp_ = timestamp; }
821
822 ThreadId tid() const { return tid_; }
823 void set_tid(ThreadId tid) { tid_ = tid; }
824
825 // The VM tag.
826 uword vm_tag() const { return vm_tag_; }
827 void set_vm_tag(uword tag) { vm_tag_ = tag; }
828
829 // The user tag.
830 uword user_tag() const { return user_tag_; }
831 void set_user_tag(uword tag) { user_tag_ = tag; }
832
833 // The class id if this is an allocation profile sample. -1 otherwise.
834 intptr_t allocation_cid() const { return allocation_cid_; }
835 void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; }
836
837 // The identity hash code of the allocated object if this is an allocation
838 // profile sample. -1 otherwise.
839 uint32_t allocation_identity_hash() const {
840 return allocation_identity_hash_;
841 }
843 allocation_identity_hash_ = hash;
844 }
845
846 bool IsAllocationSample() const { return allocation_cid_ > 0; }
847
848 // Was the stack trace truncated?
849 bool truncated() const { return truncated_; }
850 void set_truncated(bool truncated) { truncated_ = truncated; }
851
852 // Was the first frame in the stack trace executing?
853 bool first_frame_executing() const { return first_frame_executing_; }
855 first_frame_executing_ = first_frame_executing;
856 }
857
858 private:
859 void FixupCaller(const CodeLookupTable& clt,
860 uword pc_marker,
861 uword* stack_buffer);
862
863 void CheckForMissingDartFrame(const CodeLookupTable& clt,
864 const CodeDescriptor* code,
865 uword pc_marker,
866 uword* stack_buffer);
867
869 int64_t timestamp_;
870 ThreadId tid_;
871 uword vm_tag_;
872 uword user_tag_;
873 intptr_t allocation_cid_;
874 uint32_t allocation_identity_hash_;
875 bool truncated_;
876 bool first_frame_executing_;
877
878 friend class SampleBuffer;
880};
881
882// A collection of |ProcessedSample|s.
884 public:
886
887 void Add(ProcessedSample* sample) { samples_.Add(sample); }
888
889 intptr_t length() const { return samples_.length(); }
890
891 ProcessedSample* At(intptr_t index) { return samples_.At(index); }
892
894 return *code_lookup_table_;
895 }
896
897 private:
899 CodeLookupTable* code_lookup_table_;
900
901 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer);
902};
903
905 public:
906 static void Init();
907
908 static void Startup();
909 static void Cleanup();
910
911 private:
912 static constexpr intptr_t kMaxThreads = 4096;
913 static bool initialized_;
914 static bool shutdown_;
915 static bool thread_running_;
916 static ThreadJoinId processor_thread_id_;
917 static Monitor* monitor_;
918
919 static void ThreadMain(uword parameters);
920};
921
922} // namespace dart
923
924#endif // RUNTIME_VM_PROFILER_H_
static float next(float f)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
bool IsAllocationStubCode() const
Definition: profiler.h:458
bool IsNull() const
Definition: profiler.h:482
AbstractCode(ObjectPtr code)
Definition: profiler.h:408
const char * QualifiedName() const
Definition: profiler.h:441
bool IsCode() const
Definition: profiler.h:483
uword Size() const
Definition: profiler.h:420
bool IsStubCode() const
Definition: profiler.h:450
const Object * handle() const
Definition: profiler.h:413
const char * Name() const
Definition: profiler.h:433
bool IsTypeTestStubCode() const
Definition: profiler.h:466
ObjectPtr owner() const
Definition: profiler.h:474
bool is_optimized() const
Definition: profiler.h:485
ObjectPtr ptr() const
Definition: profiler.h:412
uword PayloadStart() const
Definition: profiler.h:415
int64_t compile_timestamp() const
Definition: profiler.h:425
void InsertAt(intptr_t idx, const T &value)
void Add(const T &value)
intptr_t length() const
static constexpr intptr_t kNextBit
Definition: bitfield.h:143
static constexpr T decode(S value)
Definition: bitfield.h:171
static constexpr S update(T value, S original)
Definition: bitfield.h:188
ClearProfileVisitor(Isolate *isolate)
Definition: profiler.cc:993
virtual void VisitSample(Sample *sample)
Definition: profiler.cc:996
int64_t CompileTimestamp() const
Definition: profiler.cc:1474
CodeDescriptor(const AbstractCode code)
Definition: profiler.cc:1464
uword Start() const
Definition: profiler.cc:1466
bool Contains(uword pc) const
Definition: profiler.h:512
const AbstractCode code() const
Definition: profiler.h:508
static int Compare(CodeDescriptor *const *a, CodeDescriptor *const *b)
Definition: profiler.h:517
const char * Name() const
Definition: profiler.h:510
uword Size() const
Definition: profiler.cc:1470
intptr_t length() const
Definition: profiler.h:544
CodeLookupTable(Thread *thread)
Definition: profiler.cc:1478
const CodeDescriptor * At(intptr_t index) const
Definition: profiler.h:546
const CodeDescriptor * FindCode(uword pc) const
Definition: profiler.cc:1550
static const char * LookupSymbolName(uword pc, uword *start)
static void FreeSymbolName(const char *name)
static const ThreadId kInvalidThreadId
Definition: os_thread.h:248
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
@ kUserVisibleName
Definition: object.h:645
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
bool IsNull() const
Definition: object.h:363
ProcessedSample * At(intptr_t index)
Definition: profiler.h:891
intptr_t length() const
Definition: profiler.h:889
const CodeLookupTable & code_lookup_table() const
Definition: profiler.h:893
void Add(ProcessedSample *sample)
Definition: profiler.h:887
uword user_tag() const
Definition: profiler.h:830
bool truncated() const
Definition: profiler.h:849
intptr_t length() const
Definition: profiler.h:809
void set_tid(ThreadId tid)
Definition: profiler.h:823
void set_allocation_cid(intptr_t cid)
Definition: profiler.h:835
uword At(intptr_t index) const
Definition: profiler.h:812
ThreadId tid() const
Definition: profiler.h:822
void set_truncated(bool truncated)
Definition: profiler.h:850
bool first_frame_executing() const
Definition: profiler.h:853
void Add(uword pc)
Definition: profiler.h:803
void set_first_frame_executing(bool first_frame_executing)
Definition: profiler.h:854
void set_timestamp(int64_t timestamp)
Definition: profiler.h:820
int64_t timestamp() const
Definition: profiler.h:819
bool IsAllocationSample() const
Definition: profiler.h:846
uint32_t allocation_identity_hash() const
Definition: profiler.h:839
void set_vm_tag(uword tag)
Definition: profiler.h:827
void InsertAt(intptr_t index, uword pc)
Definition: profiler.h:806
void set_allocation_identity_hash(uint32_t hash)
Definition: profiler.h:842
uword vm_tag() const
Definition: profiler.h:826
void set_user_tag(uword tag)
Definition: profiler.h:831
intptr_t allocation_cid() const
Definition: profiler.h:834
static void DumpStackTrace(void *context)
Definition: profiler.cc:417
static void IsolateShutdown(Thread *thread)
Definition: profiler.cc:1854
static void SampleAllocation(Thread *thread, intptr_t cid, uint32_t identity_hash)
Definition: profiler.cc:1271
static void SetSampleDepth(intptr_t depth)
Definition: profiler.cc:625
static intptr_t Size()
Definition: profiler.h:787
static ProfilerCounters counters()
Definition: profiler.h:91
static void UpdateRunningState()
Definition: profiler.cc:617
static void Cleanup()
Definition: profiler.cc:605
static void set_sample_block_buffer(SampleBlockBuffer *buffer)
Definition: profiler.h:70
static void SampleThread(Thread *thread, const InterruptedThreadState &state)
Definition: profiler.cc:1354
static void Init()
Definition: profiler.cc:573
static void ProcessCompletedBlocks(Isolate *isolate)
Definition: profiler.cc:1837
static SampleBlockBuffer * sample_block_buffer()
Definition: profiler.h:67
static void UpdateSamplePeriod()
Definition: profiler.cc:666
static void SetSamplePeriod(intptr_t period)
Definition: profiler.cc:656
virtual ~SampleBlockBuffer()
Definition: profiler.cc:690
SampleBlockBuffer(intptr_t blocks=kDefaultBlockCount, intptr_t samples_per_block=SampleBlock::kSamplesPerBlock)
Definition: profiler.cc:670
intptr_t Size() const
Definition: profiler.h:761
ProcessedSampleBuffer * BuildProcessedSampleBuffer(Isolate *isolate, SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
Definition: profiler.cc:761
static constexpr intptr_t kDefaultBlockCount
Definition: profiler.h:730
void VisitSamples(SampleVisitor *visitor)
Definition: profiler.h:742
Sample * ReserveAllocationSample(Isolate *isolate)
Definition: profiler.cc:821
Sample * ReserveCPUSample(Isolate *isolate)
Definition: profiler.cc:817
void StreamingToFree()
Definition: profiler.h:691
bool HasStreamableSamples(const GrowableObjectArray &tag_table, UserTag *tag)
Definition: profiler.cc:730
SampleBlock()=default
RelaxedAtomic< uint32_t > cursor_
Definition: profiler.h:718
virtual ~SampleBlock()=default
Isolate * owner() const
Definition: profiler.h:645
intptr_t capacity() const
Definition: profiler.h:643
friend class SampleBlockListProcessor
Definition: profiler.h:722
void FreeCompleted()
Definition: profiler.h:697
void MarkCompleted()
Definition: profiler.h:672
std::atomic< State > state_
Definition: profiler.h:717
static constexpr intptr_t kSamplesPerBlock
Definition: profiler.h:637
virtual Sample * ReserveSampleAndLink(Sample *previous)
Definition: profiler.cc:799
bool TryAllocateCompleted()
Definition: profiler.h:659
void StreamingToCompleted()
Definition: profiler.h:687
Isolate * owner_
Definition: profiler.h:719
virtual Sample * ReserveSample()
Definition: profiler.cc:791
bool TryAcquireStreaming(Isolate *isolate)
Definition: profiler.h:676
void set_owner(Isolate *isolate)
Definition: profiler.h:646
bool TryAllocateFree()
Definition: profiler.h:651
ProcessedSample * BuildProcessedSample(Sample *sample, const CodeLookupTable &clt)
Definition: profiler.cc:1635
virtual ~SampleBuffer()=default
void VisitSamples(SampleVisitor *visitor)
Definition: profiler.h:577
Sample * Next(Sample *sample)
Definition: profiler.cc:1679
ProcessedSampleBuffer * BuildProcessedSampleBuffer(SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
Definition: profiler.cc:1580
intptr_t capacity_
Definition: profiler.h:629
intptr_t capacity() const
Definition: profiler.h:616
virtual void Init(Sample *samples, intptr_t capacity)
Definition: profiler.h:570
virtual Sample * ReserveSampleAndLink(Sample *previous)=0
SampleBuffer()=default
Sample * samples_
Definition: profiler.h:628
Sample * At(intptr_t idx) const
Definition: profiler.h:610
DISALLOW_COPY_AND_ASSIGN(SampleBuffer)
virtual Sample * ReserveSample()=0
SampleFilter(Dart_Port port, intptr_t thread_task_mask, int64_t time_origin_micros, int64_t time_extent_micros, bool take_samples=false)
Definition: profiler.h:147
static constexpr intptr_t kNoTaskFilter
Definition: profiler.h:177
virtual bool FilterSample(Sample *sample)
Definition: profiler.h:165
bool TimeFilterSample(Sample *sample)
Definition: profiler.cc:975
Dart_Port port() const
Definition: profiler.h:167
bool take_samples() const
Definition: profiler.h:175
bool TaskFilterSample(Sample *sample)
Definition: profiler.cc:985
virtual ~SampleFilter()
Definition: profiler.h:161
intptr_t visited() const
Definition: profiler.h:132
virtual ~SampleVisitor()
Definition: profiler.h:126
virtual void Reset()
Definition: profiler.h:130
virtual void VisitSample(Sample *sample)=0
SampleVisitor(Dart_Port port)
Definition: profiler.h:125
Dart_Port port() const
Definition: profiler.h:136
void IncrementVisited()
Definition: profiler.h:134
void set_thread_task(Thread::TaskKind task)
Definition: profiler.h:324
uword * GetStackBuffer()
Definition: profiler.h:366
Thread::TaskKind thread_task() const
Definition: profiler.h:322
static constexpr int kPCArraySizeInWords
Definition: profiler.h:362
ThreadId tid() const
Definition: profiler.h:210
Sample * continuation_sample() const
Definition: profiler.h:339
uword At(intptr_t i) const
Definition: profiler.h:237
bool is_continuation_sample() const
Definition: profiler.h:328
void set_allocation_identity_hash(uint32_t hash)
Definition: profiler.h:318
void set_is_allocation_sample(bool allocation_sample)
Definition: profiler.h:310
void set_truncated_trace(bool truncated_trace)
Definition: profiler.h:302
void Init(Dart_Port port, int64_t timestamp, ThreadId tid)
Definition: profiler.h:199
uword pc() const
Definition: profiler.h:234
void set_vm_tag(uword tag)
Definition: profiler.h:266
void set_missing_frame_inserted(bool missing_frame_inserted)
Definition: profiler.h:296
bool is_allocation_sample() const
Definition: profiler.h:306
intptr_t allocation_cid() const
Definition: profiler.h:341
void SetContinuation(Sample *next)
Definition: profiler.h:332
void SetAllocationCid(intptr_t cid)
Definition: profiler.h:357
int64_t timestamp() const
Definition: profiler.h:231
uword vm_tag() const
Definition: profiler.h:265
Sample()=default
uword user_tag() const
Definition: profiler.h:271
bool missing_frame_inserted() const
Definition: profiler.h:292
void DumpStackTrace()
Definition: profiler.h:250
static constexpr int kStackBufferSizeInWords
Definition: profiler.h:365
void set_head_sample(bool head_sample)
Definition: profiler.h:346
Dart_Port port() const
Definition: profiler.h:207
uword * GetPCArray()
Definition: profiler.h:363
void set_user_tag(uword tag)
Definition: profiler.h:272
bool ignore_sample() const
Definition: profiler.h:280
void set_leaf_frame_is_dart(bool leaf_frame_is_dart)
Definition: profiler.h:276
bool leaf_frame_is_dart() const
Definition: profiler.h:274
bool exit_frame_sample() const
Definition: profiler.h:286
void set_ignore_sample(bool ignore_sample)
Definition: profiler.h:282
void set_exit_frame_sample(bool exit_frame_sample)
Definition: profiler.h:288
void SetAt(intptr_t i, uword pc)
Definition: profiler.h:244
intptr_t metadata() const
Definition: profiler.h:352
uint32_t allocation_identity_hash() const
Definition: profiler.h:314
void set_metadata(intptr_t metadata)
Definition: profiler.h:353
bool truncated_trace() const
Definition: profiler.h:300
void Clear()
Definition: profiler.h:212
bool head_sample() const
Definition: profiler.h:350
static constexpr uword kDefaultUserTag
Definition: tags.h:112
@ kInvalidTagId
Definition: tags.h:38
intptr_t size() const
#define ILLEGAL_PORT
Definition: dart_api.h:1535
int64_t Dart_Port
Definition: dart_api.h:1525
#define ASSERT(E)
static bool b
struct MyStruct a[10]
AtkStateType state
glong glong end
size_t length
Definition: dart_vm.cc:33
pthread_t ThreadJoinId
uintptr_t uword
Definition: globals.h:501
const uint32_t fp
const intptr_t cid
pthread_t ThreadId
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define Pp
Definition: globals.h:425
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
#define DECLARE_PROFILER_COUNTER(name)
Definition: profiler.h:48
#define PROFILER_COUNTERS(V)
Definition: profiler.h:32