Bug 930876 - Speed up per-tab profiling of JS by skipping the expensive string hashing. r=till.
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 25 Oct 2013 00:00:53 -0700
changeset 167198 2d537818dfb9e359b20bcf8a6fab80f7e7edb7ea
parent 167197 a2eecdb6d6b0ced94b3ffe8a47d831173e390d90
child 167199 4040c38ec0a52f15f8cc377873bdc9a2c3df841b
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs930876
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 930876 - Speed up per-tab profiling of JS by skipping the expensive string hashing. r=till.
js/src/vm/MemoryMetrics.cpp
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -87,18 +87,17 @@ InefficientNonFlatteningStringHashPolicy
         c2 = ownedChars2;
     }
 
     return PodEqual(c1, c2, k->length());
 }
 
 } // namespace js
 
-namespace JS
-{
+namespace JS {
 
 NotableStringInfo::NotableStringInfo()
     : bufferSize(0),
       buffer(0)
 {}
 
 NotableStringInfo::NotableStringInfo(JSString *str, const StringInfo &info)
     : StringInfo(info)
@@ -242,16 +241,22 @@ StatsArenaCallback(JSRuntime *rt, void *
 }
 
 static CompartmentStats *
 GetCompartmentStats(JSCompartment *comp)
 {
     return static_cast<CompartmentStats *>(comp->compartmentStats);
 }
 
+enum Granularity {
+    FineGrained,    // Corresponds to CollectRuntimeStats()
+    CoarseGrained   // Corresponds to AddSizeOfTab()
+};
+
+template <Granularity granularity>
 static void
 StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKind,
                   size_t thingSize)
 {
     StatsClosure *closure = static_cast<StatsClosure *>(data);
     RuntimeStats *rtStats = closure->rtStats;
     ZoneStats *zStats = rtStats->currZoneStats;
     switch (traceKind) {
@@ -278,26 +283,31 @@ StatsCellCallback(JSRuntime *rt, void *d
       }
 
       case JSTRACE_STRING: {
         JSString *str = static_cast<JSString *>(thing);
 
         size_t strCharsSize = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
         MOZ_ASSERT_IF(str->isShort(), strCharsSize == 0);
 
-        size_t shortStringThingSize = str->isShort() ? thingSize : 0;
+        size_t shortStringThingSize  =  str->isShort() ? thingSize : 0;
         size_t normalStringThingSize = !str->isShort() ? thingSize : 0;
 
-        ZoneStats::StringsHashMap::AddPtr p = zStats->strings.lookupForAdd(str);
-        if (!p) {
-            JS::StringInfo info(str->length(), shortStringThingSize,
-                                normalStringThingSize, strCharsSize);
-            zStats->strings.add(p, str, info);
-        } else {
-            p->value.add(shortStringThingSize, normalStringThingSize, strCharsSize);
+        // This string hashing is expensive.  Its results are unused when doing
+        // coarse-grained measurements, and skipping it more than doubles the
+        // profile speed for complex pages such as gmail.com.
+        if (granularity == FineGrained) {
+            ZoneStats::StringsHashMap::AddPtr p = zStats->strings.lookupForAdd(str);
+            if (!p) {
+                JS::StringInfo info(str->length(), shortStringThingSize,
+                                    normalStringThingSize, strCharsSize);
+                zStats->strings.add(p, str, info);
+            } else {
+                p->value.add(shortStringThingSize, normalStringThingSize, strCharsSize);
+            }
         }
 
         zStats->stringsShortGCHeap += shortStringThingSize;
         zStats->stringsNormalGCHeap += normalStringThingSize;
         zStats->stringsNormalMallocHeap += strCharsSize;
 
         break;
       }
@@ -439,17 +449,17 @@ JS::CollectRuntimeStats(JSRuntime *rt, R
     IterateChunks(rt, &rtStats->gcHeapDecommittedArenas,
                   DecommittedArenasChunkCallback);
 
     // Take the per-compartment measurements.
     StatsClosure closure(rtStats, opv);
     if (!closure.init())
         return false;
     IterateZonesCompartmentsArenasCells(rt, &closure, StatsZoneCallback, StatsCompartmentCallback,
-                                        StatsArenaCallback, StatsCellCallback);
+                                        StatsArenaCallback, StatsCellCallback<FineGrained>);
 
     // Take the "explicit/js/runtime/" measurements.
     rt->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &rtStats->runtime);
 
     for (size_t i = 0; i < rtStats->zoneStatsVector.length(); i++) {
         ZoneStats &zStats = rtStats->zoneStatsVector[i];
 
         rtStats->zTotals.add(zStats);
@@ -559,17 +569,17 @@ AddSizeOfTab(JSRuntime *rt, JSObject *ob
         return false;
 
     // Take the per-compartment measurements.
     StatsClosure closure(&rtStats, opv);
     if (!closure.init())
         return false;
     IterateZoneCompartmentsArenasCells(rt, zone, &closure, StatsZoneCallback,
                                        StatsCompartmentCallback, StatsArenaCallback,
-                                       StatsCellCallback);
+                                       StatsCellCallback<CoarseGrained>);
 
     JS_ASSERT(rtStats.zoneStatsVector.length() == 1);
     rtStats.zTotals.add(rtStats.zoneStatsVector[0]);
 
     for (size_t i = 0; i < rtStats.compartmentStatsVector.length(); i++) {
         CompartmentStats &cStats = rtStats.compartmentStatsVector[i];
         rtStats.cTotals.add(cStats);
     }