From 3ba0353391ed0295c43abcb82e38a6bdab2df2c9 Mon Sep 17 00:00:00 2001 From: "alecf%netscape.com" Date: Sat, 5 Jan 2002 00:09:53 +0000 Subject: [PATCH] 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.. git-svn-id: svn://10.0.0.236/trunk@111376 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/libpref/src/nsPrefBranch.cpp | 2 +- mozilla/modules/libpref/src/nsPrefService.cpp | 6 +- mozilla/modules/libpref/src/prefapi.cpp | 115 +++++++++++++++--- .../libpref/src/prefapi_private_data.h | 1 - 4 files changed, 105 insertions(+), 19 deletions(-) diff --git a/mozilla/modules/libpref/src/nsPrefBranch.cpp b/mozilla/modules/libpref/src/nsPrefBranch.cpp index 1fea34b00a3..82c8050e08f 100644 --- a/mozilla/modules/libpref/src/nsPrefBranch.cpp +++ b/mozilla/modules/libpref/src/nsPrefBranch.cpp @@ -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 diff --git a/mozilla/modules/libpref/src/nsPrefService.cpp b/mozilla/modules/libpref/src/nsPrefService.cpp index 688f52504d1..eefb019be86 100644 --- a/mozilla/modules/libpref/src/nsPrefService.cpp +++ b/mozilla/modules/libpref/src/nsPrefService.cpp @@ -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); diff --git a/mozilla/modules/libpref/src/prefapi.cpp b/mozilla/modules/libpref/src/prefapi.cpp index f9a78e93701..e1ef7881685 100644 --- a/mozilla/modules/libpref/src/prefapi.cpp +++ b/mozilla/modules/libpref/src/prefapi.cpp @@ -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); diff --git a/mozilla/modules/libpref/src/prefapi_private_data.h b/mozilla/modules/libpref/src/prefapi_private_data.h index d98e59d4ed7..a7a13e1d53b 100644 --- a/mozilla/modules/libpref/src/prefapi_private_data.h +++ b/mozilla/modules/libpref/src/prefapi_private_data.h @@ -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"