[Tracing] Integrate GC object statistics with tracing.

Memory infra in tracing currently uses Isolate::GetHeapStatistics to fetch
object statistics from V8 at certain frequency, which is not accurate and will
have redundant result. This path adds a trace event as well as a trace category
at where we collect object statistics after marking before sweeping, and dumps
all information to the trace event.

In order to use this functionality, we need to enable two flags:
--track-gc-object-stats and --noincremental-marking.

BUG=v8:5453

Review-Url: https://codereview.chromium.org/2379823004
Cr-Commit-Position: refs/heads/master@{#39966}
This commit is contained in:
lpy 2016-10-04 17:41:25 -07:00 committed by Commit bot
parent fa5b221ec7
commit a5a9198a9b
3 changed files with 72 additions and 0 deletions

View File

@ -2246,6 +2246,13 @@ void MarkCompactCollector::RecordObjectStats() {
ObjectStatsVisitor visitor(heap(), heap()->live_object_stats_,
heap()->dead_object_stats_);
VisitAllObjects(&visitor);
std::stringstream live, dead;
heap()->live_object_stats_->Dump(live);
heap()->dead_object_stats_->Dump(dead);
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.gc_stats"),
"V8.GC_Objects_Stats", TRACE_EVENT_SCOPE_THREAD,
"live", TRACE_STR_COPY(live.str().c_str()), "dead",
TRACE_STR_COPY(dead.str().c_str()));
if (FLAG_trace_gc_object_stats) {
heap()->live_object_stats_->PrintJSON("live");
heap()->dead_object_stats_->PrintJSON("dead");

View File

@ -42,6 +42,16 @@ V8_NOINLINE static void PrintJSONArray(size_t* array, const int len) {
PrintF(" ]");
}
V8_NOINLINE static void DumpJSONArray(std::stringstream& stream, size_t* array,
const int len) {
stream << "[";
for (int i = 0; i < len; i++) {
stream << array[i];
if (i != (len - 1)) stream << ",";
}
stream << "]";
}
void ObjectStats::PrintJSON(const char* key) {
double time = isolate()->time_millis_since_init();
int gc_count = heap()->gc_count();
@ -97,6 +107,60 @@ void ObjectStats::PrintJSON(const char* key) {
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER)
CODE_AGE_LIST_COMPLETE(CODE_AGE_WRAPPER)
#undef INSTANCE_TYPE_WRAPPER
#undef CODE_KIND_WRAPPER
#undef FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER
#undef CODE_AGE_WRAPPER
#undef PRINT_INSTANCE_TYPE_DATA
#undef PRINT_KEY_AND_ID
}
void ObjectStats::Dump(std::stringstream& stream) {
double time = isolate()->time_millis_since_init();
int gc_count = heap()->gc_count();
stream << "{";
stream << "\"isolate\":\"" << reinterpret_cast<void*>(isolate()) << "\",";
stream << "\"id\":" << gc_count << ",";
stream << "\"time\":" << time << ",";
stream << "\"bucket_sizes\":[";
for (int i = 0; i < kNumberOfBuckets; i++) {
stream << (1 << (kFirstBucketShift + i));
if (i != (kNumberOfBuckets - 1)) stream << ",";
}
stream << "],";
stream << "\"type_data\":{";
#define PRINT_INSTANCE_TYPE_DATA(name, index) \
stream << "\"" << name << "\":{"; \
stream << "\"type\":" << static_cast<int>(index) << ","; \
stream << "\"overall\":" << object_sizes_[index] << ","; \
stream << "\"count\":" << object_counts_[index] << ","; \
stream << "\"over_allocated\":" << over_allocated_[index] << ","; \
stream << "\"histogram\":"; \
DumpJSONArray(stream, size_histogram_[index], kNumberOfBuckets); \
stream << ",\"over_allocated_histogram\":"; \
DumpJSONArray(stream, over_allocated_histogram_[index], kNumberOfBuckets); \
stream << "},";
#define INSTANCE_TYPE_WRAPPER(name) PRINT_INSTANCE_TYPE_DATA(#name, name)
#define CODE_KIND_WRAPPER(name) \
PRINT_INSTANCE_TYPE_DATA("*CODE_" #name, \
FIRST_CODE_KIND_SUB_TYPE + Code::name)
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER(name) \
PRINT_INSTANCE_TYPE_DATA("*FIXED_ARRAY_" #name, \
FIRST_FIXED_ARRAY_SUB_TYPE + name)
#define CODE_AGE_WRAPPER(name) \
PRINT_INSTANCE_TYPE_DATA( \
"*CODE_AGE_" #name, \
FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - Code::kFirstCodeAge)
INSTANCE_TYPE_LIST(INSTANCE_TYPE_WRAPPER);
CODE_KIND_LIST(CODE_KIND_WRAPPER);
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER);
CODE_AGE_LIST_COMPLETE(CODE_AGE_WRAPPER);
stream << "\"END\":{}}}";
#undef INSTANCE_TYPE_WRAPPER
#undef CODE_KIND_WRAPPER
#undef FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER

View File

@ -35,6 +35,7 @@ class ObjectStats {
void CheckpointObjectStats();
void PrintJSON(const char* key);
void Dump(std::stringstream& stream);
void RecordObjectStats(InstanceType type, size_t size) {
DCHECK(type <= LAST_TYPE);