v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
heap-statistics-collector.cc
Go to the documentation of this file.
1// Copyright 2021 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
6
7#include <string>
8#include <unordered_map>
9
19
20namespace cppgc {
21namespace internal {
22
23namespace {
24
25std::string GetNormalPageSpaceName(size_t index) {
26 // Check that space is not a large object space.
28 // Handle regular normal page spaces.
30 return "NormalPageSpace" + std::to_string(index);
31 }
32 // Space is a custom space.
33 return "CustomSpace" +
34 std::to_string(index - RawHeap::kNumberOfRegularSpaces);
35}
36
37HeapStatistics::SpaceStatistics* InitializeSpace(HeapStatistics* stats,
38 std::string name) {
39 stats->space_stats.emplace_back();
40 HeapStatistics::SpaceStatistics* space_stats = &stats->space_stats.back();
41 space_stats->name = std::move(name);
42 return space_stats;
43}
44
45HeapStatistics::PageStatistics* InitializePage(
46 HeapStatistics::SpaceStatistics* stats) {
47 stats->page_stats.emplace_back();
48 HeapStatistics::PageStatistics* page_stats = &stats->page_stats.back();
49 return page_stats;
50}
51
52void FinalizePage(HeapStatistics::SpaceStatistics* space_stats,
53 HeapStatistics::PageStatistics** page_stats) {
54 if (*page_stats) {
55 DCHECK_NOT_NULL(space_stats);
56 space_stats->committed_size_bytes += (*page_stats)->committed_size_bytes;
57 space_stats->resident_size_bytes += (*page_stats)->resident_size_bytes;
58 space_stats->used_size_bytes += (*page_stats)->used_size_bytes;
59 }
60 *page_stats = nullptr;
61}
62
63void FinalizeSpace(HeapStatistics* stats,
64 HeapStatistics::SpaceStatistics** space_stats,
65 HeapStatistics::PageStatistics** page_stats) {
66 FinalizePage(*space_stats, page_stats);
67 if (*space_stats) {
68 DCHECK_NOT_NULL(stats);
69 stats->committed_size_bytes += (*space_stats)->committed_size_bytes;
70 stats->resident_size_bytes += (*space_stats)->resident_size_bytes;
71 stats->used_size_bytes += (*space_stats)->used_size_bytes;
72 }
73 *space_stats = nullptr;
74}
75
76void RecordObjectType(
77 std::unordered_map<const void*, size_t>& type_map,
78 std::vector<HeapStatistics::ObjectStatsEntry>& object_statistics,
79 HeapObjectHeader* header, size_t object_size) {
81 // Tries to insert a new entry into the typemap with a running counter. If
82 // the entry is already present, just returns the old one.
83 const auto it = type_map.insert({header->GetName().value, type_map.size()});
84 const size_t type_index = it.first->second;
85 if (object_statistics.size() <= type_index) {
86 object_statistics.resize(type_index + 1);
87 }
88 object_statistics[type_index].allocated_bytes += object_size;
89 object_statistics[type_index].object_count++;
90 }
91}
92
93} // namespace
94
96 HeapBase* heap) {
97 HeapStatistics stats;
99 current_stats_ = &stats;
100
101 ClassNameAsHeapObjectNameScope class_names_scope(*heap);
102
103 Traverse(heap->raw_heap());
105
107 stats.type_names.resize(type_name_to_index_map_.size());
108 for (auto& it : type_name_to_index_map_) {
109 stats.type_names[it.second] = reinterpret_cast<const char*>(it.first);
110 }
111 }
112
113 // Resident set size may be smaller than the than the recorded size in
114 // `StatsCollector` due to discarded memory that is tracked on page level.
115 // This only holds before we account for pooled memory.
116 DCHECK_GE(heap->stats_collector()->allocated_memory_size(),
117 stats.resident_size_bytes);
118
119 size_t pooled_memory = heap->page_backend()->page_pool().PooledMemory();
120 stats.committed_size_bytes += pooled_memory;
121 stats.resident_size_bytes += pooled_memory;
122 stats.pooled_memory_size_bytes = pooled_memory;
123
124 return stats;
125}
126
128 DCHECK_EQ(0u, space.linear_allocation_buffer().size());
129
131
133 InitializeSpace(current_stats_, GetNormalPageSpaceName(space.index()));
134
135 space.free_list().CollectStatistics(current_space_stats_->free_list_stats);
136
137 return false;
138}
139
142
143 current_space_stats_ = InitializeSpace(current_stats_, "LargePageSpace");
144
145 return false;
146}
147
158
162
163 const size_t object_size = page.PayloadSize();
164 const size_t allocated_size = LargePage::AllocationSize(object_size);
168 return false;
169}
170
172 if (header.IsFree()) return true;
173
176 // For the purpose of heap statistics, the header counts towards the allocated
177 // object size.
178 const size_t allocated_object_size =
179 header.IsLargeObject()
181 BasePage::FromPayload(const_cast<HeapObjectHeader*>(&header)))
182 ->PayloadSize()
183 : header.AllocatedSize();
184 RecordObjectType(type_name_to_index_map_,
186 allocated_object_size);
187 current_page_stats_->used_size_bytes += allocated_object_size;
188 return true;
189}
190
191} // namespace internal
192} // namespace cppgc
static constexpr bool SupportsCppClassNamesAsObjectNames()
static BasePage * FromPayload(void *)
Definition heap-page.h:314
HeapStatistics::SpaceStatistics * current_space_stats_
HeapStatistics::PageStatistics * current_page_stats_
std::unordered_map< const void *, size_t > type_name_to_index_map_
static LargePage * From(BasePage *page)
Definition heap-page.h:275
static size_t AllocationSize(size_t size)
Definition heap-page.cc:245
size_t PayloadSize() const
Definition heap-page.h:291
static constexpr size_t kNumberOfRegularSpaces
Definition raw-heap.h:43
constexpr size_t kPageSize
Definition globals.h:42
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
std::vector< ObjectStatsEntry > object_statistics