| Index: runtime/vm/profiler_test.cc
|
| diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
|
| index 08d3980cb74327a8544f11615c85330e43ec050d..5176943c54006ec7ef95479ce5f4e981f8ada696 100644
|
| --- a/runtime/vm/profiler_test.cc
|
| +++ b/runtime/vm/profiler_test.cc
|
| @@ -317,6 +317,213 @@ TEST_CASE(Profiler_TrivialRecordAllocation) {
|
| }
|
|
|
|
|
| +DART_NOINLINE static void NativeAllocationSampleHelper(char** result) {
|
| + ASSERT(result != NULL);
|
| + *result = static_cast<char*>(malloc(sizeof(char) * 1024));
|
| +}
|
| +
|
| +
|
| +ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) {
|
| + bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks;
|
| + FLAG_enable_malloc_hooks = true;
|
| +
|
| + MallocHooks::InitOnce();
|
| + MallocHooks::ResetStats();
|
| + bool stack_trace_collection_enabled =
|
| + MallocHooks::stack_trace_collection_enabled();
|
| + MallocHooks::set_stack_trace_collection_enabled(true);
|
| +
|
| + char* result = NULL;
|
| + const int64_t before_allocations_micros = Dart_TimelineGetMicros();
|
| + NativeAllocationSampleHelper(&result);
|
| +
|
| + // Disable stack allocation stack trace collection to avoid muddying up
|
| + // results.
|
| + MallocHooks::set_stack_trace_collection_enabled(false);
|
| + const int64_t after_allocations_micros = Dart_TimelineGetMicros();
|
| + const int64_t allocation_extent_micros =
|
| + after_allocations_micros - before_allocations_micros;
|
| +
|
| + // Walk the trie and do a sanity check of the allocation values associated
|
| + // with each node.
|
| + {
|
| + Thread* thread = Thread::Current();
|
| + Isolate* isolate = thread->isolate();
|
| + StackZone zone(thread);
|
| + HANDLESCOPE(thread);
|
| + Profile profile(isolate);
|
| +
|
| + // Filter for the class in the time range.
|
| + NativeAllocationSampleFilter filter(before_allocations_micros,
|
| + allocation_extent_micros);
|
| + profile.Build(thread, &filter, Profile::kNoTags);
|
| + // We should have 1 allocation sample.
|
| + EXPECT_EQ(1, profile.sample_count());
|
| + ProfileTrieWalker walker(&profile);
|
| +
|
| + // Exclusive code: NativeAllocationSampleHelper -> main.
|
| + walker.Reset(Profile::kExclusiveCode);
|
| + // Move down from the root.
|
| + EXPECT(walker.Down());
|
| + EXPECT_SUBSTRING("[Native]", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()",
|
| + walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("main", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(!walker.Down());
|
| +
|
| + // Inclusive code: main -> NativeAllocationSampleHelper.
|
| + walker.Reset(Profile::kInclusiveCode);
|
| + // Move down from the root.
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("main", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()",
|
| + walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_SUBSTRING("[Native]", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024);
|
| + EXPECT(!walker.Down());
|
| +
|
| + // Exclusive function: NativeAllocationSampleHelper -> main.
|
| + walker.Reset(Profile::kExclusiveFunction);
|
| + // Move down from the root.
|
| + EXPECT(walker.Down());
|
| + EXPECT_SUBSTRING("[Native]", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()",
|
| + walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("main", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(!walker.Down());
|
| +
|
| + // Inclusive function: main -> NativeAllocationSampleHelper.
|
| + walker.Reset(Profile::kInclusiveFunction);
|
| + // Move down from the root.
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("main", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()",
|
| + walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0);
|
| + EXPECT(walker.Down());
|
| + EXPECT_SUBSTRING("[Native]", walker.CurrentName());
|
| + EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024);
|
| + EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024);
|
| + EXPECT(!walker.Down());
|
| + }
|
| +
|
| + MallocHooks::set_stack_trace_collection_enabled(true);
|
| + free(result);
|
| + MallocHooks::set_stack_trace_collection_enabled(false);
|
| +
|
| + // Check to see that the native allocation sample associated with the memory
|
| + // freed above is marked as free and is no longer reported.
|
| + {
|
| + Thread* thread = Thread::Current();
|
| + Isolate* isolate = thread->isolate();
|
| + StackZone zone(thread);
|
| + HANDLESCOPE(thread);
|
| + Profile profile(isolate);
|
| +
|
| + // Filter for the class in the time range.
|
| + NativeAllocationSampleFilter filter(before_allocations_micros,
|
| + allocation_extent_micros);
|
| + profile.Build(thread, &filter, Profile::kNoTags);
|
| + // We should have 0 allocation samples since we freed the memory.
|
| + EXPECT_EQ(0, profile.sample_count());
|
| + }
|
| +
|
| + // Query with a time filter where no allocations occurred.
|
| + {
|
| + Thread* thread = Thread::Current();
|
| + Isolate* isolate = thread->isolate();
|
| + StackZone zone(thread);
|
| + HANDLESCOPE(thread);
|
| + Profile profile(isolate);
|
| + NativeAllocationSampleFilter filter(Dart_TimelineGetMicros(), 16000);
|
| + profile.Build(thread, &filter, Profile::kNoTags);
|
| + // We should have no allocation samples because none occured within
|
| + // the specified time range.
|
| + EXPECT_EQ(0, profile.sample_count());
|
| + }
|
| +
|
| + MallocHooks::set_stack_trace_collection_enabled(
|
| + stack_trace_collection_enabled);
|
| + MallocHooks::TearDown();
|
| + FLAG_enable_malloc_hooks = enable_malloc_hooks_saved;
|
| +}
|
| +
|
| +
|
| TEST_CASE(Profiler_ToggleRecordAllocation) {
|
| DisableNativeProfileScope dnps;
|
| const char* kScript =
|
|
|