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

Reply via email to