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:
cavin%netscape.com 2001-10-26 02:02:58 +00:00
parent d925a84d2e
commit ecc90c94ff
11 changed files with 79 additions and 15 deletions

View File

@ -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];

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
};

View File

@ -283,6 +283,8 @@ virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr);
PLDHashTable *m_cachedHeaders;
PRBool m_bCacheHeaders;
private:
PRUint32 m_cacheSize;
};
class nsMsgRetentionSettings : public nsIMsgRetentionSettings

View File

@ -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

View File

@ -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()