Bug 476299 - Decay frecency values to estimate recalculating frecencies. r=dietrich
authorEdward Lee <edilee@mozilla.com>
Sat, 14 Mar 2009 01:08:51 -0500
changeset 26145 d3956139b61809d32ef243b4f4272e764821db21
parent 26144 e29b5ed8711ac527cca9b76cd1f61bf4957d5b85
child 26146 a3dc9e28deee0ad6de2f31063bf9764c1e7e23af
push id5926
push useredward.lee@engineering.uiuc.edu
push dateSat, 14 Mar 2009 06:09:16 +0000
treeherdermozilla-central@d3956139b618 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdietrich
bugs476299, 482069
milestone1.9.2a1pre
Bug 476299 - Decay frecency values to estimate recalculating frecencies. r=dietrich Bug 482069 - Awesome bar adaptiveness totally sucks
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/src/nsNavHistoryExpire.cpp
toolkit/components/places/tests/unit/test_adaptive.js
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -79,21 +79,22 @@
 #include "nsEscape.h"
 #include "nsIVariant.h"
 #include "nsVariant.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIIDNService.h"
 #include "nsIClassInfoImpl.h"
 #include "nsThreadUtils.h"
 
+#include "mozIStorageConnection.h"
+#include "mozIStorageFunction.h"
+#include "mozIStoragePendingStatement.h"
 #include "mozIStorageService.h"
-#include "mozIStorageConnection.h"
+#include "mozIStorageStatement.h"
 #include "mozIStorageValueArray.h"
-#include "mozIStorageStatement.h"
-#include "mozIStorageFunction.h"
 #include "mozStorageCID.h"
 #include "mozStorageHelper.h"
 #include "nsPlacesTriggers.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIIdleService.h"
 #include "nsILivemarkService.h"
 
 #include "nsMathUtils.h" // for NS_ceilf()
@@ -5426,16 +5427,59 @@ nsNavHistory::Observe(nsISupports *aSubj
     if (oldDaysMin != mExpireDaysMin || oldDaysMax != mExpireDaysMax ||
         oldVisits != mExpireSites)
       mExpire.OnExpirationChanged();
   }
   else if (strcmp(aTopic, gIdleDaily) == 0) {
     // Recalculate some frecency values (zero time means don't recalculate)
     if (mFrecencyUpdateIdleTime)
       (void)RecalculateFrecencies(mNumCalculateFrecencyOnIdle, PR_TRUE);
+
+    if (mDBConn) {
+      // Globally decay places frecency rankings to estimate reduced frecency
+      // values of pages that haven't been visited for a while, i.e., they do
+      // not get an updated frecency. We directly modify moz_places to avoid
+      // bringing the whole database into places_temp through places_view. A
+      // scaling factor of .975 results in .5 the original value after 28 days.
+      nsCOMPtr<mozIStorageStatement> decayFrecency;
+      nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+        "UPDATE moz_places SET frecency = ROUND(frecency * .975) "
+        "WHERE frecency > 0"),
+        getter_AddRefs(decayFrecency));
+      NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to create decayFrecency");
+
+      // Decay potentially unused adaptive entries (e.g. those that are at 1)
+      // to allow better chances for new entries that will start at 1
+      nsCOMPtr<mozIStorageStatement> decayAdaptive;
+      rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+        "UPDATE moz_inputhistory SET use_count = use_count * .975"),
+        getter_AddRefs(decayAdaptive));
+      NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to create decayAdaptive");
+
+      // Delete any adaptive entries that won't help in ordering anymore
+      nsCOMPtr<mozIStorageStatement> deleteAdaptive;
+      rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+        "DELETE FROM moz_inputhistory WHERE use_count < .01"),
+        getter_AddRefs(deleteAdaptive));
+      NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to create deleteAdaptive");
+
+      // Run these statements asynchronously if they were created successfully
+      if (decayFrecency && decayAdaptive && deleteAdaptive) {
+        nsCOMPtr<mozIStoragePendingStatement> ps;
+        mozIStorageStatement *stmts[] = {
+          decayFrecency,
+          decayAdaptive,
+          deleteAdaptive
+        };
+
+        rv = mDBConn->ExecuteAsync(stmts, NS_ARRAY_LENGTH(stmts), nsnull,
+                                    getter_AddRefs(ps));
+        NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to exec async idle stmts");
+      }
+    }
   }
   else if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
     if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
       mInPrivateBrowsing = PR_TRUE;
     } else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
       mInPrivateBrowsing = PR_FALSE;
     }
   }
--- a/toolkit/components/places/src/nsNavHistoryExpire.cpp
+++ b/toolkit/components/places/src/nsNavHistoryExpire.cpp
@@ -1017,39 +1017,32 @@ nsNavHistoryExpire::ExpireAnnotationsPar
       ")"));
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 
 // nsNavHistoryExpire::ExpireInputHistoryParanoid
 //
-//    Deletes dangling input history, decay potentially unused entries
+//    Deletes dangling input history
 
 nsresult
 nsNavHistoryExpire::ExpireInputHistoryParanoid(mozIStorageConnection* aConnection)
 {
   // Delete dangling input history that have no associated pages
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
       "DELETE FROM moz_inputhistory WHERE place_id IN ( "
         "SELECT place_id FROM moz_inputhistory "
         "LEFT JOIN moz_places h ON h.id = place_id "
         "LEFT JOIN moz_places_temp h_t ON h_t.id = place_id "
         "WHERE h.id IS NULL "
           "AND h_t.id IS NULL "
       ")"));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Decay potentially unused entries (e.g. those that are at 1) to allow
-  // better chances for new entries that will start at 1
-  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-      "UPDATE moz_inputhistory "
-      "SET use_count = use_count * .9"));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   return NS_OK;
 }
 
 
 // nsNavHistoryExpire::ExpireForDegenerateRuns
 //
 //    This checks for potential degenerate runs. For example, a tinderbox
 //    loads many web pages quickly and we'll never have a chance to expire.
--- a/toolkit/components/places/tests/unit/test_adaptive.js
+++ b/toolkit/components/places/tests/unit/test_adaptive.js
@@ -172,16 +172,25 @@ function setCountRank(aURI, aCount, aRan
   };
 
   // Bump up the instrumentation feedback
   for (let i = 0; i < aRank; i++) {
     obs.notifyObservers(thing, "autocomplete-will-enter-text", null);
   }
 }
 
+/**
+ * Decay the adaptive entries by sending the daily idle topic
+ */
+function doAdaptiveDecay()
+{
+  for (let i = 0; i < 10; i++)
+    obs.notifyObservers(null, "idle-daily", null);
+}
+
 let uri1 = uri("http://site.tld/1");
 let uri2 = uri("http://site.tld/2");
 
 // d1 is some date for the page visit
 let d1 = new Date(Date.now() - 1000 * 60 * 60) * 1000;
 // c1 is larger (should show up higher) than c2
 let c1 = 10;
 let c2 = 1;
@@ -306,17 +315,37 @@ let tests = [
   function() {
     prepTest("9 same count, diff rank, same term; both partial search");
     observer.uriA = uri2;
     observer.uriB = uri1;
     observer.search = s1;
     observer.runCount = c1 + c2;
     setCountRank(uri1, c1, c2, s2);
     setCountRank(uri2, c1, c1, s2);
-  }
+  },
+  function() {
+    prepTest("10 same count, same rank, same term, decay first; exact match");
+    observer.uriA = uri2;
+    observer.uriB = uri1;
+    observer.search = s1;
+    observer.runCount = c1 + c1;
+    setCountRank(uri1, c1, c1, s1);
+    doAdaptiveDecay();
+    setCountRank(uri2, c1, c1, s1);
+  },
+  function() {
+    prepTest("11 same count, same rank, same term, decay second; exact match");
+    observer.uriA = uri1;
+    observer.uriB = uri2;
+    observer.search = s1;
+    observer.runCount = c1 + c1;
+    setCountRank(uri2, c1, c1, s1);
+    doAdaptiveDecay();
+    setCountRank(uri1, c1, c1, s1);
+  },
 ];
 
 /**
  * Test adapative autocomplete
  */
 function run_test() {
   do_test_pending();
   (tests.shift())();