Bug 810151: readahead for ordered jar files r=taras
authorAaron Klotz <aklotz@mozilla.com>
Thu, 21 Mar 2013 10:28:13 +0100
changeset 125723 f8e71f41c30f
parent 125722 4a553cbe3c31
child 125724 b09f11bca869
push id25082
push useraklotz@mozilla.com
push dateThu, 21 Mar 2013 09:28:58 +0000
treeherdermozilla-inbound@f8e71f41c30f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstaras
bugs810151
milestone22.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 810151: readahead for ordered jar files r=taras
modules/libjar/nsZipArchive.cpp
modules/libjar/nsZipArchive.h
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -25,16 +25,17 @@
 #include <windows.h>
 #endif
 
 // For placement new used for arena allocations of zip file list
 #include NEW_H
 #define ZIP_ARENABLOCKSIZE (1*1024)
 
 #ifdef XP_UNIX
+    #include <sys/mman.h>
     #include <sys/types.h>
     #include <sys/stat.h>
     #include <limits.h>
     #include <unistd.h>
 #elif defined(XP_WIN) || defined(XP_OS2)
     #include <io.h>
 #endif
 
@@ -160,20 +161,24 @@ nsZipHandle::nsZipHandle()
   , mRefCnt(0)
 {
   MOZ_COUNT_CTOR(nsZipHandle);
 }
 
 NS_IMPL_THREADSAFE_ADDREF(nsZipHandle)
 NS_IMPL_THREADSAFE_RELEASE(nsZipHandle)
 
-nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret)
+nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret, PRFileDesc **aFd)
 {
   mozilla::AutoFDClose fd;
-  nsresult rv = file->OpenNSPRFileDesc(PR_RDONLY, 0000, &fd.rwget());
+  int32_t flags = PR_RDONLY;
+#if defined(XP_WIN)
+  flags |= nsIFile::OS_READAHEAD;
+#endif
+  nsresult rv = file->OpenNSPRFileDesc(flags, 0000, &fd.rwget());
   if (NS_FAILED(rv))
     return rv;
 
   int64_t size = PR_Available64(fd);
   if (size >= INT32_MAX)
     return NS_ERROR_FILE_TOO_BIG;
 
   PRFileMap *map = PR_CreateFileMap(fd, size, PR_PROT_READONLY);
@@ -189,16 +194,21 @@ nsresult nsZipHandle::Init(nsIFile *file
 
   nsRefPtr<nsZipHandle> handle = new nsZipHandle();
   if (!handle) {
     PR_MemUnmap(buf, (uint32_t) size);
     PR_CloseFileMap(map);
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
+#if defined(XP_WIN)
+  if (aFd) {
+    *aFd = fd.forget();
+  }
+#endif
   handle->mMap = map;
   handle->mFile.Init(file);
   handle->mLen = (uint32_t) size;
   handle->mFileData = buf;
   *ret = handle.forget().get();
   return NS_OK;
 }
 
@@ -243,40 +253,49 @@ nsZipHandle::~nsZipHandle()
 
 //***********************************************************
 //      nsZipArchive  --  public methods
 //***********************************************************
 
 //---------------------------------------------
 //  nsZipArchive::OpenArchive
 //---------------------------------------------
-nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle)
+nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd)
 {
   mFd = aZipHandle;
 
   // Initialize our arena
   PL_INIT_ARENA_POOL(&mArena, "ZipArena", ZIP_ARENABLOCKSIZE);
 
   //-- get table of contents for archive
-  nsresult rv = BuildFileList();
+  nsresult rv = BuildFileList(aFd);
   if (NS_SUCCEEDED(rv)) {
     if (aZipHandle->mFile)
       aZipHandle->mFile.GetURIString(mURI);
   }
   return rv;
 }
 
 nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
 {
   nsRefPtr<nsZipHandle> handle;
+#if defined(XP_WIN)
+  mozilla::AutoFDClose fd;
+  nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle), &fd.rwget());
+#else
   nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle));
+#endif
   if (NS_FAILED(rv))
     return rv;
 
+#if defined(XP_WIN)
+  return OpenArchive(handle, fd.get());
+#else
   return OpenArchive(handle);
+#endif
 }
 
 //---------------------------------------------
 //  nsZipArchive::Test
 //---------------------------------------------
 nsresult nsZipArchive::Test(const char *aEntryName)
 {
   nsZipItem* currItem;
@@ -554,26 +573,37 @@ nsZipItem* nsZipArchive::CreateZipItem()
   void *mem;
   PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsZipItem));
   return (nsZipItem*)mem;
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildFileList
 //---------------------------------------------
-nsresult nsZipArchive::BuildFileList()
+nsresult nsZipArchive::BuildFileList(PRFileDesc *aFd)
 {
   // Get archive size using end pos
   const uint8_t* buf;
   const uint8_t* startp = mFd->mFileData;
   const uint8_t* endp = startp + mFd->mLen;
 MOZ_WIN_MEM_TRY_BEGIN
   uint32_t centralOffset = 4;
   if (mFd->mLen > ZIPCENTRAL_SIZE && xtolong(startp + centralOffset) == CENTRALSIG) {
     // Success means optimized jar layout from bug 559961 is in effect
+    uint32_t readaheadLength = xtolong(startp);
+    if (readaheadLength) {
+#if defined(XP_UNIX)
+      madvise(const_cast<uint8_t*>(startp), readaheadLength, MADV_WILLNEED);
+#elif defined(XP_WIN)
+      if (aFd) {
+        HANDLE hFile = (HANDLE) PR_FileDesc2NativeHandle(aFd);
+        mozilla::ReadAhead(hFile, 0, readaheadLength);
+      }
+#endif
+    }
   } else {
     for (buf = endp - ZIPEND_SIZE; buf > startp; buf--)
       {
         if (xtolong(buf) == ENDSIG) {
           centralOffset = xtolong(((ZipEnd *)buf)->offset_central_dir);
           break;
         }
       }
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -108,19 +108,20 @@ public:
   /** 
    * OpenArchive 
    * 
    * It's an error to call this more than once on the same nsZipArchive
    * object. If we were allowed to use exceptions this would have been 
    * part of the constructor 
    *
    * @param   aZipHandle  The nsZipHandle used to access the zip
+   * @param   aFd         Optional PRFileDesc for Windows readahead optimization
    * @return  status code
    */
-  nsresult OpenArchive(nsZipHandle *aZipHandle);
+  nsresult OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd = nullptr);
 
   /** 
    * OpenArchive 
    * 
    * Convenience function that generates nsZipHandle
    *
    * @param   aFile  The file used to access the zip
    * @return  status code
@@ -218,17 +219,17 @@ private:
   nsRefPtr<nsZipHandle> mFd;
 
   // file URI, for logging
   nsCString mURI;
 
 private:
   //--- private methods ---
   nsZipItem*        CreateZipItem();
-  nsresult          BuildFileList();
+  nsresult          BuildFileList(PRFileDesc *aFd = nullptr);
   nsresult          BuildSynthetics();
 
   nsZipArchive& operator=(const nsZipArchive& rhs) MOZ_DELETE;
   nsZipArchive(const nsZipArchive& rhs) MOZ_DELETE;
 };
 
 /** 
  * nsZipFind 
@@ -369,17 +370,18 @@ public:
     return ret;
   }
 };
 
 class nsZipHandle {
 friend class nsZipArchive;
 friend class mozilla::FileLocation;
 public:
-  static nsresult Init(nsIFile *file, nsZipHandle **ret);
+  static nsresult Init(nsIFile *file, nsZipHandle **ret,
+                       PRFileDesc **aFd = nullptr);
   static nsresult Init(nsZipArchive *zip, const char *entry,
                        nsZipHandle **ret);
 
   NS_METHOD_(nsrefcnt) AddRef(void);
   NS_METHOD_(nsrefcnt) Release(void);
 
   int64_t SizeOfMapping();