Commit f182fecc authored by Michael Lippautz's avatar Michael Lippautz Committed by V8 LUCI CQ

cppgc: Allow for differentiating committed and physical size on a page

- Allows for differentiating committed and physical (resident) size on
  a page. This change merely adjusts the API surface and does not
  implement resident set size tracking.
- Add object types on page level as well which helps diagnosing almost
  empty pages.

Bug: chromium:1056170
Change-Id: I64c69dc55873a0ce97d2064356bfcd957e10cbf9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3011164
Auto-Submit: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarAnton Bikineev <bikineev@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75621}
parent bb78e628
......@@ -36,9 +36,9 @@ struct HeapStatistics final {
* these objects.
*/
struct ObjectStatistics {
/** Number of distinct types in the heap. */
/** Number of distinct object types. */
size_t num_types = 0;
/** Name of each type in the heap. */
/** Name of each type. */
std::vector<std::string> type_name;
/** Number of allocated objects per each type. */
std::vector<size_t> type_count;
......@@ -51,10 +51,21 @@ struct HeapStatistics final {
* allocated memory size and overall used memory size for the page.
*/
struct PageStatistics {
/** Overall amount of memory allocated for the page. */
/** Overall committed amount of memory for the page. */
size_t committed_size_bytes = 0;
/**
* Resident amount of memory held by the page.
*
* Deprecated, use `resident_size_bytes`.
*/
size_t physical_size_bytes = 0;
/** Resident amount of memory held by the page. */
size_t resident_size_bytes = 0;
/** Amount of memory actually used on the page. */
size_t used_size_bytes = 0;
/** Statistics for object allocated on the page. Filled only when
* NameProvider::HideInternalNames() is false. */
ObjectStatistics object_stats;
};
/**
......@@ -81,8 +92,16 @@ struct HeapStatistics final {
struct SpaceStatistics {
/** The space name */
std::string name;
/** Overall amount of memory allocated for the space. */
/** Overall committed amount of memory for the heap. */
size_t committed_size_bytes = 0;
/**
* Resident amount of memory held by the heap.
*
* Deprecated, use `resident_size_bytes`.
*/
size_t physical_size_bytes = 0;
/** Resident amount of memory held by the heap. */
size_t resident_size_bytes = 0;
/** Amount of memory actually used on the space. */
size_t used_size_bytes = 0;
/** Statistics for each of the pages in the space. */
......@@ -94,16 +113,30 @@ struct HeapStatistics final {
ObjectStatistics object_stats;
};
/** Overall amount of memory allocated for the heap. */
/** Overall committed amount of memory for the heap. */
size_t committed_size_bytes = 0;
/**
*Resident amount of memory help by the heap.
*
* Deprecated, use `resident_size_bytes`.
*/
size_t physical_size_bytes = 0;
/** Resident amount of memory help by the heap. */
size_t resident_size_bytes = 0;
/** Amount of memory actually used on the heap. */
size_t used_size_bytes = 0;
/** Detail level of this HeapStatistics. */
DetailLevel detail_level;
/** Statistics for each of the spaces in the heap. Filled only when
* detail_level is kDetailed. */
* `detail_level` is `DetailLevel::kDetailed`. */
std::vector<SpaceStatistics> space_stats;
/**
* Vector of `cppgc::GarbageCollected` types that are potentially used on the
* heap. Unused types in the vector are represented by empty strings.
*/
std::vector<std::string> type_names;
};
} // namespace cppgc
......
......@@ -147,8 +147,11 @@ HeapStatistics HeapBase::CollectStatistics(
HeapStatistics::DetailLevel detail_level) {
if (detail_level == HeapStatistics::DetailLevel::kBrief) {
return {stats_collector_->allocated_memory_size(),
stats_collector_->allocated_memory_size(),
stats_collector_->allocated_memory_size(),
stats_collector_->allocated_object_size(),
HeapStatistics::DetailLevel::kBrief,
{},
{}};
}
......
......@@ -6,8 +6,10 @@
#include <string>
#include "include/cppgc/heap-statistics.h"
#include "include/cppgc/name-provider.h"
#include "src/heap/cppgc/free-list.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-base.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/raw-heap.h"
......@@ -47,6 +49,22 @@ HeapStatistics::SpaceStatistics* InitializeSpace(HeapStatistics* stats,
return space_stats;
}
HeapStatistics::PageStatistics* InitializePage(
HeapStatistics::SpaceStatistics* stats) {
stats->page_stats.emplace_back();
HeapStatistics::PageStatistics* page_stats = &stats->page_stats.back();
if (!NameProvider::HideInternalNames()) {
const size_t num_types = GlobalGCInfoTable::Get().NumberOfGCInfos();
page_stats->object_stats.num_types = num_types;
page_stats->object_stats.type_name.resize(num_types);
page_stats->object_stats.type_count.resize(num_types);
page_stats->object_stats.type_bytes.resize(num_types);
}
return page_stats;
}
void FinalizePage(HeapStatistics::SpaceStatistics* space_stats,
HeapStatistics::PageStatistics** page_stats) {
if (*page_stats) {
......@@ -69,16 +87,19 @@ void FinalizeSpace(HeapStatistics* stats,
*space_stats = nullptr;
}
void RecordObjectType(HeapStatistics::SpaceStatistics* space_stats,
void RecordObjectType(std::vector<std::string>& type_names,
HeapStatistics::ObjectStatistics& object_stats,
HeapObjectHeader* header, size_t object_size) {
if (!NameProvider::HideInternalNames()) {
// Detailed names available.
GCInfoIndex gc_info_index = header->GetGCInfoIndex();
space_stats->object_stats.type_count[gc_info_index]++;
space_stats->object_stats.type_bytes[gc_info_index] += object_size;
if (space_stats->object_stats.type_name[gc_info_index].empty()) {
space_stats->object_stats.type_name[gc_info_index] =
header->GetName().value;
const GCInfoIndex gc_info_index = header->GetGCInfoIndex();
object_stats.type_count[gc_info_index]++;
object_stats.type_bytes[gc_info_index] += object_size;
if (object_stats.type_name[gc_info_index].empty()) {
object_stats.type_name[gc_info_index] = header->GetName().value;
}
if (type_names[gc_info_index].empty()) {
type_names[gc_info_index] = header->GetName().value;
}
}
}
......@@ -90,6 +111,11 @@ HeapStatistics HeapStatisticsCollector::CollectStatistics(HeapBase* heap) {
stats.detail_level = HeapStatistics::DetailLevel::kDetailed;
current_stats_ = &stats;
if (!NameProvider::HideInternalNames()) {
const size_t num_types = GlobalGCInfoTable::Get().NumberOfGCInfos();
current_stats_->type_names.resize(num_types);
}
Traverse(heap->raw_heap());
FinalizeSpace(current_stats_, &current_space_stats_, &current_page_stats_);
......@@ -122,35 +148,45 @@ bool HeapStatisticsCollector::VisitLargePageSpace(LargePageSpace& space) {
bool HeapStatisticsCollector::VisitNormalPage(NormalPage& page) {
DCHECK_NOT_NULL(current_space_stats_);
FinalizePage(current_space_stats_, &current_page_stats_);
current_space_stats_->page_stats.emplace_back(
HeapStatistics::PageStatistics{kPageSize, 0});
current_page_stats_ = &current_space_stats_->page_stats.back();
current_page_stats_ = InitializePage(current_space_stats_);
current_page_stats_->committed_size_bytes = kPageSize;
current_page_stats_->physical_size_bytes = kPageSize;
return false;
}
bool HeapStatisticsCollector::VisitLargePage(LargePage& page) {
DCHECK_NOT_NULL(current_space_stats_);
FinalizePage(current_space_stats_, &current_page_stats_);
HeapObjectHeader* object_header = page.ObjectHeader();
size_t object_size = page.PayloadSize();
RecordObjectType(current_space_stats_, object_header, object_size);
size_t allocated_size = LargePage::AllocationSize(object_size);
current_space_stats_->physical_size_bytes += allocated_size;
current_space_stats_->used_size_bytes += object_size;
current_space_stats_->page_stats.emplace_back(
HeapStatistics::PageStatistics{allocated_size, object_size});
return true;
const size_t object_size = page.PayloadSize();
const size_t allocated_size = LargePage::AllocationSize(object_size);
current_page_stats_ = InitializePage(current_space_stats_);
current_page_stats_->committed_size_bytes = allocated_size;
current_page_stats_->physical_size_bytes = allocated_size;
return false;
}
bool HeapStatisticsCollector::VisitHeapObjectHeader(HeapObjectHeader& header) {
DCHECK(!header.IsLargeObject());
if (header.IsFree()) return true;
DCHECK_NOT_NULL(current_space_stats_);
DCHECK_NOT_NULL(current_page_stats_);
if (header.IsFree()) return true;
size_t object_size = header.AllocatedSize();
RecordObjectType(current_space_stats_, &header, object_size);
current_page_stats_->used_size_bytes += object_size;
// For the purpose of heap statistics, the header counts towards the allocated
// object size.
const size_t allocated_object_size =
header.IsLargeObject()
? LargePage::From(
BasePage::FromPayload(const_cast<HeapObjectHeader*>(&header)))
->PayloadSize()
: header.AllocatedSize();
RecordObjectType(current_stats_->type_names,
current_space_stats_->object_stats, &header,
allocated_object_size);
RecordObjectType(current_stats_->type_names,
current_page_stats_->object_stats, &header,
allocated_object_size);
current_page_stats_->used_size_bytes += allocated_object_size;
return true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment