Avoid excessive GCs after CC (bug 637206, patch/r=smaug/gal).
authorAndreas Gal <gal@mozilla.com>
Mon, 28 Feb 2011 14:44:22 -0800
changeset 63206 92b0df2936fefe5e6a9bc8baff1af52049b5244b
parent 63205 fab60117e622e0dfcdc518b27500a3dbd0d72c1f
child 63207 30d4fd4a62d247d6689979339bb561c1977d0d95
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
bugs637206
milestone2.0b13pre
Avoid excessive GCs after CC (bug 637206, patch/r=smaug/gal).
dom/base/nsJSEnvironment.cpp
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -154,16 +154,17 @@ static bool sGCHasRun;
 // guaranteed to always reflect reality and can't easily as we don't
 // have an easy place to know when a load ends or is interrupted in
 // all cases. This counter also gets reset if we end up GC'ing while
 // we're waiting for a slow page to load. IOW, this count may be 0
 // even when there are pending loads.
 static PRUint32 sPendingLoadCount;
 static PRBool sLoadingInProgress;
 
+static PRUint32 sCCollectedWaitingForGC;
 static PRBool sPostGCEventsToConsole;
 
 nsScriptNameSpaceManager *gNameSpaceManager;
 
 static nsIJSRuntimeService *sRuntimeService;
 JSRuntime *nsJSRuntime::sRuntime;
 
 static const char kJSRuntimeServiceContractID[] =
@@ -3282,29 +3283,31 @@ nsJSContext::CycleCollectNow(nsICycleCol
   NS_TIME_FUNCTION_MIN(1.0);
 
   KillCCTimer();
 
   PRTime start = PR_Now();
 
   PRUint32 suspected = nsCycleCollector_suspectedCount();
   PRUint32 collected = nsCycleCollector_collect(aListener);
-
-  // If we collected cycles, poke the GC since more objects might be unreachable now.
-  if (collected > 0) {
+  sCCollectedWaitingForGC += collected;
+
+  // If we collected a substantial amount of cycles, poke the GC since more objects
+  // might be unreachable now.
+  if (sCCollectedWaitingForGC > 250) {
     PokeGC();
   }
 
   if (sPostGCEventsToConsole) {
     PRTime now = PR_Now();
     NS_NAMED_LITERAL_STRING(kFmt,
-                            "CC timestamp: %lld, collected: %lu, suspected: %lu, duration: %llu ms.");
+                            "CC timestamp: %lld, collected: %lu (%lu waiting for GC), suspected: %lu, duration: %llu ms.");
     nsString msg;
     msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), now,
-                                        collected, suspected,
+                                        collected, sCCollectedWaitingForGC, suspected,
                                         (now - start) / PR_USEC_PER_MSEC));
     nsCOMPtr<nsIConsoleService> cs =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
   }
 }
@@ -3444,28 +3447,31 @@ DOMGCCallback(JSContext *cx, JSGCStatus 
 {
   static PRTime start;
 
   if (sPostGCEventsToConsole && NS_IsMainThread()) {
     if (status == JSGC_BEGIN) {
       start = PR_Now();
     } else if (status == JSGC_END) {
       PRTime now = PR_Now();
-      NS_NAMED_LITERAL_STRING(kFmt, "GC timestamp: %lld, duration: %llu ms.");
+      NS_NAMED_LITERAL_STRING(kFmt, "GC mode: %s, timestamp: %lld, duration: %llu ms.");
       nsString msg;
-      msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), now,
+      msg.Adopt(nsTextFormatter::smprintf(kFmt.get(),
+                cx->runtime->gcTriggerCompartment ? "compartment" : "full",
+                now,
                 (now - start) / PR_USEC_PER_MSEC));
       nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
       if (cs) {
         cs->LogStringMessage(msg.get());
       }
     }
   }
 
   if (status == JSGC_END) {
+    sCCollectedWaitingForGC = 0;
     if (sGCTimer) {
       // If we were waiting for a GC to happen, kill the timer.
       nsJSContext::KillGCTimer();
 
       // If this is a compartment GC, restart it. We still want
       // a full GC to happen. Compartment GCs usually happen as a
       // result of last-ditch or MaybeGC. In both cases its
       // probably a time of heavy activity and we want to delay
@@ -3590,16 +3596,17 @@ nsJSRuntime::ParseVersion(const nsString
 void
 nsJSRuntime::Startup()
 {
   // initialize all our statics, so that we can restart XPCOM
   sGCTimer = sCCTimer = nsnull;
   sGCHasRun = false;
   sPendingLoadCount = 0;
   sLoadingInProgress = PR_FALSE;
+  sCCollectedWaitingForGC = 0;
   sPostGCEventsToConsole = PR_FALSE;
   gNameSpaceManager = nsnull;
   sRuntimeService = nsnull;
   sRuntime = nsnull;
   gOldJSGCCallback = nsnull;
   sIsInitialized = PR_FALSE;
   sDidShutdown = PR_FALSE;
   sContextCount = 0;