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

#include <profiler.h>

Inheritance diagram for dart::Profiler:
dart::AllStatic

Static Public Member Functions

static void Init ()
 
static void Cleanup ()
 
static void SetSampleDepth (intptr_t depth)
 
static void SetSamplePeriod (intptr_t period)
 
static void UpdateSamplePeriod ()
 
static void UpdateRunningState ()
 
static SampleBlockBuffersample_block_buffer ()
 
static void set_sample_block_buffer (SampleBlockBuffer *buffer)
 
static void DumpStackTrace (void *context)
 
static void DumpStackTrace (bool for_crash=true)
 
static void SampleAllocation (Thread *thread, intptr_t cid, uint32_t identity_hash)
 
static void SampleThread (Thread *thread, const InterruptedThreadState &state)
 
static ProfilerCounters counters ()
 
static intptr_t Size ()
 
static void ProcessCompletedBlocks (Isolate *isolate)
 
static void IsolateShutdown (Thread *thread)
 

Friends

class Thread
 

Detailed Description

Definition at line 53 of file profiler.h.

Member Function Documentation

◆ Cleanup()

void dart::Profiler::Cleanup ( )
static

Definition at line 605 of file profiler.cc.

605 {
606 if (!FLAG_profiler) {
607 return;
608 }
609 ASSERT(initialized_);
612 SampleBlockCleanupVisitor visitor;
613 Isolate::VisitIsolates(&visitor);
614 initialized_ = false;
615}
static void VisitIsolates(IsolateVisitor *visitor)
Definition: isolate.cc:3531
#define ASSERT(E)

◆ counters()

static ProfilerCounters dart::Profiler::counters ( )
inlinestatic

Definition at line 91 of file profiler.h.

91 {
92 // Copies the counter values.
93 return counters_;
94 }

◆ DumpStackTrace() [1/2]

void dart::Profiler::DumpStackTrace ( bool  for_crash = true)
static

Definition at line 458 of file profiler.cc.

458 {
459 uintptr_t sp = OSThread::GetCurrentStackPointer();
460 uintptr_t fp = 0;
461 uintptr_t pc = OS::GetProgramCounter();
462
464
465 DumpStackTrace(sp, fp, pc, for_crash);
466}
static uword GetCurrentStackPointer()
Definition: os_thread.cc:132
static uintptr_t GetProgramCounter()
static void DumpStackTrace(void *context)
Definition: profiler.cc:417
const uint32_t fp
#define COPY_FP_REGISTER(fp)
Definition: globals.h:200

◆ DumpStackTrace() [2/2]

void dart::Profiler::DumpStackTrace ( void *  context)
static

Definition at line 417 of file profiler.cc.

417 {
418 if (context == nullptr) {
419 DumpStackTrace(/*for_crash=*/true);
420 return;
421 }
422#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
423 defined(DART_HOST_OS_ANDROID)
424 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
425 mcontext_t mcontext = ucontext->uc_mcontext;
429 DumpStackTrace(sp, fp, pc, /*for_crash=*/true);
430#elif defined(DART_HOST_OS_WINDOWS)
431 CONTEXT* ctx = reinterpret_cast<CONTEXT*>(context);
432#if defined(HOST_ARCH_IA32)
433 uword pc = static_cast<uword>(ctx->Eip);
434 uword fp = static_cast<uword>(ctx->Ebp);
435 uword sp = static_cast<uword>(ctx->Esp);
436#elif defined(HOST_ARCH_X64)
437 uword pc = static_cast<uword>(ctx->Rip);
438 uword fp = static_cast<uword>(ctx->Rbp);
439 uword sp = static_cast<uword>(ctx->Rsp);
440#elif defined(HOST_ARCH_ARM)
441 uword pc = static_cast<uword>(ctx->Pc);
442 uword fp = static_cast<uword>(ctx->R11);
443 uword sp = static_cast<uword>(ctx->Sp);
444#elif defined(HOST_ARCH_ARM64)
445 uword pc = static_cast<uword>(ctx->Pc);
446 uword fp = static_cast<uword>(ctx->Fp);
447 uword sp = static_cast<uword>(ctx->Sp);
448#else
449#error Unsupported architecture.
450#endif
451 DumpStackTrace(sp, fp, pc, /*for_crash=*/true);
452#else
453// TODO(fschneider): Add support for more platforms.
454// Do nothing on unsupported platforms.
455#endif
456}
static uintptr_t GetCStackPointer(const mcontext_t &mcontext)
static uintptr_t GetFramePointer(const mcontext_t &mcontext)
static uintptr_t GetProgramCounter(const mcontext_t &mcontext)
uintptr_t uword
Definition: globals.h:501

◆ Init()

void dart::Profiler::Init ( )
static

Definition at line 573 of file profiler.cc.

573 {
574 // Place some sane restrictions on user controlled flags.
575 SetSampleDepth(FLAG_max_profile_depth);
576 if (!FLAG_profiler) {
577 return;
578 }
579 ASSERT(!initialized_);
580 SetSamplePeriod(FLAG_profile_period);
581 // The profiler may have been shutdown previously, in which case the sample
582 // buffer will have already been initialized.
583 if (sample_block_buffer_ == nullptr) {
584 intptr_t num_blocks = CalculateSampleBufferCapacity();
585 sample_block_buffer_ = new SampleBlockBuffer(num_blocks);
586 }
591 initialized_ = true;
592}
static void SetSampleDepth(intptr_t depth)
Definition: profiler.cc:625
static void SetSamplePeriod(intptr_t period)
Definition: profiler.cc:656

◆ IsolateShutdown()

void dart::Profiler::IsolateShutdown ( Thread thread)
static

Definition at line 1854 of file profiler.cc.

1854 {
1855 FlushSampleBlocks(thread->isolate());
1856 ProcessCompletedBlocks(thread->isolate());
1857}
static void ProcessCompletedBlocks(Isolate *isolate)
Definition: profiler.cc:1837
static void FlushSampleBlocks(Isolate *isolate)
Definition: profiler.cc:745

◆ ProcessCompletedBlocks()

void dart::Profiler::ProcessCompletedBlocks ( Isolate isolate)
static

Definition at line 1837 of file profiler.cc.

1837 {
1838 if (!Service::profiler_stream.enabled()) return;
1839 auto thread = Thread::Current();
1840 if (Isolate::IsSystemIsolate(isolate)) return;
1841
1842 TIMELINE_DURATION(thread, Isolate, "Profiler::ProcessCompletedBlocks")
1843 DisableThreadInterruptsScope dtis(thread);
1844 StackZone zone(thread);
1845 HandleScope handle_scope(thread);
1846 StreamableSampleFilter filter(isolate->main_port(), isolate);
1847 Profile profile;
1848 profile.Build(thread, isolate, &filter, Profiler::sample_block_buffer());
1849 ServiceEvent event(isolate, ServiceEvent::kCpuSamples);
1850 event.set_cpu_profile(&profile);
1851 Service::HandleEvent(&event);
1852}
static bool IsSystemIsolate(const Isolate *isolate)
Definition: isolate.h:1445
static SampleBlockBuffer * sample_block_buffer()
Definition: profiler.h:67
static StreamInfo profiler_stream
Definition: service.h:188
static Thread * Current()
Definition: thread.h:362
FlKeyEvent * event
def Build(configs, env, options)
Definition: build.py:232
#define TIMELINE_DURATION(thread, stream, name)
Definition: timeline.h:39

◆ sample_block_buffer()

static SampleBlockBuffer * dart::Profiler::sample_block_buffer ( )
inlinestatic

Definition at line 67 of file profiler.h.

67 {
68 return sample_block_buffer_;
69 }

◆ SampleAllocation()

void dart::Profiler::SampleAllocation ( Thread thread,
intptr_t  cid,
uint32_t  identity_hash 
)
static

Definition at line 1271 of file profiler.cc.

1273 {
1274 ASSERT(thread != nullptr);
1275 OSThread* os_thread = thread->os_thread();
1276 ASSERT(os_thread != nullptr);
1277 Isolate* isolate = thread->isolate();
1278 if (!CheckIsolate(isolate)) {
1279 return;
1280 }
1281 const bool exited_dart_code = thread->HasExitedDartCode();
1282
1283 SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
1284 if (buffer == nullptr) {
1285 // Profiler not initialized.
1286 return;
1287 }
1288
1289 uintptr_t sp = OSThread::GetCurrentStackPointer();
1290 uintptr_t fp = 0;
1291 uintptr_t pc = OS::GetProgramCounter();
1292 uintptr_t lr = 0;
1293
1295
1296 uword stack_lower = 0;
1297 uword stack_upper = 0;
1298
1299 if (!GetAndValidateThreadStackBounds(os_thread, thread, fp, sp, &stack_lower,
1300 &stack_upper)) {
1301 // Could not get stack boundary.
1302 return;
1303 }
1304
1305 Sample* sample =
1306 SetupSample(thread, /*allocation_block*/ true, os_thread->trace_id());
1307 if (sample == nullptr) {
1308 // We were unable to assign a sample for this allocation.
1309 counters_.sample_allocation_failure++;
1310 return;
1311 }
1312 sample->SetAllocationCid(cid);
1313 sample->set_allocation_identity_hash(identity_hash);
1314
1315 if (FLAG_profile_vm_allocation) {
1316 ProfilerNativeStackWalker native_stack_walker(
1317 &counters_, (isolate != nullptr) ? isolate->main_port() : ILLEGAL_PORT,
1318 sample, isolate->current_allocation_sample_block(), stack_lower,
1319 stack_upper, pc, fp, sp);
1320 native_stack_walker.walk();
1321 } else if (exited_dart_code) {
1322 ProfilerDartStackWalker dart_exit_stack_walker(
1323 thread, sample, isolate->current_allocation_sample_block(), pc, fp, sp,
1324 lr, /* allocation_sample*/ true);
1325 dart_exit_stack_walker.walk();
1326 } else {
1327 // Fall back.
1328 uintptr_t pc = OS::GetProgramCounter();
1329 sample->SetAt(0, pc);
1330 }
1331}
#define ILLEGAL_PORT
Definition: dart_api.h:1535
static Sample * SetupSample(Thread *thread, bool allocation_sample, ThreadId tid)
Definition: profiler.cc:1235
static bool CheckIsolate(Isolate *isolate)
Definition: profiler.cc:1263
const intptr_t cid
static bool GetAndValidateThreadStackBounds(OSThread *os_thread, Thread *thread, uintptr_t fp, uintptr_t sp, uword *stack_lower, uword *stack_upper)
Definition: profiler.cc:352
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

◆ SampleThread()

void dart::Profiler::SampleThread ( Thread thread,
const InterruptedThreadState state 
)
static

Definition at line 1354 of file profiler.cc.

1355 {
1356 ASSERT(thread != nullptr);
1357 OSThread* os_thread = thread->os_thread();
1358 ASSERT(os_thread != nullptr);
1359 Isolate* isolate = thread->isolate();
1360
1361 // Thread is not doing VM work.
1362 if (thread->task_kind() == Thread::kUnknownTask) {
1363 counters_.bail_out_unknown_task.fetch_add(1);
1364 return;
1365 }
1366
1368 // The JumpToFrame stub manually adjusts the stack pointer, frame
1369 // pointer, and some isolate state. It is not safe to walk the
1370 // stack when executing this stub.
1371 counters_.bail_out_jump_to_exception_handler.fetch_add(1);
1372 return;
1373 }
1374
1375 const bool in_dart_code = thread->IsExecutingDartCode();
1376
1377 uintptr_t sp = 0;
1378 uintptr_t fp = state.fp;
1379 uintptr_t pc = state.pc;
1380 uintptr_t lr = state.lr;
1381#if defined(USING_SIMULATOR)
1382 Simulator* simulator = nullptr;
1383#endif
1384
1385 if (in_dart_code) {
1386// If we're in Dart code, use the Dart stack pointer.
1387#if defined(USING_SIMULATOR)
1388 simulator = isolate->simulator();
1389 sp = simulator->get_register(SPREG);
1390 fp = simulator->get_register(FPREG);
1391 pc = simulator->get_pc();
1392 lr = simulator->get_lr();
1393#else
1394 sp = state.dsp;
1395#endif
1396 } else {
1397 // If we're in runtime code, use the C stack pointer.
1398 sp = state.csp;
1399 }
1400
1401 if (!CheckIsolate(isolate)) {
1402 counters_.bail_out_check_isolate.fetch_add(1);
1403 return;
1404 }
1405
1407 if (sample_block_buffer == nullptr) {
1408 // Profiler not initialized.
1409 return;
1410 }
1411
1412 // Setup sample.
1413 Sample* sample =
1414 SetupSample(thread, /*allocation_block*/ false, os_thread->trace_id());
1415 if (sample == nullptr) {
1416 // We were unable to assign a sample for this profiler tick.
1417 counters_.sample_allocation_failure++;
1418 return;
1419 }
1420
1421 if (thread->IsDartMutatorThread()) {
1422 if (isolate->IsDeoptimizing()) {
1423 counters_.single_frame_sample_deoptimizing.fetch_add(1);
1424 SampleThreadSingleFrame(thread, sample, pc);
1425 return;
1426 }
1427 }
1428
1429 uword stack_lower = 0;
1430 uword stack_upper = 0;
1431 if (!GetAndValidateThreadStackBounds(os_thread, thread, fp, sp, &stack_lower,
1432 &stack_upper)) {
1433 counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
1434 // Could not get stack boundary.
1435 SampleThreadSingleFrame(thread, sample, pc);
1436 return;
1437 }
1438
1439 // At this point we have a valid stack boundary for this isolate and
1440 // know that our initial stack and frame pointers are within the boundary.
1441
1442 // Increment counter for vm tag.
1443 VMTagCounters* counters = isolate->vm_tag_counters();
1444 ASSERT(counters != nullptr);
1445 if (thread->IsDartMutatorThread()) {
1446 counters->Increment(sample->vm_tag());
1447 }
1448
1449 ProfilerNativeStackWalker native_stack_walker(
1450 &counters_, (isolate != nullptr) ? isolate->main_port() : ILLEGAL_PORT,
1451 sample, isolate->current_sample_block(), stack_lower, stack_upper, pc, fp,
1452 sp);
1453 const bool exited_dart_code = thread->HasExitedDartCode();
1454 ProfilerDartStackWalker dart_stack_walker(
1455 thread, sample, isolate->current_sample_block(), pc, fp, sp, lr,
1456 /* allocation_sample*/ false);
1457
1458 // All memory access is done inside CollectSample.
1459 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1460 &native_stack_walker, &dart_stack_walker, pc, fp, sp,
1461 &counters_);
1462}
static ProfilerCounters counters()
Definition: profiler.h:91
static bool HasBeenInitialized()
Definition: stub_code.h:41
static bool InJumpToFrameStub(uword pc)
Definition: stub_code.cc:139
@ kUnknownTask
Definition: thread.h:346
AtkStateType state
static void CollectSample(Isolate *isolate, bool exited_dart_code, bool in_dart_code, Sample *sample, ProfilerNativeStackWalker *native_stack_walker, ProfilerDartStackWalker *dart_stack_walker, uword pc, uword fp, uword sp, ProfilerCounters *counters)
Definition: profiler.cc:1175
const Register FPREG
const Register SPREG

◆ set_sample_block_buffer()

static void dart::Profiler::set_sample_block_buffer ( SampleBlockBuffer buffer)
inlinestatic

Definition at line 70 of file profiler.h.

70 {
71 sample_block_buffer_ = buffer;
72 }

◆ SetSampleDepth()

void dart::Profiler::SetSampleDepth ( intptr_t  depth)
static

Definition at line 625 of file profiler.cc.

625 {
626 const int kMinimumDepth = 2;
627 const int kMaximumDepth = 255;
628 if (depth < kMinimumDepth) {
629 FLAG_max_profile_depth = kMinimumDepth;
630 } else if (depth > kMaximumDepth) {
631 FLAG_max_profile_depth = kMaximumDepth;
632 } else {
633 FLAG_max_profile_depth = depth;
634 }
635}

◆ SetSamplePeriod()

void dart::Profiler::SetSamplePeriod ( intptr_t  period)
static

Definition at line 656 of file profiler.cc.

656 {
657 const int kMinimumProfilePeriod = 50;
658 if (period < kMinimumProfilePeriod) {
659 FLAG_profile_period = kMinimumProfilePeriod;
660 } else {
661 FLAG_profile_period = period;
662 }
663 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
664}
static void SetInterruptPeriod(intptr_t period)

◆ Size()

intptr_t dart::Profiler::Size ( )
inlinestatic

Definition at line 787 of file profiler.h.

787 {
788 intptr_t size = 0;
789 if (sample_block_buffer_ != nullptr) {
790 size += sample_block_buffer_->Size();
791 }
792 return size;
793}
intptr_t Size() const
Definition: profiler.h:761
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

◆ UpdateRunningState()

void dart::Profiler::UpdateRunningState ( )
static

Definition at line 617 of file profiler.cc.

617 {
618 if (!FLAG_profiler && initialized_) {
619 Cleanup();
620 } else if (FLAG_profiler && !initialized_) {
621 Init();
622 }
623}
static void Cleanup()
Definition: profiler.cc:605
static void Init()
Definition: profiler.cc:573

◆ UpdateSamplePeriod()

void dart::Profiler::UpdateSamplePeriod ( )
static

Definition at line 666 of file profiler.cc.

666 {
667 SetSamplePeriod(FLAG_profile_period);
668}

Friends And Related Function Documentation

◆ Thread

friend class Thread
friend

Definition at line 120 of file profiler.h.


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