[obj-stats] Count more field types (Smi, boxed double, string)

Distinguish between generic Tagged and Smi in-object fields, and special
case (boxed) double values and string data rather than lumping those
into generic "raw data"

Change-Id: I5d635434ab94065c077a40110948424c31ead73d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1718154
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62914}
This commit is contained in:
Leszek Swirski 2019-07-25 14:30:24 +02:00 committed by Commit Bot
parent dd7190a979
commit b50ee58ca7
4 changed files with 87 additions and 14 deletions

View File

@ -35,11 +35,16 @@ class FieldStatsCollector : public ObjectVisitor {
public:
FieldStatsCollector(size_t* tagged_fields_count,
size_t* embedder_fields_count,
size_t* inobject_smi_fields_count,
size_t* unboxed_double_fields_count,
size_t* raw_fields_count)
size_t* boxed_double_fields_count,
size_t* string_data_count, size_t* raw_fields_count)
: tagged_fields_count_(tagged_fields_count),
embedder_fields_count_(embedder_fields_count),
inobject_smi_fields_count_(inobject_smi_fields_count),
unboxed_double_fields_count_(unboxed_double_fields_count),
boxed_double_fields_count_(boxed_double_fields_count),
string_data_count_(string_data_count),
raw_fields_count_(raw_fields_count) {}
void RecordStats(HeapObject host) {
@ -62,11 +67,32 @@ class FieldStatsCollector : public ObjectVisitor {
*tagged_fields_count_ -= field_stats.embedded_fields_count_;
*embedder_fields_count_ += field_stats.embedded_fields_count_;
// Smi fields are also included into pointer words.
DCHECK_LE(
field_stats.unboxed_double_fields_count_ * kDoubleSize / kTaggedSize,
raw_fields_count_in_object);
tagged_fields_count_in_object -= field_stats.smi_fields_count_;
*tagged_fields_count_ -= field_stats.smi_fields_count_;
*inobject_smi_fields_count_ += field_stats.smi_fields_count_;
// The rest are data words.
DCHECK_LE(field_stats.unboxed_double_fields_count_,
raw_fields_count_in_object);
raw_fields_count_in_object -= field_stats.unboxed_double_fields_count_;
DCHECK_LE(
field_stats.unboxed_double_fields_count_ * kDoubleSize / kTaggedSize,
raw_fields_count_in_object);
raw_fields_count_in_object -=
field_stats.unboxed_double_fields_count_ * kDoubleSize / kTaggedSize;
*unboxed_double_fields_count_ += field_stats.unboxed_double_fields_count_;
} else if (host.IsHeapNumber() || host.IsMutableHeapNumber()) {
DCHECK_LE(kDoubleSize / kTaggedSize, raw_fields_count_in_object);
raw_fields_count_in_object -= kDoubleSize / kTaggedSize;
*boxed_double_fields_count_ += 1;
} else if (host.IsSeqString()) {
int string_data = SeqString::cast(host).synchronized_length() *
(String::cast(host).IsOneByteRepresentation() ? 1 : 2) /
kTaggedSize;
DCHECK_LE(string_data, raw_fields_count_in_object);
raw_fields_count_in_object -= string_data;
*string_data_count_ += string_data;
}
*raw_fields_count_ += raw_fields_count_in_object;
}
@ -92,9 +118,12 @@ class FieldStatsCollector : public ObjectVisitor {
private:
struct JSObjectFieldStats {
JSObjectFieldStats()
: embedded_fields_count_(0), unboxed_double_fields_count_(0) {}
: embedded_fields_count_(0),
smi_fields_count_(0),
unboxed_double_fields_count_(0) {}
unsigned embedded_fields_count_ : kDescriptorIndexBitCount;
unsigned smi_fields_count_ : kDescriptorIndexBitCount;
unsigned unboxed_double_fields_count_ : kDescriptorIndexBitCount;
};
std::unordered_map<Map, JSObjectFieldStats, Object::Hasher>
@ -104,7 +133,10 @@ class FieldStatsCollector : public ObjectVisitor {
size_t* const tagged_fields_count_;
size_t* const embedder_fields_count_;
size_t* const inobject_smi_fields_count_;
size_t* const unboxed_double_fields_count_;
size_t* const boxed_double_fields_count_;
size_t* const string_data_count_;
size_t* const raw_fields_count_;
};
@ -130,6 +162,9 @@ FieldStatsCollector::GetInobjectFieldStats(Map map) {
map.IsUnboxedDoubleField(index)) {
++stats.unboxed_double_fields_count_;
}
if (details.representation().IsSmi()) {
++stats.smi_fields_count_;
}
}
}
}
@ -149,7 +184,10 @@ void ObjectStats::ClearObjectStats(bool clear_last_time_stats) {
}
tagged_fields_count_ = 0;
embedder_fields_count_ = 0;
inobject_smi_fields_count_ = 0;
unboxed_double_fields_count_ = 0;
boxed_double_fields_count_ = 0;
string_data_count_ = 0;
raw_fields_count_ = 0;
}
@ -208,8 +246,13 @@ void ObjectStats::PrintJSON(const char* key) {
PrintF(", \"tagged_fields\": %zu", tagged_fields_count_ * kTaggedSize);
PrintF(", \"embedder_fields\": %zu",
embedder_fields_count_ * kEmbedderDataSlotSize);
PrintF(", \"inobject_smi_fields\": %zu",
inobject_smi_fields_count_ * kTaggedSize);
PrintF(", \"unboxed_double_fields\": %zu",
unboxed_double_fields_count_ * kDoubleSize);
PrintF(", \"boxed_double_fields\": %zu",
boxed_double_fields_count_ * kDoubleSize);
PrintF(", \"string_data\": %zu", string_data_count_ * kTaggedSize);
PrintF(", \"other_raw_fields\": %zu", raw_fields_count_ * kSystemPointerSize);
PrintF(" }\n");
// bucket_sizes
@ -263,8 +306,13 @@ void ObjectStats::Dump(std::stringstream& stream) {
stream << "\"tagged_fields\":" << (tagged_fields_count_ * kTaggedSize);
stream << ",\"embedder_fields\":"
<< (embedder_fields_count_ * kEmbedderDataSlotSize);
stream << ",\"inobject_smi_fields\": "
<< (inobject_smi_fields_count_ * kTaggedSize);
stream << ",\"unboxed_double_fields\": "
<< (unboxed_double_fields_count_ * kDoubleSize);
stream << ",\"boxed_double_fields\": "
<< (boxed_double_fields_count_ * kDoubleSize);
stream << ",\"string_data\": " << (string_data_count_ * kTaggedSize);
stream << ",\"other_raw_fields\":"
<< (raw_fields_count_ * kSystemPointerSize);
stream << "}, ";
@ -427,7 +475,10 @@ ObjectStatsCollectorImpl::ObjectStatsCollectorImpl(Heap* heap,
heap->mark_compact_collector()->non_atomic_marking_state()),
field_stats_collector_(
&stats->tagged_fields_count_, &stats->embedder_fields_count_,
&stats->unboxed_double_fields_count_, &stats->raw_fields_count_) {}
&stats->inobject_smi_fields_count_,
&stats->unboxed_double_fields_count_,
&stats->boxed_double_fields_count_, &stats->string_data_count_,
&stats->raw_fields_count_) {}
bool ObjectStatsCollectorImpl::ShouldRecordObject(HeapObject obj,
CowMode check_cow_array) {

View File

@ -167,7 +167,10 @@ class ObjectStats {
size_t tagged_fields_count_;
size_t embedder_fields_count_;
size_t inobject_smi_fields_count_;
size_t unboxed_double_fields_count_;
size_t boxed_double_fields_count_;
size_t string_data_count_;
size_t raw_fields_count_;
friend class ObjectStatsCollectorImpl;

View File

@ -63,9 +63,12 @@ class GlobalTimeline extends HTMLElement {
{type: 'number', label: 'Ptr compression benefit'},
{type: 'string', role: 'tooltip'},
{type: 'number', label: 'Embedder fields'},
{type: 'number', label: 'Tagged fields'},
{type: 'number', label: 'Tagged fields (excl. in-object Smis)'},
{type: 'number', label: 'In-object Smi-only fields'},
{type: 'number', label: 'Other raw fields'},
{type: 'number', label: 'Unboxed doubles'}
{type: 'number', label: 'Unboxed doubles'},
{type: 'number', label: 'Boxed doubles'},
{type: 'number', label: 'String data'}
];
const chart_data = [labels];
const isolate_data = this.data[this.selection.isolate];
@ -78,10 +81,14 @@ class GlobalTimeline extends HTMLElement {
const data = [];
data.push(gc_data.time * kMillis2Seconds);
const total = data_set.tagged_fields +
data_set.inobject_smi_fields +
data_set.embedder_fields +
data_set.other_raw_fields +
data_set.unboxed_double_fields;
const ptr_compr_benefit = data_set.tagged_fields / 2;
data_set.unboxed_double_fields +
data_set.boxed_double_fields +
data_set.string_data;
const ptr_compr_benefit =
(data_set.smi_fields + data_set.tagged_fields) / 2;
const ptr_compr_benefit_perc = ptr_compr_benefit / total * 100;
sum_total += total;
sum_ptr_compr_benefit_perc += ptr_compr_benefit_perc;
@ -92,9 +99,12 @@ class GlobalTimeline extends HTMLElement {
data.push(ptr_compr_benefit / KB);
data.push(tooltip);
data.push(data_set.embedder_fields / KB);
data.push(data_set.inobject_smi_fields / KB);
data.push(data_set.tagged_fields / KB);
data.push(data_set.other_raw_fields / KB);
data.push(data_set.unboxed_double_fields / KB);
data.push(data_set.boxed_double_fields / KB);
data.push(data_set.string_data / KB);
chart_data.push(data);
});
const avg_ptr_compr_benefit_perc =

View File

@ -137,11 +137,15 @@ class TraceFileReader extends HTMLElement {
}
addFieldTypeData(data, isolate, gc_id, data_set, tagged_fields,
embedder_fields, unboxed_double_fields, other_raw_fields) {
inobject_smi_fields, embedder_fields, unboxed_double_fields,
boxed_double_fields, string_data, other_raw_fields) {
data[isolate].gcs[gc_id][data_set].field_data = {
tagged_fields,
inobject_smi_fields,
embedder_fields,
unboxed_double_fields,
boxed_double_fields,
string_data,
other_raw_fields
};
}
@ -217,8 +221,12 @@ class TraceFileReader extends HTMLElement {
const field_data = entry.field_data;
this.addFieldTypeData(data, isolate, gc_id, data_set,
field_data.tagged_fields, field_data.embedder_fields,
field_data.tagged_fields,
field_data.inobject_smi_fields,
field_data.embedder_fields,
field_data.unboxed_double_fields,
field_data.boxed_double_fields,
field_data.string_data,
field_data.other_raw_fields);
data[isolate].gcs[gc_id][data_set].bucket_sizes =
@ -282,8 +290,9 @@ class TraceFileReader extends HTMLElement {
this.createOrUpdateEntryIfNeeded(data, entry);
this.createDatasetIfNeeded(data, entry, entry.key);
this.addFieldTypeData(data, entry.isolate, entry.id, entry.key,
entry.tagged_fields, entry.embedder_fields,
entry.unboxed_double_fields, entry.other_raw_fields);
entry.tagged_fields, entry.embedder_fields, entry.inobject_smi_fields,
entry.unboxed_double_fields, entry.boxed_double_fields,
entry.string_data, entry.other_raw_fields);
} else if (entry.type === 'instance_type_data') {
if (entry.id in data[entry.isolate].gcs) {
this.createOrUpdateEntryIfNeeded(data, entry);