final fix for bug 112708 - reduce number pref allocations by using a few large buffers to hold all the prefnames

sr=brendan r=bnesse, dp
Also, clean more unnecessary routines..
This commit is contained in:
alecf%netscape.com 2002-01-05 00:09:53 +00:00
Родитель 529d5aabe3
Коммит 480e6bab51
4 изменённых файлов: 105 добавлений и 19 удалений

Просмотреть файл

@ -535,7 +535,7 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, PRUint32 *aCou
ed.parent = getPrefName(aStartingAt);
ed.pref_list = &prefArray;
pref_HashTableEnumerateEntries(pref_enumChild, &ed);
PL_DHashTableEnumerate(&gHashTable, pref_enumChild, &ed);
// now that we've built up the list, run the callback on
// all the matching elements

Просмотреть файл

@ -428,9 +428,9 @@ static nsresult savePrefFile(nsIFile* aFile)
return NS_BASE_STREAM_OSERROR;
stream << PREFS_HEADER_LINE_1 << nsEndl << PREFS_HEADER_LINE_2 << nsEndl << nsEndl;
/* LI_STUFF here we pass in the heSaveProc proc used so that li can do its own thing */
pref_HashTableEnumerateEntries(pref_savePref, valueArray);
// get the lines that we're supposed to be writing to the file
PL_DHashTableEnumerate(&gHashTable, pref_savePref, valueArray);
/* Sort the preferences to make a readable file on disk */
NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char*), pref_CompareStrings, NULL);

Просмотреть файл

@ -82,7 +82,9 @@ clearPrefEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
PR_FREEIF(pref->defaultPref.stringVal);
PR_FREEIF(pref->userPref.stringVal);
}
PL_strfree((char*)pref->key);
// don't need to free this as it's allocated in memory owned by
// the global PrefNameBuffer
pref->key = nsnull;
memset(entry, 0, table->entrySize);
}
@ -176,8 +178,97 @@ static PLDHashTableOps pref_HashTableOps = {
nsnull,
};
class PrefNameBuffer;
/*----------------------------------------------------------------------------------------*/
// making PrefNameBuffer exactly 8k for nice allocation
#define PREFNAME_BUFFER_LEN (8192 - (sizeof(PrefNameBuffer*) + sizeof(char*)))
#define WORD_ALIGN_MASK (PR_ALIGN_OF_WORD - 1)
// sanity checking
#if (PR_ALIGN_OF_WORD & WORD_ALIGN_MASK) != 0
#error "PR_ALIGN_OF_WORD must be a power of 2!"
#endif
class PrefNameBuffer {
public:
PrefNameBuffer(PrefNameBuffer* aNext) : mNext(aNext), mNextFree(0)
{}
static const char *StrDup(const char*);
static void FreeAllBuffers();
private:
char *Alloc(PRInt32 len);
static PrefNameBuffer *gRoot;
// member variables
class PrefNameBuffer* mNext;
PRUint32 mNextFree;
char mBuf[PREFNAME_BUFFER_LEN];
};
PrefNameBuffer *PrefNameBuffer::gRoot = nsnull;
char*
PrefNameBuffer::Alloc(PRInt32 len)
{
NS_ASSERTION(this == gRoot, "Can only allocate on the root!\n");
NS_ASSERTION(len < PREFNAME_BUFFER_LEN, "Can only allocate short strings\n");
// check for space in the current buffer
if ((mNextFree + len) > PREFNAME_BUFFER_LEN) {
// allocate and update the root
gRoot = new PrefNameBuffer(this);
return gRoot->Alloc(len);
}
// ok, we have space.
char *result = &mBuf[mNextFree];
mNextFree += len;
// now align the next free allocation
mNextFree = (mNextFree + WORD_ALIGN_MASK) & ~WORD_ALIGN_MASK;
return result;
}
// equivalent to strdup() - does no error checking,
// we're assuming we're only called with a valid pointer
const char *
PrefNameBuffer::StrDup(const char *str)
{
if (!gRoot) {
gRoot = new PrefNameBuffer(nsnull);
// ack, no memory
if (!gRoot)
return nsnull;
}
// extra byte for null-termination
PRInt32 len = strlen(str) + 1;
char *buf = gRoot->Alloc(len);
memcpy(buf, str, len);
return buf;
}
void
PrefNameBuffer::FreeAllBuffers()
{
PrefNameBuffer *curr = gRoot;
PrefNameBuffer *next;
do {
next = curr->mNext;
delete curr;
} while ((curr = next) != nsnull);
gRoot = nsnull;
}
/*---------------------------------------------------------------------------*/
#define PREF_IS_LOCKED(pref) ((pref)->flags & PREF_LOCKED)
#define PREF_IS_CONFIG(pref) ((pref)->flags & PREF_CONFIG)
@ -261,7 +352,6 @@ PRBool pref_VerifyLockFile(char* buf, long buflen)
}
PRBool PREF_Init(const char *filename)
{
PRBool ok = PR_TRUE, request = PR_FALSE;
@ -385,6 +475,8 @@ void PREF_CleanupPrefs()
gHashTable.ops = nsnull;
}
PrefNameBuffer::FreeAllBuffers();
if (gSavedLine)
free(gSavedLine);
gSavedLine = NULL;
@ -780,7 +872,8 @@ PREF_DeleteBranch(const char *branch_name)
if ((len > 1) && branch_name[len - 1] != '.')
branch_dot += '.';
pref_HashTableEnumerateEntries(pref_DeleteItem, (void*) branch_dot.get());
PL_DHashTableEnumerate(&gHashTable, pref_DeleteItem,
(void*) branch_dot.get());
return PREF_NOERROR;
}
@ -828,7 +921,8 @@ PREF_ClearAllUserPrefs()
if (!gHashTable.ops)
return PREF_NOT_INITIALIZED;
pref_HashTableEnumerateEntries(pref_ClearUserPref, nsnull);
PL_DHashTableEnumerate(&gHashTable, pref_ClearUserPref, nsnull);
return PREF_OK;
}
@ -909,13 +1003,6 @@ static inline PrefHashEntry* pref_HashTableLookup(const void *key)
return result;
}
PRIntn pref_HashTableEnumerateEntries(PLDHashEnumerator f, void *arg)
{
PRIntn result;
result = PL_DHashTableEnumerate(&gHashTable, f, arg);
return result;
}
PrefResult pref_HashPref(const char *key, PrefValue value, PrefType type, PrefAction action)
{
PrefHashEntry* pref;
@ -934,7 +1021,7 @@ PrefResult pref_HashPref(const char *key, PrefValue value, PrefType type, PrefAc
// initialize the pref entry
pref->flags = type;
pref->key = PL_strdup(key);
pref->key = PrefNameBuffer::StrDup(key);
pref->defaultPref.intVal = 0;
pref->userPref.intVal = 0;
@ -1178,7 +1265,7 @@ PREF_CreateChildList(const char* parent_node, char **child_list)
return PREF_OUT_OF_MEMORY;
pcs.childList[0] = '\0';
pref_HashTableEnumerateEntries(pref_addChild, &pcs);
PL_DHashTableEnumerate(&gHashTable, pref_addChild, &pcs);
*child_list = pcs.childList;
PR_Free(pcs.parent);

Просмотреть файл

@ -44,7 +44,6 @@ PLDHashOperator PR_CALLBACK pref_savePref(PLDHashTable*, PLDHashEntryHdr *, PRUi
int PR_CALLBACK pref_CompareStrings(const void *v1, const void *v2, void* unused);
extern JSBool pref_InitInitialObjects(void);
extern PRIntn pref_HashTableEnumerateEntries(PLDHashEnumerator f, void *arg);
#include "nsIFileSpec.h"