Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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 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
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
291
293 return MissingFrameInsertedBit::decode(state_);
294 }
295
299
300 bool truncated_trace() const { return TruncatedTraceBit::decode(state_); }
301
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 enum StateBits {
370 kHeadSampleBit = 0,
371 kLeafFrameIsDartBit = 1,
372 kIgnoreBit = 2,
373 kExitFrameBit = 3,
374 kMissingFrameInsertedBit = 4,
375 kTruncatedTraceBit = 5,
376 kClassAllocationSampleBit = 6,
377 kContinuationSampleBit = 7,
378 kThreadTaskBit = 8, // 7 bits.
379 kMetadataBit = 15, // 16 bits.
380 kNextFreeBit = 31,
381 };
382 class HeadSampleBit : public BitField<uint32_t, bool, kHeadSampleBit, 1> {};
383 class LeafFrameIsDart
384 : public BitField<uint32_t, bool, kLeafFrameIsDartBit, 1> {};
385 class IgnoreBit : public BitField<uint32_t, bool, kIgnoreBit, 1> {};
386 class ExitFrameBit : public BitField<uint32_t, bool, kExitFrameBit, 1> {};
387 class MissingFrameInsertedBit
388 : public BitField<uint32_t, bool, kMissingFrameInsertedBit, 1> {};
389 class TruncatedTraceBit
390 : public BitField<uint32_t, bool, kTruncatedTraceBit, 1> {};
391 class ClassAllocationSampleBit
392 : public BitField<uint32_t, bool, kClassAllocationSampleBit, 1> {};
393 class ContinuationSampleBit
394 : public BitField<uint32_t, bool, kContinuationSampleBit, 1> {};
395 class ThreadTaskBit
396 : public BitField<uint32_t, Thread::TaskKind, kThreadTaskBit, 7> {};
397 class MetadataBits : public BitField<uint32_t, intptr_t, kMetadataBit, 16> {};
398
399 int64_t timestamp_;
400 Dart_Port port_;
401 ThreadId tid_;
402 uword stack_buffer_[kStackBufferSizeInWords];
403 uword pc_array_[kPCArraySizeInWords];
404 uword vm_tag_;
405 uword user_tag_;
406 uint32_t state_;
407 Sample* next_;
408 uint32_t allocation_identity_hash_;
409
411};
412
414 public:
415 explicit AbstractCode(ObjectPtr code) : code_(Object::Handle(code)) {
416 ASSERT(code_.IsNull() || code_.IsCode());
417 }
418
419 ObjectPtr ptr() const { return code_.ptr(); }
420 const Object* handle() const { return &code_; }
421
423 ASSERT(code_.IsCode());
424 return Code::Cast(code_).PayloadStart();
425 }
426
427 uword Size() const {
428 ASSERT(code_.IsCode());
429 return Code::Cast(code_).Size();
430 }
431
432 int64_t compile_timestamp() const {
433 if (code_.IsCode()) {
434 return Code::Cast(code_).compile_timestamp();
435 } else {
436 return 0;
437 }
438 }
439
440 const char* Name() const {
441 if (code_.IsCode()) {
442 return Code::Cast(code_).Name();
443 } else {
444 return "";
445 }
446 }
447
448 const char* QualifiedName() const {
449 if (code_.IsCode()) {
450 return Code::Cast(code_).QualifiedName(
452 } else {
453 return "";
454 }
455 }
456
457 bool IsStubCode() const {
458 if (code_.IsCode()) {
459 return Code::Cast(code_).IsStubCode();
460 } else {
461 return false;
462 }
463 }
464
465 bool IsAllocationStubCode() const {
466 if (code_.IsCode()) {
467 return Code::Cast(code_).IsAllocationStubCode();
468 } else {
469 return false;
470 }
471 }
472
473 bool IsTypeTestStubCode() const {
474 if (code_.IsCode()) {
475 return Code::Cast(code_).IsTypeTestStubCode();
476 } else {
477 return false;
478 }
479 }
480
481 ObjectPtr owner() const {
482 if (code_.IsCode()) {
483 return Code::Cast(code_).owner();
484 } else {
485 return Object::null();
486 }
487 }
488
489 bool IsNull() const { return code_.IsNull(); }
490 bool IsCode() const { return code_.IsCode(); }
491
492 bool is_optimized() const {
493 if (code_.IsCode()) {
494 return Code::Cast(code_).is_optimized();
495 } else {
496 return false;
497 }
498 }
499
500 private:
501 const Object& code_;
502};
503
504// A Code object descriptor.
506 public:
507 explicit CodeDescriptor(const AbstractCode code);
508
509 uword Start() const;
510
511 uword Size() const;
512
513 int64_t CompileTimestamp() const;
514
515 const AbstractCode code() const { return code_; }
516
517 const char* Name() const { return code_.Name(); }
518
519 bool Contains(uword pc) const {
520 uword end = Start() + Size();
521 return (pc >= Start()) && (pc < end);
522 }
523
524 static int Compare(CodeDescriptor* const* a, CodeDescriptor* const* b) {
525 ASSERT(a != nullptr);
526 ASSERT(b != nullptr);
527
528 uword a_start = (*a)->Start();
529 uword b_start = (*b)->Start();
530
531 if (a_start < b_start) {
532 return -1;
533 } else if (a_start > b_start) {
534 return 1;
535 } else {
536 return 0;
537 }
538 }
539
540 private:
541 const AbstractCode code_;
542
544};
545
546// Fast lookup of Dart code objects.
548 public:
549 explicit CodeLookupTable(Thread* thread);
550
551 intptr_t length() const { return code_objects_.length(); }
552
553 const CodeDescriptor* At(intptr_t index) const {
554 return code_objects_.At(index);
555 }
556
557 const CodeDescriptor* FindCode(uword pc) const;
558
559 private:
560 void Build(Thread* thread);
561
562 void Add(const Object& code);
563
564 // Code objects sorted by entry.
566
568
570};
571
573 public:
574 SampleBuffer() = default;
575 virtual ~SampleBuffer() = default;
576
577 virtual void Init(Sample* samples, intptr_t capacity) {
578 ASSERT(samples != nullptr);
579 ASSERT(capacity > 0);
580 samples_ = samples;
582 }
583
585 ASSERT(visitor != nullptr);
586 const intptr_t length = capacity();
587 for (intptr_t i = 0; i < length; i++) {
588 Sample* sample = At(i);
589 if (!sample->head_sample()) {
590 // An inner sample in a chain of samples.
591 continue;
592 }
593 if (sample->ignore_sample()) {
594 // Bad sample.
595 continue;
596 }
597 if (sample->port() != visitor->port()) {
598 // Another isolate.
599 continue;
600 }
601 if (sample->timestamp() == 0) {
602 // Empty.
603 continue;
604 }
605 if (sample->At(0) == 0) {
606 // No frames.
607 continue;
608 }
609 visitor->IncrementVisited();
610 visitor->VisitSample(sample);
611 }
612 }
613
614 virtual Sample* ReserveSample() = 0;
615 virtual Sample* ReserveSampleAndLink(Sample* previous) = 0;
616
617 Sample* At(intptr_t idx) const {
618 ASSERT(idx >= 0);
619 ASSERT(idx < capacity_);
620 return &samples_[idx];
621 }
622
623 intptr_t capacity() const { return capacity_; }
624
626 SampleFilter* filter,
627 ProcessedSampleBuffer* buffer = nullptr);
628
629 protected:
630 Sample* Next(Sample* sample);
631
633 const CodeLookupTable& clt);
634
636 intptr_t capacity_;
637
639};
640
641class SampleBlock : public SampleBuffer {
642 public:
643 // The default number of samples per block. Overridden by some tests.
644 static constexpr intptr_t kSamplesPerBlock = 100;
645
646 SampleBlock() = default;
647 virtual ~SampleBlock() = default;
648
649 // Returns the number of samples contained within this block.
650 intptr_t capacity() const { return capacity_; }
651
652 Isolate* owner() const { return owner_; }
653 void set_owner(Isolate* isolate) { owner_ = isolate; }
654
655 virtual Sample* ReserveSample();
656 virtual Sample* ReserveSampleAndLink(Sample* previous);
657
659 State expected = kFree;
660 State desired = kSampling;
661 std::memory_order success_order = std::memory_order_acquire;
662 std::memory_order failure_order = std::memory_order_relaxed;
663 return state_.compare_exchange_strong(expected, desired, success_order,
664 failure_order);
665 }
667 State expected = kCompleted;
668 State desired = kSampling;
669 std::memory_order success_order = std::memory_order_acquire;
670 std::memory_order failure_order = std::memory_order_relaxed;
671 if (state_.compare_exchange_strong(expected, desired, success_order,
672 failure_order)) {
673 owner_ = nullptr;
674 cursor_ = 0;
675 return true;
676 }
677 return false;
678 }
680 ASSERT(state_.load(std::memory_order_relaxed) == kSampling);
681 state_.store(kCompleted, std::memory_order_release);
682 }
684 if (state_.load(std::memory_order_relaxed) != kCompleted) return false;
685 if (owner_ != isolate) return false;
686
687 State expected = kCompleted;
688 State desired = kStreaming;
689 std::memory_order success_order = std::memory_order_acquire;
690 std::memory_order failure_order = std::memory_order_relaxed;
691 return state_.compare_exchange_strong(expected, desired, success_order,
692 failure_order);
693 }
695 ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
696 state_.store(kCompleted, std::memory_order_relaxed);
697 }
699 ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
700 owner_ = nullptr;
701 cursor_ = 0;
702 state_.store(kFree, std::memory_order_release);
703 }
705 State expected = kCompleted;
706 State desired = kStreaming;
707 std::memory_order success_order = std::memory_order_acquire;
708 std::memory_order failure_order = std::memory_order_relaxed;
709 if (state_.compare_exchange_strong(expected, desired, success_order,
710 failure_order)) {
712 }
713 }
714
715 protected:
716 bool HasStreamableSamples(const GrowableObjectArray& tag_table, UserTag* tag);
717
718 enum State : uint32_t {
720 kSampling, // I.e., writing.
722 kStreaming, // I.e., reading.
723 };
724 std::atomic<State> state_ = kFree;
726 Isolate* owner_ = nullptr;
727
728 private:
730 friend class SampleBlockBuffer;
731
733};
734
736 public:
737 static constexpr intptr_t kDefaultBlockCount = 600;
738
739 // Creates a SampleBlockBuffer with a predetermined number of blocks.
740 //
741 // Defaults to kDefaultBlockCount blocks. Block size is fixed to
742 // SampleBlock::kSamplesPerBlock samples per block, except for in tests.
743 explicit SampleBlockBuffer(
744 intptr_t blocks = kDefaultBlockCount,
745 intptr_t samples_per_block = SampleBlock::kSamplesPerBlock);
746
747 virtual ~SampleBlockBuffer();
748
750 ASSERT(visitor != nullptr);
751 for (intptr_t i = 0; i < capacity_; ++i) {
752 blocks_[i].VisitSamples(visitor);
753 }
754 }
755
756 void FreeCompletedBlocks();
757
758 // Reserves a sample for a CPU profile.
759 //
760 // Returns nullptr when a sample can't be reserved.
762
763 // Reserves a sample for a Dart object allocation profile.
764 //
765 // Returns nullptr when a sample can't be reserved.
767
768 intptr_t Size() const { return memory_->size(); }
769
771 Isolate* isolate,
772 SampleFilter* filter,
773 ProcessedSampleBuffer* buffer = nullptr);
774
775 private:
776 Sample* ReserveSampleImpl(Isolate* isolate, bool allocation_sample);
777
778 // Returns nullptr if there are no available blocks.
779 SampleBlock* ReserveSampleBlock();
780
781 // Sample block management.
782 RelaxedAtomic<int> cursor_;
783 SampleBlock* blocks_;
784 intptr_t capacity_;
785
786 // Sample buffer management.
787 VirtualMemory* memory_;
788 Sample* sample_buffer_;
789
790 friend class Isolate;
792};
793
794intptr_t Profiler::Size() {
795 intptr_t size = 0;
796 if (sample_block_buffer_ != nullptr) {
797 size += sample_block_buffer_->Size();
798 }
799 return size;
800}
801
802// A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have
803// been merged into a logical sample. The raw data may have been processed to
804// improve the quality of the stack trace.
806 public:
808
809 // Add |pc| to stack trace.
810 void Add(uword pc) { pcs_.Add(pc); }
811
812 // Insert |pc| at |index|.
813 void InsertAt(intptr_t index, uword pc) { pcs_.InsertAt(index, pc); }
814
815 // Number of pcs in stack trace.
816 intptr_t length() const { return pcs_.length(); }
817
818 // Get |pc| at |index|.
819 uword At(intptr_t index) const {
820 ASSERT(index >= 0);
821 ASSERT(index < length());
822 return pcs_[index];
823 }
824
825 // Timestamp sample was taken at.
826 int64_t timestamp() const { return timestamp_; }
827 void set_timestamp(int64_t timestamp) { timestamp_ = timestamp; }
828
829 ThreadId tid() const { return tid_; }
830 void set_tid(ThreadId tid) { tid_ = tid; }
831
832 // The VM tag.
833 uword vm_tag() const { return vm_tag_; }
834 void set_vm_tag(uword tag) { vm_tag_ = tag; }
835
836 // The user tag.
837 uword user_tag() const { return user_tag_; }
838 void set_user_tag(uword tag) { user_tag_ = tag; }
839
840 // The class id if this is an allocation profile sample. -1 otherwise.
841 intptr_t allocation_cid() const { return allocation_cid_; }
842 void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; }
843
844 // The identity hash code of the allocated object if this is an allocation
845 // profile sample. -1 otherwise.
846 uint32_t allocation_identity_hash() const {
847 return allocation_identity_hash_;
848 }
850 allocation_identity_hash_ = hash;
851 }
852
853 bool IsAllocationSample() const { return allocation_cid_ > 0; }
854
855 // Was the stack trace truncated?
856 bool truncated() const { return truncated_; }
857 void set_truncated(bool truncated) { truncated_ = truncated; }
858
859 // Was the first frame in the stack trace executing?
860 bool first_frame_executing() const { return first_frame_executing_; }
862 first_frame_executing_ = first_frame_executing;
863 }
864
865 private:
866 void FixupCaller(const CodeLookupTable& clt,
867 uword pc_marker,
868 uword* stack_buffer);
869
870 void CheckForMissingDartFrame(const CodeLookupTable& clt,
871 const CodeDescriptor* code,
872 uword pc_marker,
873 uword* stack_buffer);
874
876 int64_t timestamp_;
877 ThreadId tid_;
878 uword vm_tag_;
879 uword user_tag_;
880 intptr_t allocation_cid_;
881 uint32_t allocation_identity_hash_;
882 bool truncated_;
883 bool first_frame_executing_;
884
885 friend class SampleBuffer;
887};
888
889// A collection of |ProcessedSample|s.
891 public:
893
894 void Add(ProcessedSample* sample) { samples_.Add(sample); }
895
896 intptr_t length() const { return samples_.length(); }
897
898 ProcessedSample* At(intptr_t index) { return samples_.At(index); }
899
901 return *code_lookup_table_;
902 }
903
904 private:
906 CodeLookupTable* code_lookup_table_;
907
909};
910
912 public:
913 static void Init();
914
915 static void Startup();
916 static void Cleanup();
917
918 private:
919 static constexpr intptr_t kMaxThreads = 4096;
920 static bool initialized_;
921 static bool shutdown_;
922 static bool thread_running_;
923 static ThreadJoinId processor_thread_id_;
924 static Monitor* monitor_;
925
926 static void ThreadMain(uword parameters);
927};
928
929} // namespace dart
930
931#endif // RUNTIME_VM_PROFILER_H_
static float next(float f)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
bool IsAllocationStubCode() const
Definition profiler.h:465
bool IsNull() const
Definition profiler.h:489
AbstractCode(ObjectPtr code)
Definition profiler.h:415
const char * QualifiedName() const
Definition profiler.h:448
bool IsCode() const
Definition profiler.h:490
uword Size() const
Definition profiler.h:427
bool IsStubCode() const
Definition profiler.h:457
const Object * handle() const
Definition profiler.h:420
const char * Name() const
Definition profiler.h:440
bool IsTypeTestStubCode() const
Definition profiler.h:473
ObjectPtr owner() const
Definition profiler.h:481
bool is_optimized() const
Definition profiler.h:492
ObjectPtr ptr() const
Definition profiler.h:419
uword PayloadStart() const
Definition profiler.h:422
int64_t compile_timestamp() const
Definition profiler.h:432
void InsertAt(intptr_t idx, const T &value)
void Add(const T &value)
intptr_t length() const
static constexpr bool decode(uint32_t value)
Definition bitfield.h:173
static constexpr uint32_t update(bool value, uint32_t original)
Definition bitfield.h:190
virtual void VisitSample(Sample *sample)
Definition profiler.cc:990
int64_t CompileTimestamp() const
Definition profiler.cc:1468
uword Start() const
Definition profiler.cc:1460
bool Contains(uword pc) const
Definition profiler.h:519
const AbstractCode code() const
Definition profiler.h:515
static int Compare(CodeDescriptor *const *a, CodeDescriptor *const *b)
Definition profiler.h:524
const char * Name() const
Definition profiler.h:517
uword Size() const
Definition profiler.cc:1464
intptr_t length() const
Definition profiler.h:551
const CodeDescriptor * At(intptr_t index) const
Definition profiler.h:553
const CodeDescriptor * FindCode(uword pc) const
Definition profiler.cc:1544
static void FreeSymbolName(char *name)
static char * LookupSymbolName(uword pc, uword *start)
static const ThreadId kInvalidThreadId
Definition os_thread.h:244
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:898
intptr_t length() const
Definition profiler.h:896
const CodeLookupTable & code_lookup_table() const
Definition profiler.h:900
void Add(ProcessedSample *sample)
Definition profiler.h:894
uword user_tag() const
Definition profiler.h:837
bool truncated() const
Definition profiler.h:856
intptr_t length() const
Definition profiler.h:816
void set_tid(ThreadId tid)
Definition profiler.h:830
void set_allocation_cid(intptr_t cid)
Definition profiler.h:842
uword At(intptr_t index) const
Definition profiler.h:819
ThreadId tid() const
Definition profiler.h:829
void set_truncated(bool truncated)
Definition profiler.h:857
bool first_frame_executing() const
Definition profiler.h:860
void Add(uword pc)
Definition profiler.h:810
void set_first_frame_executing(bool first_frame_executing)
Definition profiler.h:861
void set_timestamp(int64_t timestamp)
Definition profiler.h:827
int64_t timestamp() const
Definition profiler.h:826
bool IsAllocationSample() const
Definition profiler.h:853
uint32_t allocation_identity_hash() const
Definition profiler.h:846
void set_vm_tag(uword tag)
Definition profiler.h:834
void InsertAt(intptr_t index, uword pc)
Definition profiler.h:813
void set_allocation_identity_hash(uint32_t hash)
Definition profiler.h:849
uword vm_tag() const
Definition profiler.h:833
void set_user_tag(uword tag)
Definition profiler.h:838
intptr_t allocation_cid() const
Definition profiler.h:841
static void DumpStackTrace(void *context)
Definition profiler.cc:409
static void IsolateShutdown(Thread *thread)
Definition profiler.cc:1848
static void SampleAllocation(Thread *thread, intptr_t cid, uint32_t identity_hash)
Definition profiler.cc:1265
static void SetSampleDepth(intptr_t depth)
Definition profiler.cc:619
static intptr_t Size()
Definition profiler.h:794
static ProfilerCounters counters()
Definition profiler.h:91
static void UpdateRunningState()
Definition profiler.cc:611
static void Cleanup()
Definition profiler.cc:599
static void set_sample_block_buffer(SampleBlockBuffer *buffer)
Definition profiler.h:70
static void SampleThread(Thread *thread, const InterruptedThreadState &state)
Definition profiler.cc:1348
static void Init()
Definition profiler.cc:567
static void ProcessCompletedBlocks(Isolate *isolate)
Definition profiler.cc:1831
static SampleBlockBuffer * sample_block_buffer()
Definition profiler.h:67
static void UpdateSamplePeriod()
Definition profiler.cc:660
static void SetSamplePeriod(intptr_t period)
Definition profiler.cc:650
void store(T arg, std::memory_order order=std::memory_order_relaxed)
Definition atomic.h:27
virtual ~SampleBlockBuffer()
Definition profiler.cc:684
intptr_t Size() const
Definition profiler.h:768
ProcessedSampleBuffer * BuildProcessedSampleBuffer(Isolate *isolate, SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
Definition profiler.cc:755
static constexpr intptr_t kDefaultBlockCount
Definition profiler.h:737
void VisitSamples(SampleVisitor *visitor)
Definition profiler.h:749
Sample * ReserveAllocationSample(Isolate *isolate)
Definition profiler.cc:815
Sample * ReserveCPUSample(Isolate *isolate)
Definition profiler.cc:811
void StreamingToFree()
Definition profiler.h:698
bool HasStreamableSamples(const GrowableObjectArray &tag_table, UserTag *tag)
Definition profiler.cc:724
SampleBlock()=default
RelaxedAtomic< uint32_t > cursor_
Definition profiler.h:725
virtual ~SampleBlock()=default
Isolate * owner() const
Definition profiler.h:652
intptr_t capacity() const
Definition profiler.h:650
friend class SampleBlockListProcessor
Definition profiler.h:729
void FreeCompleted()
Definition profiler.h:704
void MarkCompleted()
Definition profiler.h:679
std::atomic< State > state_
Definition profiler.h:724
static constexpr intptr_t kSamplesPerBlock
Definition profiler.h:644
virtual Sample * ReserveSampleAndLink(Sample *previous)
Definition profiler.cc:793
bool TryAllocateCompleted()
Definition profiler.h:666
void StreamingToCompleted()
Definition profiler.h:694
Isolate * owner_
Definition profiler.h:726
virtual Sample * ReserveSample()
Definition profiler.cc:785
bool TryAcquireStreaming(Isolate *isolate)
Definition profiler.h:683
void set_owner(Isolate *isolate)
Definition profiler.h:653
bool TryAllocateFree()
Definition profiler.h:658
ProcessedSample * BuildProcessedSample(Sample *sample, const CodeLookupTable &clt)
Definition profiler.cc:1629
virtual ~SampleBuffer()=default
void VisitSamples(SampleVisitor *visitor)
Definition profiler.h:584
Sample * Next(Sample *sample)
Definition profiler.cc:1673
ProcessedSampleBuffer * BuildProcessedSampleBuffer(SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
Definition profiler.cc:1574
intptr_t capacity_
Definition profiler.h:636
intptr_t capacity() const
Definition profiler.h:623
virtual void Init(Sample *samples, intptr_t capacity)
Definition profiler.h:577
virtual Sample * ReserveSampleAndLink(Sample *previous)=0
SampleBuffer()=default
Sample * samples_
Definition profiler.h:635
Sample * At(intptr_t idx) const
Definition profiler.h:617
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:969
Dart_Port port() const
Definition profiler.h:167
bool take_samples() const
Definition profiler.h:175
bool TaskFilterSample(Sample *sample)
Definition profiler.cc:979
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:1530
int64_t Dart_Port
Definition dart_api.h:1524
#define ASSERT(E)
static bool b
struct MyStruct a[10]
AtkStateType state
glong glong end
static const uint8_t buffer[]
size_t length
pthread_t ThreadJoinId
uintptr_t uword
Definition globals.h:501
const uint32_t fp
const intptr_t cid
pthread_t ThreadId
#define Pp
Definition globals.h:425
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition globals.h:593
#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