Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_HEAP_OBJECT_STATS_H_
6 : #define V8_HEAP_OBJECT_STATS_H_
7 :
8 : #include <set>
9 :
10 : #include "src/base/ieee754.h"
11 : #include "src/heap/heap.h"
12 : #include "src/heap/mark-compact.h"
13 : #include "src/heap/objects-visiting.h"
14 : #include "src/objects.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : class ObjectStats {
20 : public:
21 0 : explicit ObjectStats(Heap* heap) : heap_(heap) { ClearObjectStats(); }
22 :
23 : // ObjectStats are kept in two arrays, counts and sizes. Related stats are
24 : // stored in a contiguous linear buffer. Stats groups are stored one after
25 : // another.
26 : enum {
27 : FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1,
28 : FIRST_FIXED_ARRAY_SUB_TYPE =
29 : FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS,
30 : OBJECT_STATS_COUNT =
31 : FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1,
32 : };
33 :
34 : void ClearObjectStats(bool clear_last_time_stats = false);
35 :
36 : void CheckpointObjectStats();
37 : void PrintJSON(const char* key);
38 : void Dump(std::stringstream& stream);
39 :
40 : void RecordObjectStats(InstanceType type, size_t size) {
41 : DCHECK(type <= LAST_TYPE);
42 0 : object_counts_[type]++;
43 0 : object_sizes_[type] += size;
44 0 : size_histogram_[type][HistogramIndexFromSize(size)]++;
45 : }
46 :
47 0 : void RecordCodeSubTypeStats(int code_sub_type, size_t size) {
48 0 : int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type;
49 : DCHECK(code_sub_type_index >= FIRST_CODE_KIND_SUB_TYPE &&
50 : code_sub_type_index < FIRST_FIXED_ARRAY_SUB_TYPE);
51 0 : object_counts_[code_sub_type_index]++;
52 0 : object_sizes_[code_sub_type_index] += size;
53 0 : const int idx = HistogramIndexFromSize(size);
54 0 : size_histogram_[code_sub_type_index][idx]++;
55 0 : }
56 :
57 0 : bool RecordFixedArraySubTypeStats(FixedArrayBase* array, int array_sub_type,
58 : size_t size, size_t over_allocated) {
59 : auto it = visited_fixed_array_sub_types_.insert(array);
60 0 : if (!it.second) return false;
61 : DCHECK(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE);
62 0 : object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++;
63 0 : object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size;
64 : size_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]
65 0 : [HistogramIndexFromSize(size)]++;
66 0 : if (over_allocated > 0) {
67 : InstanceType type =
68 0 : array->IsHashTable() ? HASH_TABLE_TYPE : FIXED_ARRAY_TYPE;
69 : over_allocated_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] +=
70 0 : over_allocated;
71 : over_allocated_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]
72 0 : [HistogramIndexFromSize(over_allocated)]++;
73 0 : over_allocated_[type] += over_allocated;
74 0 : over_allocated_histogram_[type][HistogramIndexFromSize(over_allocated)]++;
75 : }
76 : return true;
77 : }
78 :
79 : size_t object_count_last_gc(size_t index) {
80 0 : return object_counts_last_time_[index];
81 : }
82 :
83 : size_t object_size_last_gc(size_t index) {
84 0 : return object_sizes_last_time_[index];
85 : }
86 :
87 : Isolate* isolate();
88 : Heap* heap() { return heap_; }
89 :
90 : private:
91 : static const int kFirstBucketShift = 5; // <=32
92 : static const int kLastBucketShift = 19; // >512k
93 : static const int kFirstBucket = 1 << kFirstBucketShift;
94 : static const int kLastBucket = 1 << kLastBucketShift;
95 : static const int kNumberOfBuckets = kLastBucketShift - kFirstBucketShift + 1;
96 :
97 : void PrintKeyAndId(const char* key, int gc_count);
98 : // The following functions are excluded from inline to reduce the overall
99 : // binary size of VB. On x64 this save around 80KB.
100 : V8_NOINLINE void PrintInstanceTypeJSON(const char* key, int gc_count,
101 : const char* name, int index);
102 : V8_NOINLINE void DumpInstanceTypeData(std::stringstream& stream,
103 : const char* name, int index);
104 :
105 0 : int HistogramIndexFromSize(size_t size) {
106 0 : if (size == 0) return 0;
107 0 : int idx = static_cast<int>(base::ieee754::log2(static_cast<double>(size))) -
108 0 : kFirstBucketShift;
109 0 : return idx < 0 ? 0 : idx;
110 : }
111 :
112 : Heap* heap_;
113 : // Object counts and used memory by InstanceType.
114 : size_t object_counts_[OBJECT_STATS_COUNT];
115 : size_t object_counts_last_time_[OBJECT_STATS_COUNT];
116 : size_t object_sizes_[OBJECT_STATS_COUNT];
117 : size_t object_sizes_last_time_[OBJECT_STATS_COUNT];
118 : // Approximation of overallocated memory by InstanceType.
119 : size_t over_allocated_[OBJECT_STATS_COUNT];
120 : // Detailed histograms by InstanceType.
121 : size_t size_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets];
122 : size_t over_allocated_histogram_[OBJECT_STATS_COUNT][kNumberOfBuckets];
123 :
124 : std::set<FixedArrayBase*> visited_fixed_array_sub_types_;
125 : };
126 :
127 : class ObjectStatsCollector {
128 : public:
129 : ObjectStatsCollector(Heap* heap, ObjectStats* stats);
130 :
131 : void CollectGlobalStatistics();
132 : void CollectStatistics(HeapObject* obj);
133 :
134 : private:
135 : class CompilationCacheTableVisitor;
136 :
137 : void RecordBytecodeArrayDetails(BytecodeArray* obj);
138 : void RecordCodeDetails(Code* code);
139 : void RecordFixedArrayDetails(FixedArray* array);
140 : void RecordJSCollectionDetails(JSObject* obj);
141 : void RecordJSObjectDetails(JSObject* object);
142 : void RecordJSWeakCollectionDetails(JSWeakCollection* obj);
143 : void RecordMapDetails(Map* map);
144 : void RecordScriptDetails(Script* obj);
145 : void RecordTemplateInfoDetails(TemplateInfo* obj);
146 : void RecordSharedFunctionInfoDetails(SharedFunctionInfo* sfi);
147 :
148 : bool RecordFixedArrayHelper(HeapObject* parent, FixedArray* array,
149 : int subtype, size_t overhead);
150 : void RecursivelyRecordFixedArrayHelper(HeapObject* parent, FixedArray* array,
151 : int subtype);
152 : template <class HashTable>
153 : void RecordHashTableHelper(HeapObject* parent, HashTable* array, int subtype);
154 : bool SameLiveness(HeapObject* obj1, HeapObject* obj2);
155 : Heap* heap_;
156 : ObjectStats* stats_;
157 : MarkCompactCollector::NonAtomicMarkingState* marking_state_;
158 :
159 : friend class ObjectStatsCollector::CompilationCacheTableVisitor;
160 : };
161 :
162 : } // namespace internal
163 : } // namespace v8
164 :
165 : #endif // V8_HEAP_OBJECT_STATS_H_
|