OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2845 map.AddRange(ToAddress(0x180), 0x80, 6U); | 2845 map.AddRange(ToAddress(0x180), 0x80, 6U); |
2846 map.AddRange(ToAddress(0x180), 0x80, 7U); | 2846 map.AddRange(ToAddress(0x180), 0x80, 7U); |
2847 CHECK_EQ(7u, map.GetTraceNodeId(ToAddress(0x180))); | 2847 CHECK_EQ(7u, map.GetTraceNodeId(ToAddress(0x180))); |
2848 CHECK_EQ(5u, map.GetTraceNodeId(ToAddress(0x200))); | 2848 CHECK_EQ(5u, map.GetTraceNodeId(ToAddress(0x200))); |
2849 CHECK_EQ(3u, map.size()); | 2849 CHECK_EQ(3u, map.size()); |
2850 | 2850 |
2851 map.Clear(); | 2851 map.Clear(); |
2852 CHECK_EQ(0u, map.size()); | 2852 CHECK_EQ(0u, map.size()); |
2853 CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400))); | 2853 CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400))); |
2854 } | 2854 } |
2855 | |
2856 | |
2857 static const v8::AllocationProfile::Node* FindAllocationProfileNode( | |
2858 v8::AllocationProfile& profile, const Vector<const char*>& names) { | |
2859 v8::AllocationProfile::Node* node = profile.GetRootNode(); | |
2860 for (int i = 0; node != nullptr && i < names.length(); ++i) { | |
2861 const char* name = names[i]; | |
2862 auto children = node->children; | |
2863 node = nullptr; | |
2864 for (v8::AllocationProfile::Node* child : children) { | |
2865 v8::String::Utf8Value child_name(child->name); | |
2866 if (strcmp(*child_name, name) == 0) { | |
2867 node = child; | |
2868 break; | |
2869 } | |
2870 } | |
2871 } | |
2872 return node; | |
2873 } | |
2874 | |
2875 | |
2876 // 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.
| |
2877 // v8::String::Utf8Value name(node->name); | |
2878 // printf("name:%*s %s %d:%d\n", indent, " ", | |
2879 // *name, node->line_number, node->column_number); | |
2880 | |
2881 // indent += 2; | |
2882 // for (auto allocation : node->allocations) { | |
2883 // printf("%*s size %zu count %d\n", indent, " ", allocation.size, | |
2884 // allocation.count); | |
2885 // } | |
2886 | |
2887 // for (auto child : node->children) { | |
2888 // PrintNode(child, indent); | |
2889 // } | |
2890 // } | |
2891 | |
2892 | |
2893 TEST(SamplingHeapProfiler) { | |
2894 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
2895 LocalContext env; | |
2896 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | |
2897 | |
2898 // Turn off always_opt. Inlining can cause stack traces to be shorter than | |
2899 // what we expect in this test. | |
2900 v8::internal::FLAG_always_opt = false; | |
2901 | |
2902 const char* script_source = | |
2903 "var A = [];\n" | |
2904 "function bar(size) { return new Array(size); }\n" | |
2905 "var foo = function() {\n" | |
2906 " for (var i = 0; i < 1024; ++i) {\n" | |
2907 " A[i] = bar(1024);\n" | |
2908 " }\n" | |
2909 "}\n" | |
2910 "foo();"; | |
2911 | |
2912 // Sample should be empty if requested before sampling has started. | |
2913 { | |
2914 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
2915 CHECK(profile.GetRootNode() == nullptr); | |
2916 } | |
2917 | |
2918 int count_512kb = 0; | |
2919 { | |
2920 heap_profiler->StartSamplingHeapProfiler(512 * 1024); | |
2921 CompileRun(script_source); | |
2922 | |
2923 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
2924 | |
2925 const char* names[] = {"", "foo", "bar"}; | |
2926 auto node_bar = FindAllocationProfileNode( | |
2927 profile, Vector<const char*>(names, arraysize(names))); | |
2928 CHECK(node_bar); | |
2929 | |
2930 // Count the number of allocations we sampled from bar. | |
2931 for (auto allocation : node_bar->allocations) { | |
2932 count_512kb += allocation.count; | |
2933 } | |
2934 | |
2935 heap_profiler->StopSamplingHeapProfiler(); | |
2936 } | |
2937 | |
2938 // Samples should get cleared once sampling is stopped. | |
2939 { | |
2940 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
2941 CHECK(profile.GetRootNode() == nullptr); | |
2942 } | |
2943 | |
2944 // Sampling at a higher rate should give us more sampled objects. | |
2945 { | |
2946 heap_profiler->StartSamplingHeapProfiler(256 * 1024); | |
2947 CompileRun(script_source); | |
2948 | |
2949 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
2950 | |
2951 const char* names[] = {"", "foo", "bar"}; | |
2952 auto node_bar = FindAllocationProfileNode( | |
2953 profile, Vector<const char*>(names, arraysize(names))); | |
2954 CHECK(node_bar); | |
2955 | |
2956 // Count the number of allocations we sampled from bar. | |
2957 int count_256kb = 0; | |
2958 for (auto allocation : node_bar->allocations) { | |
2959 count_256kb += allocation.count; | |
2960 } | |
2961 | |
2962 // We should have roughly twice as many sampled allocations. However, since | |
2963 // sampling is a randomized process, we use a weaker test. | |
2964 CHECK_GT(count_256kb, count_512kb); | |
2965 | |
2966 heap_profiler->StopSamplingHeapProfiler(); | |
2967 } | |
2968 | |
2969 // A more complicated test cases with deeper call graph and dynamically | |
2970 // generated function names. | |
2971 { | |
2972 heap_profiler->StartSamplingHeapProfiler(512); | |
2973 CompileRun(record_trace_tree_source); | |
2974 | |
2975 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
2976 | |
2977 const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; | |
2978 auto node1 = FindAllocationProfileNode( | |
2979 profile, Vector<const char*>(names1, arraysize(names1))); | |
2980 CHECK(node1); | |
2981 | |
2982 const char* names2[] = {"", "generateFunctions"}; | |
2983 auto node2 = FindAllocationProfileNode( | |
2984 profile, Vector<const char*>(names2, arraysize(names2))); | |
2985 CHECK(node2); | |
2986 | |
2987 heap_profiler->StopSamplingHeapProfiler(); | |
2988 } | |
2989 } | |
2990 | |
2991 | |
2992 TEST(SamplingHeapProfilerApiAllocation) { | |
2993 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
2994 LocalContext env; | |
2995 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | |
2996 | |
2997 heap_profiler->StartSamplingHeapProfiler(2 * 1024); // 2 KiB. | |
2998 | |
2999 for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate()); | |
3000 | |
3001 v8::AllocationProfile profile = heap_profiler->GetAllocationProfile(); | |
3002 const char* names[] = {"(V8 API)"}; | |
3003 auto node = FindAllocationProfileNode( | |
3004 profile, Vector<const char*>(names, arraysize(names))); | |
3005 CHECK(node); | |
3006 | |
3007 heap_profiler->StopSamplingHeapProfiler(); | |
3008 } | |
OLD | NEW |