OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_HEAP_OBJECT_STATS_H_ | 5 #ifndef V8_HEAP_OBJECT_STATS_H_ |
6 #define V8_HEAP_OBJECT_STATS_H_ | 6 #define V8_HEAP_OBJECT_STATS_H_ |
7 | 7 |
8 #include "src/heap/heap.h" | 8 #include "src/heap/heap.h" |
9 #include "src/heap/objects-visiting.h" | 9 #include "src/heap/objects-visiting.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 class ObjectStats { | 15 class ObjectStats { |
16 public: | 16 public: |
17 explicit ObjectStats(Heap* heap) : heap_(heap) {} | 17 explicit ObjectStats(Heap* heap) : heap_(heap) { ClearObjectStats(); } |
18 | 18 |
19 // ObjectStats are kept in two arrays, counts and sizes. Related stats are | 19 // ObjectStats are kept in two arrays, counts and sizes. Related stats are |
20 // stored in a contiguous linear buffer. Stats groups are stored one after | 20 // stored in a contiguous linear buffer. Stats groups are stored one after |
21 // another. | 21 // another. |
22 enum { | 22 enum { |
23 FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1, | 23 FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1, |
24 FIRST_FIXED_ARRAY_SUB_TYPE = | 24 FIRST_FIXED_ARRAY_SUB_TYPE = |
25 FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS, | 25 FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS, |
26 FIRST_CODE_AGE_SUB_TYPE = | 26 FIRST_CODE_AGE_SUB_TYPE = |
27 FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1, | 27 FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1, |
28 OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kCodeAgeCount + 1 | 28 OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kCodeAgeCount + 1 |
29 }; | 29 }; |
30 | 30 |
31 void ClearObjectStats(bool clear_last_time_stats = false); | 31 void ClearObjectStats(bool clear_last_time_stats = false); |
32 | 32 |
33 void TraceObjectStats(); | |
34 void TraceObjectStat(const char* name, int count, int size, double time); | |
35 void CheckpointObjectStats(); | 33 void CheckpointObjectStats(); |
| 34 void PrintJSON(const char* key); |
36 | 35 |
37 void RecordObjectStats(InstanceType type, size_t size) { | 36 void RecordObjectStats(InstanceType type, size_t size) { |
38 DCHECK(type <= LAST_TYPE); | 37 DCHECK(type <= LAST_TYPE); |
39 object_counts_[type]++; | 38 object_counts_[type]++; |
40 object_sizes_[type] += size; | 39 object_sizes_[type] += size; |
| 40 size_histogram_[type][HistogramIndexFromSize(size)]++; |
41 } | 41 } |
42 | 42 |
43 void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) { | 43 void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) { |
44 int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type; | 44 int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type; |
45 int code_age_index = | 45 int code_age_index = |
46 FIRST_CODE_AGE_SUB_TYPE + code_age - Code::kFirstCodeAge; | 46 FIRST_CODE_AGE_SUB_TYPE + code_age - Code::kFirstCodeAge; |
47 DCHECK(code_sub_type_index >= FIRST_CODE_KIND_SUB_TYPE && | 47 DCHECK(code_sub_type_index >= FIRST_CODE_KIND_SUB_TYPE && |
48 code_sub_type_index < FIRST_CODE_AGE_SUB_TYPE); | 48 code_sub_type_index < FIRST_CODE_AGE_SUB_TYPE); |
49 DCHECK(code_age_index >= FIRST_CODE_AGE_SUB_TYPE && | 49 DCHECK(code_age_index >= FIRST_CODE_AGE_SUB_TYPE && |
50 code_age_index < OBJECT_STATS_COUNT); | 50 code_age_index < OBJECT_STATS_COUNT); |
51 object_counts_[code_sub_type_index]++; | 51 object_counts_[code_sub_type_index]++; |
52 object_sizes_[code_sub_type_index] += size; | 52 object_sizes_[code_sub_type_index] += size; |
53 object_counts_[code_age_index]++; | 53 object_counts_[code_age_index]++; |
54 object_sizes_[code_age_index] += size; | 54 object_sizes_[code_age_index] += size; |
| 55 const int idx = HistogramIndexFromSize(size); |
| 56 size_histogram_[code_sub_type_index][idx]++; |
| 57 size_histogram_[code_age_index][idx]++; |
55 } | 58 } |
56 | 59 |
57 void RecordFixedArraySubTypeStats(int array_sub_type, size_t size) { | 60 void RecordFixedArraySubTypeStats(int array_sub_type, size_t size, |
| 61 size_t over_allocated) { |
58 DCHECK(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE); | 62 DCHECK(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE); |
59 object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++; | 63 object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++; |
60 object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size; | 64 object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size; |
| 65 size_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] |
| 66 [HistogramIndexFromSize(size)]++; |
| 67 over_allocated_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += |
| 68 over_allocated; |
| 69 over_allocated_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] |
| 70 [HistogramIndexFromSize(over_allocated)]++; |
61 } | 71 } |
62 | 72 |
63 size_t object_count_last_gc(size_t index) { | 73 size_t object_count_last_gc(size_t index) { |
64 return object_counts_last_time_[index]; | 74 return object_counts_last_time_[index]; |
65 } | 75 } |
66 | 76 |
67 size_t object_size_last_gc(size_t index) { | 77 size_t object_size_last_gc(size_t index) { |
68 return object_sizes_last_time_[index]; | 78 return object_sizes_last_time_[index]; |
69 } | 79 } |
70 | 80 |
71 Isolate* isolate(); | 81 Isolate* isolate(); |
72 Heap* heap() { return heap_; } | 82 Heap* heap() { return heap_; } |
73 | 83 |
74 private: | 84 private: |
| 85 static const int kFirstBucketShift = 5; // <=32 |
| 86 static const int kLastBucketShift = 19; // >512k |
| 87 static const int kFirstBucket = 1 << kFirstBucketShift; |
| 88 static const int kLastBucket = 1 << kLastBucketShift; |
| 89 static const int kNumberOfBuckets = kLastBucketShift - kFirstBucketShift; |
| 90 |
| 91 int HistogramIndexFromSize(size_t size) { |
| 92 if (size == 0) return 0; |
| 93 int idx = |
| 94 static_cast<int>(log2(static_cast<double>(size))) - kFirstBucketShift; |
| 95 return idx < 0 ? 0 : idx; |
| 96 } |
| 97 |
75 Heap* heap_; | 98 Heap* heap_; |
76 | 99 // Object counts and used memory by InstanceType. |
77 // Object counts and used memory by InstanceType | |
78 size_t object_counts_[OBJECT_STATS_COUNT]; | 100 size_t object_counts_[OBJECT_STATS_COUNT]; |
79 size_t object_counts_last_time_[OBJECT_STATS_COUNT]; | 101 size_t object_counts_last_time_[OBJECT_STATS_COUNT]; |
80 size_t object_sizes_[OBJECT_STATS_COUNT]; | 102 size_t object_sizes_[OBJECT_STATS_COUNT]; |
81 size_t object_sizes_last_time_[OBJECT_STATS_COUNT]; | 103 size_t object_sizes_last_time_[OBJECT_STATS_COUNT]; |
| 104 // Approximation of overallocated memory by InstanceType. |
| 105 size_t over_allocated_[OBJECT_STATS_COUNT]; |
| 106 // Detailed histograms by InstanceType. |
| 107 size_t size_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets]; |
| 108 size_t over_allocated_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets]; |
82 }; | 109 }; |
83 | 110 |
84 class ObjectStatsCollector { | 111 class ObjectStatsCollector { |
85 public: | 112 public: |
86 static void CollectStatistics(StaticVisitorBase::VisitorId id, Map* map, | 113 static void CollectStatistics(ObjectStats* stats, HeapObject* obj); |
| 114 |
| 115 private: |
| 116 static void RecordMapDetails(ObjectStats* stats, Heap* heap, HeapObject* obj); |
| 117 static void RecordCodeDetails(ObjectStats* stats, Heap* heap, |
87 HeapObject* obj); | 118 HeapObject* obj); |
88 static void CollectFixedArrayStatistics(HeapObject* obj); | 119 static void RecordSharedFunctionInfoDetails(ObjectStats* stats, Heap* heap, |
| 120 HeapObject* obj); |
| 121 static void RecordFixedArrayDetails(ObjectStats* stats, Heap* heap, |
| 122 HeapObject* obj); |
89 | 123 |
90 static void CountFixedArray(FixedArrayBase* fixed_array, | 124 static void RecordJSObjectDetails(ObjectStats* stats, Heap* heap, |
91 FixedArraySubInstanceType fast_type, | 125 JSObject* object); |
92 FixedArraySubInstanceType dictionary_type); | 126 static void RecordJSWeakCollectionDetails(ObjectStats* stats, Heap* heap, |
93 static void RecordMapStats(Map* map, HeapObject* obj); | 127 JSWeakCollection* obj); |
94 static void RecordCodeStats(Map* map, HeapObject* obj); | |
95 static void RecordSharedFunctionInfoStats(Map* map, HeapObject* obj); | |
96 static void RecordFixedArrayStats(Map* map, HeapObject* obj); | |
97 }; | |
98 | |
99 class MarkCompactObjectStatsVisitor | |
100 : public StaticMarkingVisitor<MarkCompactObjectStatsVisitor> { | |
101 public: | |
102 static void Initialize(VisitorDispatchTable<Callback>* original); | |
103 | |
104 template <VisitorId id> | |
105 static inline void Visit(Map* map, HeapObject* obj); | |
106 }; | |
107 | |
108 class IncrementalMarkingObjectStatsVisitor | |
109 : public StaticMarkingVisitor<IncrementalMarkingObjectStatsVisitor> { | |
110 public: | |
111 static void Initialize(VisitorDispatchTable<Callback>* original); | |
112 | |
113 template <VisitorId id> | |
114 static inline void Visit(Map* map, HeapObject* obj); | |
115 }; | 128 }; |
116 | 129 |
117 } // namespace internal | 130 } // namespace internal |
118 } // namespace v8 | 131 } // namespace v8 |
119 | 132 |
120 #endif // V8_HEAP_OBJECT_STATS_H_ | 133 #endif // V8_HEAP_OBJECT_STATS_H_ |
OLD | NEW |