Bug 1180715 (1/4) - Track image LoadTime to compare with file mtime. review=seth
authorOliver Henshaw <oliver.henshaw@gmail.com>
Tue, 20 Oct 2015 10:45:25 +0530
changeset 301872 38558bb6671b53b51716c9a8d897b9eb1f3668a8
parent 301871 4e79bfe043c8419874fff97657178408eb51ea63
child 301873 7b4f0495cf6d5f40298755b6d8d15434f449fa0c
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1180715
milestone44.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 1180715 (1/4) - Track image LoadTime to compare with file mtime. review=seth mTouchedTime is not appropriate for this as it is updated when an image load re-uses the same imgRequest, especially as it has one second granularity. A timestamp that is updated every time the backing file is re-read should work better. A millisecond granularity timestamp would be preferable, and would be achievable on most or all supported platforms. But some older filesystems have timestamp granularity of a second or worse, notably ext3 and FAT32 (and even ext4 filesytems created with inode_size < 256 bytes, e.g. with 'mke2fs -t small' - see https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps for details.)
image/imgLoader.cpp
image/imgLoader.h
image/imgRequest.cpp
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -857,16 +857,17 @@ SecondsFromPRTime(PRTime prTime)
 }
 
 imgCacheEntry::imgCacheEntry(imgLoader* loader, imgRequest* request,
                              bool forcePrincipalCheck)
  : mLoader(loader),
    mRequest(request),
    mDataSize(0),
    mTouchedTime(SecondsFromPRTime(PR_Now())),
+   mLoadTime(SecondsFromPRTime(PR_Now())),
    mExpiryTime(0),
    mMustValidate(false),
    // We start off as evicted so we don't try to update the cache. PutIntoCache
    // will set this to false.
    mEvicted(true),
    mHasNoProxies(true),
    mForcePrincipalCheck(forcePrincipalCheck)
 { }
@@ -893,16 +894,21 @@ imgCacheEntry::UpdateCache(int32_t diff 
 {
   // Don't update the cache if we've been removed from it or it doesn't care
   // about our size or usage.
   if (!Evicted() && HasNoProxies()) {
     mLoader->CacheEntriesChanged(mRequest->IsChrome(), diff);
   }
 }
 
+void imgCacheEntry::UpdateLoadTime()
+{
+  mLoadTime = SecondsFromPRTime(PR_Now());
+}
+
 void
 imgCacheEntry::SetHasNoProxies(bool hasNoProxies)
 {
   if (MOZ_LOG_TEST(GetImgLog(), LogLevel::Debug)) {
     if (hasNoProxies) {
       LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies true",
                           "uri", mRequest->CacheKey().Spec());
     } else {
@@ -1705,17 +1711,17 @@ imgLoader::ValidateEntry(imgCacheEntry* 
     hasExpired = false;
   }
 
   nsresult rv;
 
   // Special treatment for file URLs - aEntry has expired if file has changed
   nsCOMPtr<nsIFileURL> fileUrl(do_QueryInterface(aURI));
   if (fileUrl) {
-    uint32_t lastModTime = aEntry->GetTouchedTime();
+    uint32_t lastModTime = aEntry->GetLoadTime();
 
     nsCOMPtr<nsIFile> theFile;
     rv = fileUrl->GetFile(getter_AddRefs(theFile));
     if (NS_SUCCEEDED(rv)) {
       PRTime fileLastMod;
       rv = theFile->GetLastModifiedTime(&fileLastMod);
       if (NS_SUCCEEDED(rv)) {
         // nsIFile uses millisec, NSPR usec
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -86,16 +86,23 @@ public:
     return mTouchedTime;
   }
   void SetTouchedTime(int32_t time)
   {
     mTouchedTime = time;
     Touch(/* updateTime = */ false);
   }
 
+  uint32_t GetLoadTime() const
+  {
+    return mLoadTime;
+  }
+
+  void UpdateLoadTime();
+
   int32_t GetExpiryTime() const
   {
     return mExpiryTime;
   }
   void SetExpiryTime(int32_t aExpiryTime)
   {
     mExpiryTime = aExpiryTime;
     Touch();
@@ -159,16 +166,17 @@ private: // methods
 private: // data
   nsAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 
   imgLoader* mLoader;
   RefPtr<imgRequest> mRequest;
   uint32_t mDataSize;
   int32_t mTouchedTime;
+  uint32_t mLoadTime;
   int32_t mExpiryTime;
   nsExpirationState mExpirationState;
   bool mMustValidate : 1;
   bool mEvicted : 1;
   bool mHasNoProxies : 1;
   bool mForcePrincipalCheck : 1;
 };
 
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -154,16 +154,17 @@ imgRequest::Init(nsIURI *aURI,
   mChannel->GetNotificationCallbacks(getter_AddRefs(mPrevChannelSink));
 
   NS_ASSERTION(mPrevChannelSink != this,
                "Initializing with a channel that already calls back to us!");
 
   mChannel->SetNotificationCallbacks(this);
 
   mCacheEntry = aCacheEntry;
+  mCacheEntry->UpdateLoadTime();
 
   SetLoadId(aCX);
 
   // Grab the inner window ID of the loading document, if possible.
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
   if (doc) {
     mInnerWindowId = doc->InnerWindowID();
   }