Revision: 12082
Author: [email protected]
Date: Fri Jul 13 05:22:09 2012
Log: Add counters that automatically track object sizes and counts.
Review URL: https://chromiumcodereview.appspot.com/10702168
http://code.google.com/p/v8/source/detail?r=12082
Modified:
/branches/bleeding_edge/src/d8.cc
/branches/bleeding_edge/src/d8.h
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/objects-visiting.h
/branches/bleeding_edge/src/v8-counters.cc
/branches/bleeding_edge/src/v8-counters.h
=======================================
--- /branches/bleeding_edge/src/d8.cc Tue Jul 3 06:44:36 2012
+++ /branches/bleeding_edge/src/d8.cc Fri Jul 13 05:22:09 2012
@@ -1301,20 +1301,24 @@
counters[j].key = i.CurrentKey();
}
qsort(counters, number_of_counters, sizeof(counters[0]), CompareKeys);
-
printf("+--------------------------------------------+-------------+\n");
- printf("| Name | Value |
\n");
-
printf("+--------------------------------------------+-------------+\n");
+
printf("+----------------------------------------------------------------+"
+ "-------------+\n");
+ printf("|
Name |"
+ " Value |\n");
+
printf("+----------------------------------------------------------------+"
+ "-------------+\n");
for (j = 0; j < number_of_counters; j++) {
Counter* counter = counters[j].counter;
const char* key = counters[j].key;
if (counter->is_histogram()) {
- printf("| c:%-40s | %11i |\n", key, counter->count());
- printf("| t:%-40s | %11i |\n", key, counter->sample_total());
+ printf("| c:%-60s | %11i |\n", key, counter->count());
+ printf("| t:%-60s | %11i |\n", key, counter->sample_total());
} else {
- printf("| %-42s | %11i |\n", key, counter->count());
+ printf("| %-62s | %11i |\n", key, counter->count());
}
}
-
printf("+--------------------------------------------+-------------+\n");
+
printf("+----------------------------------------------------------------+"
+ "-------------+\n");
delete [] counters;
}
delete counters_file_;
=======================================
--- /branches/bleeding_edge/src/d8.h Tue Jul 3 06:44:36 2012
+++ /branches/bleeding_edge/src/d8.h Fri Jul 13 05:22:09 2012
@@ -67,7 +67,7 @@
CounterCollection();
Counter* GetNextCounter();
private:
- static const unsigned kMaxCounters = 256;
+ static const unsigned kMaxCounters = 512;
uint32_t magic_number_;
uint32_t max_counters_;
uint32_t max_name_size_;
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Wed Jul 11 07:09:42 2012
+++ /branches/bleeding_edge/src/flag-definitions.h Fri Jul 13 05:22:09 2012
@@ -367,6 +367,8 @@
DEFINE_bool(incremental_marking_steps, true, "do incremental marking
steps")
DEFINE_bool(trace_incremental_marking, false,
"trace progress of the incremental marking")
+DEFINE_bool(track_gc_object_stats, false,
+ "track object counts and memory usage")
// v8.cc
DEFINE_bool(use_idle_notification, true,
=======================================
--- /branches/bleeding_edge/src/heap.cc Fri Jul 13 05:12:09 2012
+++ /branches/bleeding_edge/src/heap.cc Fri Jul 13 05:22:09 2012
@@ -179,6 +179,8 @@
// Put a dummy entry in the remembered pages so we can find the list the
// minidump even if there are no real unmapped pages.
RememberUnmappedPage(NULL, false);
+
+ ClearObjectStats(true);
}
@@ -7196,5 +7198,36 @@
remembered_unmapped_pages_index_++;
remembered_unmapped_pages_index_ %= kRememberedUnmappedPages;
}
+
+
+void Heap::ClearObjectStats(bool clear_last_time_stats) {
+ memset(object_counts_, 0, sizeof(object_counts_));
+ memset(object_sizes_, 0, sizeof(object_sizes_));
+ if (clear_last_time_stats) {
+ memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_));
+ memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_));
+ }
+}
+
+
+static LazyMutex checkpoint_object_stats_mutex = LAZY_MUTEX_INITIALIZER;
+
+
+void Heap::CheckpointObjectStats() {
+ ScopedLock lock(checkpoint_object_stats_mutex.Pointer());
+ Counters* counters = isolate()->counters();
+#define ADJUST_LAST_TIME_OBJECT_COUNT(name) \
+ counters->count_of_##name()->Increment(object_counts_[name]); \
+ counters->count_of_##name()->Decrement(object_counts_last_time_[name]); \
+ counters->size_of_##name()->Increment(object_sizes_[name]); \
+ counters->size_of_##name()->Decrement(object_sizes_last_time_[name]);
+ INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
+#undef ADJUST_LAST_TIME_OBJECT_COUNT
+ memcpy(object_counts_last_time_, object_counts_,
+ sizeof(object_counts_));
+ memcpy(object_sizes_last_time_, object_sizes_,
+ sizeof(object_sizes_));
+ ClearObjectStats();
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Jul 9 01:59:03 2012
+++ /branches/bleeding_edge/src/heap.h Fri Jul 13 05:22:09 2012
@@ -1600,6 +1600,14 @@
global_ic_age_ = (global_ic_age_ + 1) &
SharedFunctionInfo::ICAgeBits::kMax;
}
+ void RecordObjectStats(InstanceType type, size_t size) {
+ ASSERT(type <= LAST_TYPE);
+ object_counts_[type]++;
+ object_sizes_[type] += size;
+ }
+
+ void CheckpointObjectStats();
+
private:
Heap();
@@ -1993,11 +2001,18 @@
void AdvanceIdleIncrementalMarking(intptr_t step_size);
+ void ClearObjectStats(bool clear_last_time_stats = false);
static const int kInitialSymbolTableSize = 2048;
static const int kInitialEvalCacheSize = 64;
static const int kInitialNumberStringCacheSize = 256;
+ // Object counts and used memory by InstanceType
+ size_t object_counts_[LAST_TYPE + 1];
+ size_t object_counts_last_time_[LAST_TYPE + 1];
+ size_t object_sizes_[LAST_TYPE + 1];
+ size_t object_sizes_last_time_[LAST_TYPE + 1];
+
// Maximum GC pause.
int max_gc_pause_;
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Tue Jul 10 06:31:36 2012
+++ /branches/bleeding_edge/src/mark-compact.cc Fri Jul 13 05:22:09 2012
@@ -943,6 +943,17 @@
static inline void IterateBody(Map* map, HeapObject* obj) {
table_.GetVisitor(map)(map, obj);
}
+
+ template<int id>
+ class ObjectStatsTracker {
+ public:
+ static inline void Visit(Map* map, HeapObject* obj) {
+ Heap* heap = map->GetHeap();
+ int object_size = obj->Size();
+ heap->RecordObjectStats(map->instance_type(), object_size);
+ non_count_table_.GetVisitorById(static_cast<VisitorId>(id))(map,
obj);
+ }
+ };
static void Initialize() {
table_.Register(kVisitShortcutCandidate,
@@ -1012,6 +1023,15 @@
table_.RegisterSpecializations<StructObjectVisitor,
kVisitStruct,
kVisitStructGeneric>();
+
+ if (FLAG_track_gc_object_stats) {
+ // Copy the visitor table to make call-through possible.
+ non_count_table_.CopyFrom(&table_);
+#define VISITOR_ID_COUNT_FUNCTION(id)\
+ table_.Register(kVisit##id, ObjectStatsTracker<kVisit##id>::Visit);
+ VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION)
+#undef VISITOR_ID_COUNT_FUNCTION
+ }
}
INLINE(static void VisitPointer(Heap* heap, Object** p)) {
@@ -1557,11 +1577,14 @@
typedef void (*Callback)(Map* map, HeapObject* object);
static VisitorDispatchTable<Callback> table_;
+ static VisitorDispatchTable<Callback> non_count_table_;
};
VisitorDispatchTable<StaticMarkingVisitor::Callback>
StaticMarkingVisitor::table_;
+VisitorDispatchTable<StaticMarkingVisitor::Callback>
+ StaticMarkingVisitor::non_count_table_;
class MarkingVisitor : public ObjectVisitor {
@@ -2437,6 +2460,10 @@
// Clean up dead objects from the runtime profiler.
heap()->isolate()->runtime_profiler()->RemoveDeadSamples();
}
+
+ if (FLAG_track_gc_object_stats) {
+ heap()->CheckpointObjectStats();
+ }
}
=======================================
--- /branches/bleeding_edge/src/objects-visiting.h Tue Apr 17 03:37:41 2012
+++ /branches/bleeding_edge/src/objects-visiting.h Fri Jul 13 05:22:09 2012
@@ -46,71 +46,70 @@
// Base class for all static visitors.
class StaticVisitorBase : public AllStatic {
public:
- enum VisitorId {
- kVisitSeqAsciiString = 0,
- kVisitSeqTwoByteString,
- kVisitShortcutCandidate,
- kVisitByteArray,
- kVisitFreeSpace,
- kVisitFixedArray,
- kVisitFixedDoubleArray,
- kVisitGlobalContext,
-
- // For data objects, JS objects and structs along with generic visitor
which
- // can visit object of any size we provide visitors specialized by
- // object size in words.
- // Ids of specialized visitors are declared in a linear order (without
- // holes) starting from the id of visitor specialized for 2 words
objects
- // (base visitor id) and ending with the id of generic visitor.
- // Method GetVisitorIdForSize depends on this ordering to calculate
visitor
- // id of specialized visitor from given instance size, base visitor id
and
- // generic visitor's id.
-
- kVisitDataObject,
- kVisitDataObject2 = kVisitDataObject,
- kVisitDataObject3,
- kVisitDataObject4,
- kVisitDataObject5,
- kVisitDataObject6,
- kVisitDataObject7,
- kVisitDataObject8,
- kVisitDataObject9,
- kVisitDataObjectGeneric,
-
- kVisitJSObject,
- kVisitJSObject2 = kVisitJSObject,
- kVisitJSObject3,
- kVisitJSObject4,
- kVisitJSObject5,
- kVisitJSObject6,
- kVisitJSObject7,
- kVisitJSObject8,
- kVisitJSObject9,
- kVisitJSObjectGeneric,
-
- kVisitStruct,
- kVisitStruct2 = kVisitStruct,
- kVisitStruct3,
- kVisitStruct4,
- kVisitStruct5,
- kVisitStruct6,
- kVisitStruct7,
- kVisitStruct8,
- kVisitStruct9,
- kVisitStructGeneric,
-
- kVisitConsString,
- kVisitSlicedString,
- kVisitOddball,
- kVisitCode,
- kVisitMap,
- kVisitPropertyCell,
- kVisitSharedFunctionInfo,
- kVisitJSFunction,
- kVisitJSWeakMap,
- kVisitJSRegExp,
-
+#define VISITOR_ID_LIST(V) \
+ V(SeqAsciiString) \
+ V(SeqTwoByteString) \
+ V(ShortcutCandidate) \
+ V(ByteArray) \
+ V(FreeSpace) \
+ V(FixedArray) \
+ V(FixedDoubleArray) \
+ V(GlobalContext) \
+ V(DataObject2) \
+ V(DataObject3) \
+ V(DataObject4) \
+ V(DataObject5) \
+ V(DataObject6) \
+ V(DataObject7) \
+ V(DataObject8) \
+ V(DataObject9) \
+ V(DataObjectGeneric) \
+ V(JSObject2) \
+ V(JSObject3) \
+ V(JSObject4) \
+ V(JSObject5) \
+ V(JSObject6) \
+ V(JSObject7) \
+ V(JSObject8) \
+ V(JSObject9) \
+ V(JSObjectGeneric) \
+ V(Struct2) \
+ V(Struct3) \
+ V(Struct4) \
+ V(Struct5) \
+ V(Struct6) \
+ V(Struct7) \
+ V(Struct8) \
+ V(Struct9) \
+ V(StructGeneric) \
+ V(ConsString) \
+ V(SlicedString) \
+ V(Oddball) \
+ V(Code) \
+ V(Map) \
+ V(PropertyCell) \
+ V(SharedFunctionInfo) \
+ V(JSFunction) \
+ V(JSWeakMap) \
+ V(JSRegExp)
+
+ // For data objects, JS objects and structs along with generic visitor
which
+ // can visit object of any size we provide visitors specialized by
+ // object size in words.
+ // Ids of specialized visitors are declared in a linear order (without
+ // holes) starting from the id of visitor specialized for 2 words objects
+ // (base visitor id) and ending with the id of generic visitor.
+ // Method GetVisitorIdForSize depends on this ordering to calculate
visitor
+ // id of specialized visitor from given instance size, base visitor id
and
+ // generic visitor's id.
+ enum VisitorId {
+#define VISITOR_ID_ENUM_DECL(id) kVisit##id,
+ VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
+#undef VISITOR_ID_ENUM_DECL
kVisitorIdCount,
+ kVisitDataObject = kVisitDataObject2,
+ kVisitJSObject = kVisitJSObject2,
+ kVisitStruct = kVisitStruct2,
kMinObjectSizeInWords = 2
};
=======================================
--- /branches/bleeding_edge/src/v8-counters.cc Fri Jul 13 05:12:09 2012
+++ /branches/bleeding_edge/src/v8-counters.cc Fri Jul 13 05:22:09 2012
@@ -53,6 +53,14 @@
STATS_COUNTER_LIST_2(SC)
#undef SC
+#define SC(name) \
+ StatsCounter count_of_##name = { "c:" "V8.CountOf_" #name, NULL, false
};\
+ count_of_##name##_ = count_of_##name; \
+ StatsCounter size_of_##name = { "c:" "V8.SizeOf_" #name, NULL, false
};\
+ size_of_##name##_ = size_of_##name;
+ INSTANCE_TYPE_LIST(SC)
+#undef SC
+
StatsCounter state_counters[] = {
#define COUNTER_NAME(name) \
{ "c:V8.State" #name, NULL, false },
=======================================
--- /branches/bleeding_edge/src/v8-counters.h Fri Jul 13 05:12:09 2012
+++ /branches/bleeding_edge/src/v8-counters.h Fri Jul 13 05:22:09 2012
@@ -30,6 +30,7 @@
#include "allocation.h"
#include "counters.h"
+#include "objects.h"
#include "v8globals.h"
namespace v8 {
@@ -308,6 +309,12 @@
STATS_COUNTER_LIST_2(SC)
#undef SC
+#define SC(name) \
+ StatsCounter* count_of_##name() { return &count_of_##name##_; } \
+ StatsCounter* size_of_##name() { return &size_of_##name##_; }
+ INSTANCE_TYPE_LIST(SC)
+#undef SC
+
enum Id {
#define RATE_ID(name, caption) k_##name,
HISTOGRAM_TIMER_LIST(RATE_ID)
@@ -319,6 +326,9 @@
STATS_COUNTER_LIST_1(COUNTER_ID)
STATS_COUNTER_LIST_2(COUNTER_ID)
#undef COUNTER_ID
+#define COUNTER_ID(name) kCountOf##name, kSizeOf##name,
+ INSTANCE_TYPE_LIST(COUNTER_ID)
+#undef COUNTER_ID
#define COUNTER_ID(name) k_##name,
STATE_TAG_LIST(COUNTER_ID)
#undef COUNTER_ID
@@ -346,6 +356,12 @@
STATS_COUNTER_LIST_2(SC)
#undef SC
+#define SC(name) \
+ StatsCounter size_of_##name##_; \
+ StatsCounter count_of_##name##_;
+ INSTANCE_TYPE_LIST(SC)
+#undef SC
+
enum {
#define COUNTER_ID(name) __##name,
STATE_TAG_LIST(COUNTER_ID)
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev