mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 02:47:07 +00:00
Bug #74955: When loading folders, preset the msg hdr cache table size to eliminate
the need of allocating and de-allocating tables. Same thing for users of nsUInt32Array and nsUInt8Array. r=bienvenu, sr=sspitzer.
This commit is contained in:
parent
d925a84d2e
commit
ecc90c94ff
@ -39,6 +39,10 @@
|
||||
#include "nsMsgThreadedDBView.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsIMsgThread.h"
|
||||
#include "nsIDBFolderInfo.h"
|
||||
|
||||
#define MSGHDR_CACHE_LOOK_AHEAD_SIZE 25 // Allocate this more to avoid reallocation on new mail.
|
||||
#define MSGHDR_CACHE_MAX_SIZE 8192 // Max msghdr cache entries.
|
||||
|
||||
nsMsgThreadedDBView::nsMsgThreadedDBView()
|
||||
{
|
||||
@ -57,6 +61,30 @@ NS_IMETHODIMP nsMsgThreadedDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeV
|
||||
rv = nsMsgDBView::Open(folder, sortType, sortOrder, viewFlags, pCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Preset msg hdr cache size for performance reason.
|
||||
if (m_db)
|
||||
{
|
||||
PRInt32 totalMessages, unreadMessages;
|
||||
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
|
||||
rv = m_db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (m_viewFlags & nsMsgViewFlagsType::kUnreadOnly)
|
||||
{
|
||||
// Set unread msg size + extra entries to avoid reallocation on new mail.
|
||||
dbFolderInfo->GetNumNewMessages(&unreadMessages);
|
||||
totalMessages = (PRUint32)unreadMessages+MSGHDR_CACHE_LOOK_AHEAD_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbFolderInfo->GetNumMessages(&totalMessages);
|
||||
if (totalMessages > MSGHDR_CACHE_MAX_SIZE)
|
||||
totalMessages = MSGHDR_CACHE_MAX_SIZE; // use max default
|
||||
else
|
||||
totalMessages += MSGHDR_CACHE_LOOK_AHEAD_SIZE;// allocate extra entries to avoid reallocation on new mail.
|
||||
}
|
||||
m_db->SetMsgHdrCacheSize((PRUint32)totalMessages);
|
||||
}
|
||||
|
||||
if (pCount)
|
||||
*pCount = 0;
|
||||
return InitThreadedView(pCount);
|
||||
@ -137,6 +165,10 @@ nsresult nsMsgThreadedDBView::AddKeys(nsMsgKey *pKeys, PRInt32 *pFlags, const ch
|
||||
|
||||
{
|
||||
PRInt32 numAdded = 0;
|
||||
// Allocate enough space first to avoid memory allocation/deallocation.
|
||||
m_keys.AllocateSpace(numKeysToAdd);
|
||||
m_flags.AllocateSpace(numKeysToAdd);
|
||||
m_levels.AllocateSpace(numKeysToAdd);
|
||||
for (PRInt32 i = 0; i < numKeysToAdd; i++)
|
||||
{
|
||||
PRInt32 threadFlag = pFlags[i];
|
||||
|
@ -92,10 +92,10 @@ PRBool nsUInt32Array::SetSize(PRUint32 nSize,
|
||||
}
|
||||
else if (nSize <= m_nMaxSize)
|
||||
{
|
||||
// The new size is within the current maximum size, make sure new
|
||||
// elements are to initialized to zero
|
||||
if (nSize > m_nSize)
|
||||
nsCRT::memset(&m_pData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
// The new size is within the current maximum size, make sure new
|
||||
// elements are to initialized to zero
|
||||
if (nSize > m_nSize)
|
||||
nsCRT::memset(&m_pData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
|
||||
m_nSize = nSize;
|
||||
}
|
||||
|
@ -43,6 +43,12 @@ public:
|
||||
// State/attribute member functions
|
||||
PRUint32 GetSize() const;
|
||||
PRBool SetSize(PRUint32 nNewSize, PRBool AdjustGrowth=PR_FALSE, PRUint32 nGrowBy = 0);
|
||||
PRBool AllocateSpace(PRUint32 nNewSize) {
|
||||
PRUint32 saveSize = m_nSize;
|
||||
nsresult rv = SetSize(nNewSize);
|
||||
m_nSize = saveSize;
|
||||
return rv;
|
||||
};
|
||||
|
||||
// Accessor member functions
|
||||
PRUint32 &ElementAt(PRUint32 nIndex);
|
||||
|
@ -77,14 +77,14 @@ void nsUint8Array::SetSize(PRInt32 nNewSize, PRInt32 nGrowBy)
|
||||
}
|
||||
else if (nNewSize <= m_nMaxSize)
|
||||
{
|
||||
// it fits
|
||||
if (nNewSize > m_nSize)
|
||||
{
|
||||
// initialize the new elements
|
||||
// it fits
|
||||
if (nNewSize > m_nSize)
|
||||
{
|
||||
// initialize the new elements
|
||||
|
||||
nsCRT::memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(PRUint8));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
m_nSize = nNewSize;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
PRInt32 GetSize() const;
|
||||
PRInt32 GetUpperBound() const;
|
||||
void SetSize(PRInt32 nNewSize, PRInt32 nGrowBy = -1);
|
||||
void AllocateSpace(PRUint32 nNewSize) { PRInt32 saveSize = m_nSize; SetSize(nNewSize); m_nSize = saveSize;};
|
||||
|
||||
// Operations
|
||||
// Clean up
|
||||
|
@ -106,9 +106,11 @@ protected:
|
||||
time_t m_folderDate;
|
||||
nsMsgKey m_highWaterMessageKey; // largest news article number or imap uid whose header we've seen
|
||||
|
||||
// m_numVisibleMessages, m_numNewMessages and m_numMessages can never be negative. 0 means 'no msgs'.
|
||||
PRInt32 m_numVisibleMessages; // doesn't include expunged or ignored messages (but does include collapsed).
|
||||
PRInt32 m_numNewMessages;
|
||||
PRInt32 m_numMessages; // includes expunged and ignored messages
|
||||
|
||||
PRInt32 m_flags; // folder specific flags. This holds things like re-use thread pane,
|
||||
// configured for off-line use, use default retrieval, purge article/header options
|
||||
nsMsgKey m_lastMessageLoaded; // set by the FE's to remember the last loaded message
|
||||
|
@ -57,6 +57,8 @@ interface nsIDBFolderInfo : nsISupports {
|
||||
attribute unsigned long FolderDate;
|
||||
void ChangeNumNewMessages(in long delta);
|
||||
void ChangeNumMessages(in long delta);
|
||||
|
||||
// ChangeNumVisibleMessages, NumNewMessages and NumMessages will never return negative numbers. 0 means 'no msgs'.
|
||||
void ChangeNumVisibleMessages(in long delta);
|
||||
attribute long NumNewMessages;
|
||||
attribute long NumMessages;
|
||||
|
@ -264,5 +264,8 @@ interface nsIMsgDatabase : nsIDBChangeAnnouncer {
|
||||
// news can be threaded by default)
|
||||
readonly attribute nsMsgViewFlagsTypeValue defaultViewFlags;
|
||||
readonly attribute nsMsgViewSortTypeValue defaultSortType;
|
||||
|
||||
// for msg hdr hash table allocation. controllable by caller to improve folder loading preformance.
|
||||
attribute unsigned long msgHdrCacheSize;
|
||||
};
|
||||
|
||||
|
@ -283,6 +283,8 @@ virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr);
|
||||
PLDHashTable *m_cachedHeaders;
|
||||
PRBool m_bCacheHeaders;
|
||||
|
||||
private:
|
||||
PRUint32 m_cacheSize;
|
||||
};
|
||||
|
||||
class nsMsgRetentionSettings : public nsIMsgRetentionSettings
|
||||
|
@ -522,6 +522,7 @@ NS_IMETHODIMP nsDBFolderInfo::GetMailboxName(nsString *boxName)
|
||||
NS_IMETHODIMP nsDBFolderInfo::ChangeNumNewMessages(PRInt32 delta)
|
||||
{
|
||||
m_numNewMessages += delta;
|
||||
// m_numNewMessages can never be set to negative.
|
||||
if (m_numNewMessages < 0)
|
||||
{
|
||||
#ifdef DEBUG_bienvenu1
|
||||
@ -535,6 +536,7 @@ NS_IMETHODIMP nsDBFolderInfo::ChangeNumNewMessages(PRInt32 delta)
|
||||
NS_IMETHODIMP nsDBFolderInfo::ChangeNumMessages(PRInt32 delta)
|
||||
{
|
||||
m_numMessages += delta;
|
||||
// m_numMessages can never be set to negative.
|
||||
if (m_numMessages < 0)
|
||||
{
|
||||
#ifdef DEBUG_bienvenu
|
||||
@ -548,6 +550,7 @@ NS_IMETHODIMP nsDBFolderInfo::ChangeNumMessages(PRInt32 delta)
|
||||
NS_IMETHODIMP nsDBFolderInfo::ChangeNumVisibleMessages(PRInt32 delta)
|
||||
{
|
||||
m_numVisibleMessages += delta;
|
||||
// m_numVisibleMessages can never be set to negative.
|
||||
if (m_numVisibleMessages < 0)
|
||||
{
|
||||
#ifdef DEBUG_bienvenu
|
||||
|
@ -95,7 +95,7 @@ static NS_DEFINE_CID(kMsgHeaderParserCID, NS_MSGHEADERPARSER_CID);
|
||||
|
||||
#define MSG_HASH_SIZE 512
|
||||
|
||||
const PRInt32 kMaxHdrsInCache = 512;
|
||||
const PRInt32 kMaxHdrsInCache = 512; // this will be used on discovery, since we don't know total, and after loading (and sorting), on a new header, we'll use this.
|
||||
|
||||
// special keys
|
||||
static const nsMsgKey kAllMsgHdrsTableKey = 1;
|
||||
@ -139,12 +139,12 @@ nsresult nsMsgDatabase::AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key) // do we w
|
||||
if (m_bCacheHeaders)
|
||||
{
|
||||
if (!m_cachedHeaders)
|
||||
m_cachedHeaders = PL_NewDHashTable(&gMsgDBHashTableOps, (void *) nsnull, sizeof(struct MsgHdrHashElement), kMaxHdrsInCache );
|
||||
m_cachedHeaders = PL_NewDHashTable(&gMsgDBHashTableOps, (void *) nsnull, sizeof(struct MsgHdrHashElement), m_cacheSize );
|
||||
if (m_cachedHeaders)
|
||||
{
|
||||
if (key == nsMsgKey_None)
|
||||
hdr->GetMessageKey(&key);
|
||||
if (m_cachedHeaders->entryCount > kMaxHdrsInCache)
|
||||
if (m_cachedHeaders->entryCount > m_cacheSize)
|
||||
ClearHdrCache(PR_TRUE);
|
||||
PLDHashEntryHdr *entry = PL_DHashTableOperate(m_cachedHeaders, (void *) key, PL_DHASH_ADD);
|
||||
if (!entry)
|
||||
@ -170,6 +170,19 @@ nsresult nsMsgDatabase::AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key) // do we w
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::SetMsgHdrCacheSize(PRUint32 aSize)
|
||||
{
|
||||
m_cacheSize = aSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::GetMsgHdrCacheSize(PRUint32 *aSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSize);
|
||||
*aSize = m_cacheSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::ClearCachedHdrs()
|
||||
{
|
||||
return ClearHdrCache(PR_FALSE); // don't re-init, hope db gets closed.
|
||||
@ -187,7 +200,7 @@ nsresult nsMsgDatabase::ClearHdrCache(PRBool reInit)
|
||||
if (reInit)
|
||||
{
|
||||
PL_DHashTableFinish(saveCachedHeaders);
|
||||
PL_DHashTableInit(saveCachedHeaders, &gMsgDBHashTableOps, nsnull, sizeof(struct MsgHdrHashElement), kMaxHdrsInCache);
|
||||
PL_DHashTableInit(saveCachedHeaders, &gMsgDBHashTableOps, nsnull, sizeof(struct MsgHdrHashElement), m_cacheSize);
|
||||
m_cachedHeaders = saveCachedHeaders;
|
||||
|
||||
}
|
||||
@ -672,11 +685,11 @@ nsMsgDatabase::nsMsgDatabase()
|
||||
m_HeaderParser(nsnull),
|
||||
m_headersInUse(nsnull),
|
||||
m_cachedHeaders(nsnull),
|
||||
m_bCacheHeaders(PR_FALSE)
|
||||
m_bCacheHeaders(PR_TRUE),
|
||||
m_cacheSize(kMaxHdrsInCache)
|
||||
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_bCacheHeaders = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMsgDatabase::~nsMsgDatabase()
|
||||
|
Loading…
x
Reference in New Issue
Block a user