Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
dart::HeapProfileSampler Class Reference

#include <sampler.h>

Public Member Functions

 HeapProfileSampler (Thread *thread)
 
void Initialize ()
 
void Cleanup ()
 
void ScheduleUpdateThreadEnable ()
 
bool ShouldUpdateThreadEnable ()
 
void UpdateThreadEnable ()
 
void ScheduleSetThreadSamplingInterval ()
 
bool ShouldSetThreadSamplingInterval ()
 
void SetThreadSamplingInterval ()
 
void HandleReleasedTLAB (Thread *thread)
 
void HandleNewTLAB (intptr_t old_tlab_remaining_space, bool is_first_tlab)
 
void * InvokeCallbackForLastSample (intptr_t cid)
 
bool HasOutstandingSample () const
 
void SampleNewSpaceAllocation (intptr_t allocation_size)
 
void SampleOldSpaceAllocation (intptr_t allocation_size)
 

Static Public Member Functions

static void Enable (bool enabled)
 
static bool enabled ()
 
static void SetSamplingInterval (intptr_t bytes_interval)
 
static void SetSamplingCallback (Dart_HeapSamplingCreateCallback create_callback, Dart_HeapSamplingDeleteCallback delete_callback)
 
static Dart_HeapSamplingDeleteCallback delete_callback ()
 

Detailed Description

Definition at line 28 of file sampler.h.

Constructor & Destructor Documentation

◆ HeapProfileSampler()

dart::HeapProfileSampler::HeapProfileSampler ( Thread thread)
explicit

Definition at line 44 of file sampler.cc.

45 : interval_to_next_sample_(kUninitialized), thread_(thread) {}

Member Function Documentation

◆ Cleanup()

void dart::HeapProfileSampler::Cleanup ( )
inline

Definition at line 59 of file sampler.h.

59 {
60 ResetState();
61 last_sample_size_ = kUninitialized;
62 }

◆ delete_callback()

static Dart_HeapSamplingDeleteCallback dart::HeapProfileSampler::delete_callback ( )
inlinestatic

Definition at line 54 of file sampler.h.

54 {
55 return delete_callback_;
56 }

◆ Enable()

void dart::HeapProfileSampler::Enable ( bool  enabled)
static

Definition at line 47 of file sampler.cc.

47 {
48 // Don't try and change enabled state if sampler instances are currently
49 // doing work.
50 WriteRwLocker locker(Thread::Current(), lock_);
51 enabled_ = enabled;
52
53 IsolateGroup::ForEach([&](IsolateGroup* group) {
54 group->thread_registry()->ForEachThread([&](Thread* thread) {
55 thread->heap_sampler().ScheduleUpdateThreadEnable();
56 });
57 });
58}
void ScheduleUpdateThreadEnable()
Definition: sampler.cc:109
static bool enabled()
Definition: sampler.h:39
static void ForEach(std::function< void(IsolateGroup *)> action)
Definition: isolate.cc:683
static Thread * Current()
Definition: thread.h:362

◆ enabled()

static bool dart::HeapProfileSampler::enabled ( )
inlinestatic

Definition at line 39 of file sampler.h.

39{ return enabled_; }

◆ HandleNewTLAB()

void dart::HeapProfileSampler::HandleNewTLAB ( intptr_t  old_tlab_remaining_space,
bool  is_first_tlab 
)

Definition at line 162 of file sampler.cc.

163 {
164 ASSERT_THREAD_STATE(thread_);
165 ReadRwLocker locker(thread_, lock_);
166 if (!enabled_ || (next_tlab_offset_ == kUninitialized && !is_first_tlab)) {
167 return;
168 } else if (is_first_tlab) {
169 ASSERT(next_tlab_offset_ == kUninitialized);
170 if (interval_to_next_sample_ != kUninitialized) {
171 intptr_t top = thread_->top();
172 intptr_t tlab_size = thread_->true_end() - top;
173 if (tlab_size >= interval_to_next_sample_) {
174 thread_->set_end(top + interval_to_next_sample_);
176 } else {
177 next_tlab_offset_ = interval_to_next_sample_ - tlab_size;
179 }
180 } else {
181 SetThreadSamplingIntervalLocked();
182 }
183 return;
184 }
185 intptr_t updated_offset = next_tlab_offset_ + old_tlab_remaining_space;
186 if (updated_offset + thread_->top() > thread_->true_end()) {
187 // The next sampling point isn't in this TLAB.
188 next_tlab_offset_ = updated_offset - (thread_->true_end() - thread_->top());
189 thread_->set_end(thread_->true_end());
191 } else {
192 ASSERT(updated_offset <= static_cast<intptr_t>(thread_->true_end()) -
193 static_cast<intptr_t>(thread_->top()));
194 thread_->set_end(updated_offset + thread_->top());
195 next_tlab_offset_ = kUninitialized;
197 }
198}
void set_end(uword end)
Definition: thread.h:713
uword top() const
Definition: thread.h:709
uword true_end() const
Definition: thread.h:711
#define ASSERT(E)
#define ASSERT_THREAD_STATE(__thread)
Definition: sampler.cc:29
#define ASSERT_TLAB_BOUNDARIES_VALID(__thread)
Definition: sampler.cc:19

◆ HandleReleasedTLAB()

void dart::HeapProfileSampler::HandleReleasedTLAB ( Thread thread)

Definition at line 153 of file sampler.cc.

153 {
154 ReadRwLocker locker(thread, lock_);
155 if (!enabled_) {
156 return;
157 }
158 interval_to_next_sample_ = remaining_TLAB_interval();
159 next_tlab_offset_ = kUninitialized;
160}

◆ HasOutstandingSample()

bool dart::HeapProfileSampler::HasOutstandingSample ( ) const
inline

Definition at line 124 of file sampler.h.

124 {
125 return last_sample_size_ != kUninitialized;
126 }

◆ Initialize()

void dart::HeapProfileSampler::Initialize ( )

Definition at line 101 of file sampler.cc.

101 {
102 // Don't grab lock_ here as it can cause a deadlock if thread initialization
103 // occurs when the profiler state is being changed. Instead, let the thread
104 // perform initialization when it's no longer holding the thread registry's
105 // thread_lock().
107}

◆ InvokeCallbackForLastSample()

void * dart::HeapProfileSampler::InvokeCallbackForLastSample ( intptr_t  cid)

Definition at line 200 of file sampler.cc.

200 {
201 ASSERT(enabled_);
202 ASSERT(create_callback_ != nullptr);
203 ReadRwLocker locker(thread_, lock_);
204 ClassTable* table = IsolateGroup::Current()->class_table();
205 void* result = create_callback_(
206 reinterpret_cast<Dart_Isolate>(thread_->isolate()),
207 reinterpret_cast<Dart_IsolateGroup>(thread_->isolate_group()),
208 table->UserVisibleNameFor(cid), last_sample_size_);
209 last_sample_size_ = kUninitialized;
210 return result;
211}
SI F table(const skcms_Curve *curve, F v)
static IsolateGroup * Current()
Definition: isolate.h:539
ClassTable * class_table() const
Definition: isolate.h:496
Isolate * isolate() const
Definition: thread.h:534
IsolateGroup * isolate_group() const
Definition: thread.h:541
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
struct _Dart_IsolateGroup * Dart_IsolateGroup
Definition: dart_api.h:89
GAsyncResult * result
const intptr_t cid

◆ SampleNewSpaceAllocation()

void dart::HeapProfileSampler::SampleNewSpaceAllocation ( intptr_t  allocation_size)

Definition at line 213 of file sampler.cc.

213 {
214 ReadRwLocker locker(thread_, lock_);
215 if (!enabled_) {
216 return;
217 }
218 // We should never be sampling an allocation that won't fit in the
219 // current TLAB.
220 ASSERT(allocation_size <=
221 static_cast<intptr_t>(thread_->true_end() - thread_->top()));
222 ASSERT(sampling_interval_ >= 0);
223
224 // Clean up interval state in preparation for a new interval.
225 ResetIntervalState();
226
227 if (UNLIKELY(allocation_size >= sampling_interval_)) {
228 last_sample_size_ = allocation_size;
229 // Reset the sampling interval, but only count the sample once.
230 NumberOfSamplesLocked(allocation_size);
231 return;
232 }
233 last_sample_size_ =
234 sampling_interval_ * NumberOfSamplesLocked(allocation_size);
235}
#define UNLIKELY(cond)
Definition: globals.h:261

◆ SampleOldSpaceAllocation()

void dart::HeapProfileSampler::SampleOldSpaceAllocation ( intptr_t  allocation_size)

Definition at line 237 of file sampler.cc.

237 {
238 ASSERT_THREAD_STATE(thread_);
239 ReadRwLocker locker(thread_, lock_);
240 if (!enabled_) {
241 return;
242 }
243 ASSERT(sampling_interval_ >= 0);
244 // Account for any new space allocations that have happened since we last
245 // updated the sampling interval statistic.
246 intptr_t tlab_interval = remaining_TLAB_interval();
247 if (tlab_interval != kUninitialized) {
248 interval_to_next_sample_ = tlab_interval;
249 }
250
251 // If we don't have a TLAB yet simply initialize interval_to_next_sample_
252 // from the sampling interval.
253 if (interval_to_next_sample_ == kUninitialized) {
254 interval_to_next_sample_ = sampling_interval_;
255 }
256
257 // Check the allocation is large enough to trigger a sample. If not, tighten
258 // the interval.
259 if (allocation_size < interval_to_next_sample_) {
260 intptr_t end = static_cast<intptr_t>(thread_->end());
261 const intptr_t orig_end = end;
262 const intptr_t true_end = static_cast<intptr_t>(thread_->true_end());
263 const intptr_t orig_tlab_offset = next_tlab_offset_;
264 USE(orig_tlab_offset);
265 USE(orig_end);
266 // We may not have a TLAB, don't pull one out of thin air.
267 if (end != 0) {
268 if (next_tlab_offset_ != kUninitialized) {
269 end += next_tlab_offset_;
270 next_tlab_offset_ = kUninitialized;
271 }
272
273 end += allocation_size;
274 if (end > true_end) {
275 thread_->set_end(true_end);
276 next_tlab_offset_ = end - true_end;
278 } else {
279 thread_->set_end(end);
281 }
282 }
283 interval_to_next_sample_ -= allocation_size;
284 ASSERT(interval_to_next_sample_ > 0);
285 return;
286 }
287 // Clean up interval state in preparation for a new interval.
288 ResetIntervalState();
289
290 // Find a new sampling point and reset TLAB boundaries.
291 SetThreadSamplingIntervalLocked();
292 last_sample_size_ = allocation_size;
293}
uword end() const
Definition: thread.h:710
glong glong end
static void USE(T &&)
Definition: globals.h:618

◆ ScheduleSetThreadSamplingInterval()

void dart::HeapProfileSampler::ScheduleSetThreadSamplingInterval ( )

Definition at line 131 of file sampler.cc.

131 {
132 schedule_thread_set_sampling_interval_ = true;
134}
void ScheduleInterrupts(uword interrupt_bits)
Definition: thread.cc:710
@ kVMInterrupt
Definition: thread.h:488

◆ ScheduleUpdateThreadEnable()

void dart::HeapProfileSampler::ScheduleUpdateThreadEnable ( )

Definition at line 109 of file sampler.cc.

109 {
110 schedule_thread_enable_ = true;
112}

◆ SetSamplingCallback()

void dart::HeapProfileSampler::SetSamplingCallback ( Dart_HeapSamplingCreateCallback  create_callback,
Dart_HeapSamplingDeleteCallback  delete_callback 
)
static

Definition at line 81 of file sampler.cc.

83 {
84 // Protect against the callback being changed in the middle of a sample.
85 WriteRwLocker locker(Thread::Current(), lock_);
86 if ((create_callback_ != nullptr && create_callback == nullptr) ||
87 (delete_callback_ != nullptr && delete_callback == nullptr)) {
88 FATAL("Clearing sampling callbacks is prohibited.");
89 }
90 create_callback_ = create_callback;
91 delete_callback_ = delete_callback;
92}
static Dart_HeapSamplingDeleteCallback delete_callback()
Definition: sampler.h:54
#define FATAL(error)

◆ SetSamplingInterval()

void dart::HeapProfileSampler::SetSamplingInterval ( intptr_t  bytes_interval)
static

Definition at line 60 of file sampler.cc.

60 {
61 // Don't try and change sampling interval state if sampler instances are
62 // currently doing work.
63 WriteRwLocker locker(Thread::Current(), lock_);
64 ASSERT(bytes_interval >= 0);
65 sampling_interval_ = bytes_interval;
66
67 // The sampling interval will be set in each thread once sampling is enabled.
68 if (!enabled_) {
69 return;
70 }
71
72 // If sampling is enabled, notify each thread that it should update its
73 // sampling interval.
74 IsolateGroup::ForEach([&](IsolateGroup* group) {
75 group->thread_registry()->ForEachThread([&](Thread* thread) {
76 thread->heap_sampler().ScheduleSetThreadSamplingInterval();
77 });
78 });
79}
void ScheduleSetThreadSamplingInterval()
Definition: sampler.cc:131

◆ SetThreadSamplingInterval()

void dart::HeapProfileSampler::SetThreadSamplingInterval ( )

Definition at line 136 of file sampler.cc.

136 {
137 ASSERT_THREAD_STATE(thread_);
138 ReadRwLocker locker(thread_, lock_);
139 SetThreadSamplingIntervalLocked();
140}

◆ ShouldSetThreadSamplingInterval()

bool dart::HeapProfileSampler::ShouldSetThreadSamplingInterval ( )
inline

Definition at line 98 of file sampler.h.

98 {
99 return schedule_thread_set_sampling_interval_.exchange(false);
100 }

◆ ShouldUpdateThreadEnable()

bool dart::HeapProfileSampler::ShouldUpdateThreadEnable ( )
inline

Definition at line 76 of file sampler.h.

76 {
77 return schedule_thread_enable_.exchange(false);
78 }

◆ UpdateThreadEnable()

void dart::HeapProfileSampler::UpdateThreadEnable ( )

Definition at line 114 of file sampler.cc.

114 {
115 ASSERT_THREAD_STATE(thread_);
116 ReadRwLocker locker(Thread::Current(), lock_);
117 UpdateThreadEnableLocked();
118}

The documentation for this class was generated from the following files: