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