Chromium Code Reviews| Index: test/cctest/test-heap-profiler.cc |
| diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc |
| index a2fd09e9f59d4edd27b4c6ca1c0b3800648e8729..05d7b4b628917e2061709bfa323d61314bb07c58 100644 |
| --- a/test/cctest/test-heap-profiler.cc |
| +++ b/test/cctest/test-heap-profiler.cc |
| @@ -2852,3 +2852,148 @@ TEST(AddressToTraceMap) { |
| CHECK_EQ(0u, map.size()); |
| CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400))); |
| } |
| + |
| + |
| +static const v8::AllocationProfile::Node* FindAllocationProfileNode( |
| + v8::AllocationProfile& profile, const Vector<const char*>& names) { |
| + v8::AllocationProfile::Node* node = profile.GetRootNode(); |
| + for (int i = 0; node != nullptr && i < names.length(); ++i) { |
| + const char* name = names[i]; |
| + auto children = node->children; |
| + node = nullptr; |
| + for (v8::AllocationProfile::Node* child : children) { |
| + v8::String::Utf8Value child_name(child->name); |
| + if (strcmp(*child_name, name) == 0) { |
| + node = child; |
| + break; |
| + } |
| + } |
| + } |
| + return node; |
| +} |
| + |
| + |
| +TEST(SamplingHeapProfiler) { |
| + v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| + LocalContext env; |
| + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| + |
| + // Turn off always_opt. Inlining can cause stack traces to be shorter than |
| + // what we expect in this test. |
| + v8::internal::FLAG_always_opt = false; |
| + |
| + const char* script_source = |
| + "var A = [];\n" |
| + "function bar(size) { return new Array(size); }\n" |
| + "var foo = function() {\n" |
| + " for (var i = 0; i < 1024; ++i) {\n" |
| + " A[i] = bar(1024);\n" |
| + " }\n" |
| + "}\n" |
| + "foo();"; |
| + |
| + // Sample should be empty if requested before sampling has started. |
| + { |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile == nullptr); |
| + } |
| + |
| + int count_512kb = 0; |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(512 * 1024); |
|
alph
2016/01/20 23:13:01
This is a source for flakiness, as the interval is
ofrobots
2016/01/21 03:03:28
I like the idea to suppress randomness some of the
alph
2016/01/21 03:21:55
oh yes, it's 2 multiplies by sizeof(intptr_t) = 16
|
| + CompileRun(script_source); |
| + |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
|
alph
2016/01/20 23:13:01
Please use SmartPointer wherever possible.
ofrobots
2016/01/21 03:03:28
Done.
|
| + CHECK(profile); |
| + |
| + const char* names[] = {"", "foo", "bar"}; |
| + auto node_bar = FindAllocationProfileNode( |
| + *profile, Vector<const char*>(names, arraysize(names))); |
| + CHECK(node_bar); |
| + |
| + // Count the number of allocations we sampled from bar. |
| + for (auto allocation : node_bar->allocations) { |
| + count_512kb += allocation.count; |
| + } |
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| + delete profile; |
| + } |
| + |
| + // Samples should get cleared once sampling is stopped. |
| + { |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile == nullptr); |
| + } |
| + |
| + // Sampling at a higher rate should give us more sampled objects. |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(32 * 1024); |
| + CompileRun(script_source); |
| + |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile); |
| + |
| + const char* names[] = {"", "foo", "bar"}; |
| + auto node_bar = FindAllocationProfileNode( |
| + *profile, Vector<const char*>(names, arraysize(names))); |
| + CHECK(node_bar); |
| + |
| + // Count the number of allocations we sampled from bar. |
| + int count_32kb = 0; |
| + for (auto allocation : node_bar->allocations) { |
| + count_32kb += allocation.count; |
| + } |
| + |
| + // We should have roughly 16x as many sampled allocations. However, since |
| + // sampling is a randomized process, we use a weaker test. |
| + CHECK_GT(count_32kb, count_512kb); |
|
alph
2016/01/20 23:13:01
Again, this seems to be a source for the test flak
ofrobots
2016/01/21 03:03:28
I am intentionally using a weak test here to avoid
|
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| + delete profile; |
| + } |
| + |
| + // A more complicated test cases with deeper call graph and dynamically |
| + // generated function names. |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(128); |
| + CompileRun(record_trace_tree_source); |
| + |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile); |
| + |
| + const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; |
| + auto node1 = FindAllocationProfileNode( |
| + *profile, Vector<const char*>(names1, arraysize(names1))); |
| + CHECK(node1); |
| + |
| + const char* names2[] = {"", "generateFunctions"}; |
| + auto node2 = FindAllocationProfileNode( |
| + *profile, Vector<const char*>(names2, arraysize(names2))); |
| + CHECK(node2); |
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| + delete profile; |
| + } |
| +} |
| + |
| + |
| +TEST(SamplingHeapProfilerApiAllocation) { |
| + v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| + LocalContext env; |
| + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| + |
| + heap_profiler->StartSamplingHeapProfiler(256); |
| + |
| + for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate()); |
| + |
| + v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile); |
| + const char* names[] = {"(V8 API)"}; |
| + auto node = FindAllocationProfileNode( |
| + *profile, Vector<const char*>(names, arraysize(names))); |
| + CHECK(node); |
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| + delete profile; |
| +} |