Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: test/cctest/test-heap-profiler.cc

Issue 1555553002: [profiler] Implement POC Sampling Heap Profiler (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: cleanup samples when sampling heap profiler is stopped Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 827 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 const v8::HeapGraphNode* root1 = snapshot->GetRoot(); 838 const v8::HeapGraphNode* root1 = snapshot->GetRoot();
839 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( 839 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
840 snapshot))->GetSortedEntriesList(); 840 snapshot))->GetSortedEntriesList();
841 const v8::HeapGraphNode* root2 = snapshot->GetRoot(); 841 const v8::HeapGraphNode* root2 = snapshot->GetRoot();
842 CHECK_EQ(root1, root2); 842 CHECK_EQ(root1, root2);
843 } 843 }
844 844
845 845
846 namespace { 846 namespace {
847 847
848 class OneByteResource : public v8::String::ExternalOneByteStringResource {
849 public:
850 explicit OneByteResource(i::Vector<char> string) : data_(string.start()) {
851 length_ = string.length();
852 }
853 virtual const char* data() const { return data_; }
854 virtual size_t length() const { return length_; }
855
856 private:
857 const char* data_;
858 size_t length_;
859 };
860
848 class TestJSONStream : public v8::OutputStream { 861 class TestJSONStream : public v8::OutputStream {
849 public: 862 public:
850 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} 863 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {}
851 explicit TestJSONStream(int abort_countdown) 864 explicit TestJSONStream(int abort_countdown)
852 : eos_signaled_(0), abort_countdown_(abort_countdown) {} 865 : eos_signaled_(0), abort_countdown_(abort_countdown) {}
853 virtual ~TestJSONStream() {} 866 virtual ~TestJSONStream() {}
854 virtual void EndOfStream() { ++eos_signaled_; } 867 virtual void EndOfStream() { ++eos_signaled_; }
855 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { 868 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
856 if (abort_countdown_ > 0) --abort_countdown_; 869 if (abort_countdown_ > 0) --abort_countdown_;
857 if (abort_countdown_ == 0) return kAbort; 870 if (abort_countdown_ == 0) return kAbort;
858 CHECK_GT(chars_written, 0); 871 CHECK_GT(chars_written, 0);
859 i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0'); 872 i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0');
860 i::MemCopy(chunk.start(), buffer, chars_written); 873 i::MemCopy(chunk.start(), buffer, chars_written);
861 return kContinue; 874 return kContinue;
862 } 875 }
863 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int chars_written) { 876 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int chars_written) {
864 CHECK(false); 877 CHECK(false);
865 return kAbort; 878 return kAbort;
866 } 879 }
867 void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); } 880 void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); }
868 int eos_signaled() { return eos_signaled_; } 881 int eos_signaled() { return eos_signaled_; }
869 int size() { return buffer_.size(); } 882 int size() { return buffer_.size(); }
870 883
884 // Verifies that the stream contains JSON, parses, and returns the parsed
885 // result.
886 v8::Local<v8::Object> verifyAndParseJSON(LocalContext& env) {
887 i::ScopedVector<char> json(size());
888 WriteTo(json);
889
890 // Verify that string is valid JSON.
891 OneByteResource* json_res = new OneByteResource(json);
892 v8::Local<v8::String> json_string =
893 v8::String::NewExternalOneByte(env->GetIsolate(), json_res)
894 .ToLocalChecked();
895 env->Global()
896 ->Set(env.local(), v8_str("json_snapshot"), json_string)
897 .FromJust();
898 v8::Local<v8::Value> snapshot_parse_result =
899 CompileRun("var parsed = JSON.parse(json_snapshot); true;");
900 CHECK(!snapshot_parse_result.IsEmpty());
901
902 v8::Local<v8::Object> parsed = env->Global()
903 ->Get(env.local(), v8_str("parsed"))
904 .ToLocalChecked()
905 ->ToObject(env.local())
906 .ToLocalChecked();
907 return parsed;
908 }
909
871 private: 910 private:
872 i::Collector<char> buffer_; 911 i::Collector<char> buffer_;
873 int eos_signaled_; 912 int eos_signaled_;
874 int abort_countdown_; 913 int abort_countdown_;
875 }; 914 };
876 915
877 class OneByteResource : public v8::String::ExternalOneByteStringResource {
878 public:
879 explicit OneByteResource(i::Vector<char> string) : data_(string.start()) {
880 length_ = string.length();
881 }
882 virtual const char* data() const { return data_; }
883 virtual size_t length() const { return length_; }
884 private:
885 const char* data_;
886 size_t length_;
887 };
888
889 } // namespace 916 } // namespace
890 917
891 TEST(HeapSnapshotJSONSerialization) { 918 TEST(HeapSnapshotJSONSerialization) {
892 v8::Isolate* isolate = CcTest::isolate(); 919 v8::Isolate* isolate = CcTest::isolate();
893 LocalContext env; 920 LocalContext env;
894 v8::HandleScope scope(isolate); 921 v8::HandleScope scope(isolate);
895 v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler(); 922 v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
896 923
897 #define STRING_LITERAL_FOR_TEST \ 924 #define STRING_LITERAL_FOR_TEST \
898 "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\"" 925 "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
899 CompileRun( 926 CompileRun(
900 "function A(s) { this.s = s; }\n" 927 "function A(s) { this.s = s; }\n"
901 "function B(x) { this.x = x; }\n" 928 "function B(x) { this.x = x; }\n"
902 "var a = new A(" STRING_LITERAL_FOR_TEST ");\n" 929 "var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
903 "var b = new B(a);"); 930 "var b = new B(a);");
904 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); 931 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
905 CHECK(ValidateSnapshot(snapshot)); 932 CHECK(ValidateSnapshot(snapshot));
906 933
907 TestJSONStream stream; 934 TestJSONStream stream;
908 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 935 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
909 CHECK_GT(stream.size(), 0); 936 CHECK_GT(stream.size(), 0);
910 CHECK_EQ(1, stream.eos_signaled()); 937 CHECK_EQ(1, stream.eos_signaled());
911 i::ScopedVector<char> json(stream.size());
912 stream.WriteTo(json);
913 938
914 // Verify that snapshot string is valid JSON. 939 v8::Local<v8::Object> parsed_snapshot = stream.verifyAndParseJSON(env);
915 OneByteResource* json_res = new OneByteResource(json);
916 v8::Local<v8::String> json_string =
917 v8::String::NewExternalOneByte(env->GetIsolate(), json_res)
918 .ToLocalChecked();
919 env->Global()
920 ->Set(env.local(), v8_str("json_snapshot"), json_string)
921 .FromJust();
922 v8::Local<v8::Value> snapshot_parse_result = CompileRun(
923 "var parsed = JSON.parse(json_snapshot); true;");
924 CHECK(!snapshot_parse_result.IsEmpty());
925
926 // Verify that snapshot object has required fields.
927 v8::Local<v8::Object> parsed_snapshot =
928 env->Global()
929 ->Get(env.local(), v8_str("parsed"))
930 .ToLocalChecked()
931 ->ToObject(env.local())
932 .ToLocalChecked();
933 CHECK(parsed_snapshot->Has(env.local(), v8_str("snapshot")).FromJust()); 940 CHECK(parsed_snapshot->Has(env.local(), v8_str("snapshot")).FromJust());
934 CHECK(parsed_snapshot->Has(env.local(), v8_str("nodes")).FromJust()); 941 CHECK(parsed_snapshot->Has(env.local(), v8_str("nodes")).FromJust());
935 CHECK(parsed_snapshot->Has(env.local(), v8_str("edges")).FromJust()); 942 CHECK(parsed_snapshot->Has(env.local(), v8_str("edges")).FromJust());
936 CHECK(parsed_snapshot->Has(env.local(), v8_str("strings")).FromJust()); 943 CHECK(parsed_snapshot->Has(env.local(), v8_str("strings")).FromJust());
937 944
938 // Get node and edge "member" offsets. 945 // Get node and edge "member" offsets.
939 v8::Local<v8::Value> meta_analysis_result = CompileRun( 946 v8::Local<v8::Value> meta_analysis_result = CompileRun(
940 "var meta = parsed.snapshot.meta;\n" 947 "var meta = parsed.snapshot.meta;\n"
941 "var edge_count_offset = meta.node_fields.indexOf('edge_count');\n" 948 "var edge_count_offset = meta.node_fields.indexOf('edge_count');\n"
942 "var node_fields_count = meta.node_fields.length;\n" 949 "var node_fields_count = meta.node_fields.length;\n"
(...skipping 1902 matching lines...) Expand 10 before | Expand all | Expand 10 after
2845 map.AddRange(ToAddress(0x180), 0x80, 6U); 2852 map.AddRange(ToAddress(0x180), 0x80, 6U);
2846 map.AddRange(ToAddress(0x180), 0x80, 7U); 2853 map.AddRange(ToAddress(0x180), 0x80, 7U);
2847 CHECK_EQ(7u, map.GetTraceNodeId(ToAddress(0x180))); 2854 CHECK_EQ(7u, map.GetTraceNodeId(ToAddress(0x180)));
2848 CHECK_EQ(5u, map.GetTraceNodeId(ToAddress(0x200))); 2855 CHECK_EQ(5u, map.GetTraceNodeId(ToAddress(0x200)));
2849 CHECK_EQ(3u, map.size()); 2856 CHECK_EQ(3u, map.size());
2850 2857
2851 map.Clear(); 2858 map.Clear();
2852 CHECK_EQ(0u, map.size()); 2859 CHECK_EQ(0u, map.size());
2853 CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400))); 2860 CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400)));
2854 } 2861 }
2862
2863
2864 TEST(SamplingHeapProfiler) {
2865 v8::HandleScope scope(v8::Isolate::GetCurrent());
2866 LocalContext env;
2867 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
2868
2869 // GetHeapSample should return an empty stream when called before starting
2870 // the sampling heap profiler.
2871 TestJSONStream stream0;
2872 heap_profiler->GetHeapSample(&stream0);
2873 CHECK_EQ(stream0.size(), 0);
2874 CHECK_EQ(1, stream0.eos_signaled());
2875
2876 heap_profiler->StartSamplingHeapProfiler();
2877 CompileRun(
2878 "var A = [];\n"
2879 "function bar(size) { return new Array(size); }\n"
2880 "var foo = function() {\n"
2881 " for (var i = 0; i < 1024; ++i) {\n"
2882 " A[i] = bar(1024);\n"
2883 " }\n"
2884 "}\n"
2885 "foo();");
2886
2887 TestJSONStream stream1;
2888 heap_profiler->GetHeapSample(&stream1);
2889 heap_profiler->StopSamplingHeapProfiler();
2890
2891 CHECK_GT(stream1.size(), 0);
2892 CHECK_EQ(1, stream1.eos_signaled());
2893
2894 v8::Local<v8::Object> sample = stream1.verifyAndParseJSON(env);
2895 CHECK(sample->IsArray());
2896 v8::Local<v8::Value> validation_result = CompileRun(
2897 "parsed.every(allocation => {\n"
2898 " return allocation.size && Array.isArray(allocation.stack) &&\n"
2899 " allocation.stack.every(frame => {\n"
2900 " return frame.hasOwnProperty('name') &&\n"
2901 " frame.hasOwnProperty('scriptName') &&\n"
2902 " frame.hasOwnProperty('line') &&\n"
2903 " frame.hasOwnProperty('column');\n"
2904 " });\n"
2905 "});");
2906 CHECK(validation_result->IsTrue());
2907
2908 // Samples are reset once sampling heap profiler is stopped.
2909 TestJSONStream stream2;
2910 heap_profiler->GetHeapSample(&stream2);
2911 CHECK_EQ(stream2.size(), 0);
2912 CHECK_EQ(1, stream2.eos_signaled());
2913 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698