author | Michal Novotny <michal.novotny@gmail.com> |
Wed, 24 Nov 2010 16:42:30 +0100 | |
changeset 58167 | 59144b59cd11dc99985b669e348a55a68be4fee8 |
parent 58166 | 2c8654b57cca8c10e9afef8dd2ac5fd05f38dd3f |
child 58168 | 6852e7c47edf9f467aa133bd3851d6792b7b5d1d |
push id | 17179 |
push user | mlamouri@mozilla.com |
push date | Wed, 24 Nov 2010 15:43:48 +0000 |
treeherder | mozilla-central@59144b59cd11 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jduell, blocking-bN |
bugs | 592422 |
milestone | 2.0b8pre |
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
|
--- a/netwerk/cache/nsDiskCacheMap.h +++ b/netwerk/cache/nsDiskCacheMap.h @@ -89,16 +89,19 @@ struct nsDiskCacheEntry; // Min and max values for the number of records in the DiskCachemap #define kMinRecordCount 512 #define kSeparateFile 0 // #define must always be <= 65535KB, or overflow. See bug 443067 Comment 8 #define kMaxDataFileSize 5 * 1024 * 1024 // 5 MB (in bytes) #define kBuckets (1 << 5) // must be a power of 2! +// preallocate up to 1MB of separate cache file +#define kPreallocateLimit 1 * 1024 * 1024 + class nsDiskCacheRecord { private: PRUint32 mHashNumber; PRUint32 mEvictionRank; PRUint32 mDataLocation; PRUint32 mMetaLocation;
--- a/netwerk/cache/nsDiskCacheStreams.cpp +++ b/netwerk/cache/nsDiskCacheStreams.cpp @@ -38,16 +38,17 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsDiskCache.h" #include "nsDiskCacheDevice.h" #include "nsDiskCacheStreams.h" #include "nsCacheService.h" +#include "mozilla/FileUtils.h" // Assumptions: // - cache descriptors live for life of streams // - streams will only be used by FileTransport, // they will not be directly accessible to clients // - overlapped I/O is NOT supported @@ -724,16 +725,20 @@ nsDiskCacheStreamIO::FlushBufferToFile() rv = cacheMap->DeleteStorage(record, nsDiskCache::kData); if (NS_FAILED(rv)) return rv; } record->SetDataFileGeneration(mBinding->mGeneration); // allocate file rv = OpenCacheFile(PR_RDWR | PR_CREATE_FILE, &mFD); if (NS_FAILED(rv)) return rv; + + PRInt64 dataSize = mBinding->mCacheEntry->PredictedDataSize(); + if (dataSize != -1) + mozilla::fallocate(mFD, PR_MIN(dataSize, kPreallocateLimit)); } // write buffer PRInt32 bytesWritten = PR_Write(mFD, mBuffer, mBufEnd); if (PRUint32(bytesWritten) != mBufEnd) { NS_WARNING("failed to flush all data"); return NS_ERROR_UNEXPECTED; // NS_ErrorAccordingToNSPR() }
--- a/xpcom/glue/FileUtils.cpp +++ b/xpcom/glue/FileUtils.cpp @@ -42,66 +42,83 @@ #include <sys/stat.h> #elif defined(XP_WIN) #include <windows.h> #endif #include "nscore.h" #include "private/pprio.h" #include "mozilla/FileUtils.h" +#include "mozilla/FunctionTimer.h" bool mozilla::fallocate(PRFileDesc *aFD, PRInt64 aLength) { + NS_TIME_FUNCTION; #if defined(HAVE_POSIX_FALLOCATE) return posix_fallocate(PR_FileDesc2NativeHandle(aFD), 0, aLength) == 0; #elif defined(XP_WIN) - return PR_Seek64(aFD, aLength, PR_SEEK_SET) == aLength - && 0 != SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle(aFD)); + PROffset64 oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); + if (oldpos == -1) + return false; + + if (PR_Seek64(aFD, aLength, PR_SEEK_SET) != aLength) + return false; + + bool retval = (0 != SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle(aFD))); + + PR_Seek64(aFD, oldpos, PR_SEEK_SET); + return retval; #elif defined(XP_MACOSX) int fd = PR_FileDesc2NativeHandle(aFD); fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, aLength}; // Try to get a continous chunk of disk space int ret = fcntl(fd, F_PREALLOCATE, &store); - if(-1 == ret){ + if (-1 == ret) { // OK, perhaps we are too fragmented, allocate non-continuous store.fst_flags = F_ALLOCATEALL; ret = fcntl(fd, F_PREALLOCATE, &store); if (-1 == ret) return false; } return 0 == ftruncate(fd, aLength); #elif defined(XP_UNIX) // The following is copied from fcntlSizeHint in sqlite /* If the OS does not have posix_fallocate(), fake it. First use ** ftruncate() to set the file size, then write a single byte to ** the last byte in each block within the extended region. This ** is the same technique used by glibc to implement posix_fallocate() ** on systems that do not have a real fallocate() system call. */ + PROffset64 oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); + if (oldpos == -1) + return false; + struct stat buf; int fd = PR_FileDesc2NativeHandle(aFD); if (fstat(fd, &buf)) return false; if (buf.st_size >= aLength) return false; const int nBlk = buf.st_blksize; if (!nBlk) return false; if (ftruncate(fd, aLength)) return false; - + int nWrite; // Return value from write() PRInt64 iWrite = ((buf.st_size + 2 * nBlk - 1) / nBlk) * nBlk - 1; // Next offset to write to do { nWrite = 0; if (PR_Seek64(aFD, iWrite, PR_SEEK_SET) == iWrite) nWrite = PR_Write(aFD, "", 1); iWrite += nBlk; } while (nWrite == 1 && iWrite < aLength); + + PR_Seek64(aFD, oldpos, PR_SEEK_SET); return nWrite == 1; #endif return false; }