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..d19871c2e67ead64efa193b89f6e30a18c4d56c2 100644 |
| --- a/test/cctest/test-heap-profiler.cc |
| +++ b/test/cctest/test-heap-profiler.cc |
| @@ -2852,3 +2852,157 @@ 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; |
| +} |
| + |
| + |
| +// static void PrintNode(const v8::AllocationProfile::Node* node, int indent) { |
|
Hannes Payer (out of office)
2016/01/19 08:44:08
You probably don't need that piece anymore.
Yang
2016/01/19 12:33:34
Yup. Remove instead of comment out.
|
| +// v8::String::Utf8Value name(node->name); |
| +// printf("name:%*s %s %d:%d\n", indent, " ", |
| +// *name, node->line_number, node->column_number); |
| + |
| +// indent += 2; |
| +// for (auto allocation : node->allocations) { |
| +// printf("%*s size %zu count %d\n", indent, " ", allocation.size, |
| +// allocation.count); |
| +// } |
| + |
| +// for (auto child : node->children) { |
| +// PrintNode(child, indent); |
| +// } |
| +// } |
| + |
| + |
| +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.GetRootNode() == nullptr); |
| + } |
| + |
| + int count_512kb = 0; |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(512 * 1024); |
| + CompileRun(script_source); |
| + |
| + v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); |
| + |
| + 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(); |
| + } |
| + |
| + // Samples should get cleared once sampling is stopped. |
| + { |
| + v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); |
| + CHECK(profile.GetRootNode() == nullptr); |
| + } |
| + |
| + // Sampling at a higher rate should give us more sampled objects. |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(256 * 1024); |
| + CompileRun(script_source); |
| + |
| + v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); |
| + |
| + 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_256kb = 0; |
| + for (auto allocation : node_bar->allocations) { |
| + count_256kb += allocation.count; |
| + } |
| + |
| + // We should have roughly twice as many sampled allocations. However, since |
| + // sampling is a randomized process, we use a weaker test. |
| + CHECK_GT(count_256kb, count_512kb); |
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| + } |
| + |
| + // A more complicated test cases with deeper call graph and dynamically |
| + // generated function names. |
| + { |
| + heap_profiler->StartSamplingHeapProfiler(512); |
| + CompileRun(record_trace_tree_source); |
| + |
| + v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); |
| + |
| + 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(); |
| + } |
| +} |
| + |
| + |
| +TEST(SamplingHeapProfilerApiAllocation) { |
| + v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| + LocalContext env; |
| + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| + |
| + heap_profiler->StartSamplingHeapProfiler(2 * 1024); // 2 KiB. |
| + |
| + for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate()); |
| + |
| + v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); |
| + const char* names[] = {"(V8 API)"}; |
| + auto node = FindAllocationProfileNode( |
| + profile, Vector<const char*>(names, arraysize(names))); |
| + CHECK(node); |
| + |
| + heap_profiler->StopSamplingHeapProfiler(); |
| +} |