Bug 599545 - Investigate remote-prefs serialization performance. r=dwitte, a=blocking-fennec2.0b2+

This commit is contained in:
Mike Kristoffersen 2010-10-19 22:35:08 +02:00
Родитель 80f231dc57
Коммит 3a55459851
12 изменённых файлов: 307 добавлений и 65 удалений

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

@ -383,10 +383,14 @@ ContentChild::AddRemoteAlertObserver(const nsString& aData,
}
bool
ContentChild::RecvPreferenceUpdate(const nsCString& aPref)
ContentChild::RecvPreferenceUpdate(const PrefTuple& aPref)
{
nsCOMPtr<nsIPrefServiceInternal> prefs = do_GetService("@mozilla.org/preferences-service;1");
prefs->ReadPrefBuffer(aPref);
if (!prefs)
return false;
prefs->SetPreference(&aPref);
return true;
}

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

@ -104,8 +104,8 @@ public:
// auto remove when alertfinished is received.
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
virtual bool RecvPreferenceUpdate(const nsCString& aDomain);
virtual bool RecvPreferenceUpdate(const PrefTuple& aPref);
virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);

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

@ -196,10 +196,10 @@ ContentParent::IsAlive()
}
bool
ContentParent::RecvReadPrefs(nsCString* prefs)
ContentParent::RecvReadPrefsArray(nsTArray<PrefTuple> *prefs)
{
EnsurePrefService();
mPrefService->SerializePreferences(*prefs);
mPrefService->MirrorPreferences(prefs);
return true;
}
@ -301,10 +301,14 @@ ContentParent::Observe(nsISupports* aSubject,
if (!strcmp(aTopic, "nsPref:changed")) {
// We know prefs are ASCII here.
NS_LossyConvertUTF16toASCII strData(aData);
nsCString prefBuffer;
nsCOMPtr<nsIPrefServiceInternal> prefs = do_GetService("@mozilla.org/preferences-service;1");
prefs->SerializePreference(strData, prefBuffer);
if (!SendPreferenceUpdate(prefBuffer))
PrefTuple pref;
nsCOMPtr<nsIPrefServiceInternal> prefService =
do_GetService("@mozilla.org/preferences-service;1");
prefService->MirrorPreference(strData, &pref);
if (!SendPreferenceUpdate(pref))
return NS_ERROR_NOT_AVAILABLE;
}
else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {

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

@ -125,7 +125,7 @@ private:
const PRInt64& aContentLength);
virtual bool DeallocPExternalHelperApp(PExternalHelperAppParent* aService);
virtual bool RecvReadPrefs(nsCString* prefs);
virtual bool RecvReadPrefsArray(nsTArray<PrefTuple> *retValue);
void EnsurePrefService();

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

@ -45,8 +45,11 @@ include "mozilla/chrome/RegistryMessageUtils.h";
include "mozilla/net/NeckoMessageUtils.h";
include "nsGeoPositionIPCSerialiser.h";
include "PPrefTuple.h";
using GeoPosition;
using PrefTuple;
using nsTArray<PrefTuple>;
using ChromePackage;
using ResourceMapping;
@ -76,7 +79,7 @@ child:
async NotifyVisited(URI uri);
PreferenceUpdate(nsCString pref);
PreferenceUpdate(PrefTuple pref);
NotifyAlertsObserver(nsCString topic, nsString data);
@ -96,8 +99,8 @@ parent:
async LoadURIExternal(URI uri);
// PrefService messages
sync ReadPrefs() returns (nsCString retValue);
// PrefService message
sync ReadPrefsArray() returns (nsTArray<PrefTuple> retValue);
sync SyncMessage(nsString aMessage, nsString aJSON)
returns (nsString[] retval);

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

@ -57,5 +57,10 @@ XPIDLSRCS = \
nsIRelativeFilePref.idl \
$(NULL)
EXPORTS = \
PPrefTuple.h \
PrefTuple.h
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,106 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla preference service code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mike Kristoffersen <moz@mikek.dk> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef dom_pref_hash_entry_array_IPC_serialiser
#define dom_pref_hash_entry_array_IPC_serialiser
#include "IPC/IPCMessageUtils.h"
#include "nsTArray.h"
#include "pldhash.h"
#include "nsIPrefService.h"
#include "PrefTuple.h"
namespace IPC {
template <>
struct ParamTraits<PrefTuple>
{
typedef PrefTuple paramType;
// Function to serialize a PrefTuple
static void Write(Message *aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.key);
WriteParam(aMsg, (PRUint32)aParam.type);
switch (aParam.type) {
case PrefTuple::PREF_STRING:
WriteParam(aMsg, aParam.stringVal);
break;
case PrefTuple::PREF_INT:
WriteParam(aMsg, aParam.intVal);
break;
case PrefTuple::PREF_BOOL:
WriteParam(aMsg, aParam.boolVal);
break;
}
}
// Function to de-serialize a PrefTuple
static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
{
PRUint32 type;
if (!ReadParam(aMsg, aIter, &(aResult->key)))
return false;
if (!ReadParam(aMsg, aIter, &type))
return false;
switch (type) {
case PrefTuple::PREF_STRING:
aResult->type = PrefTuple::PREF_STRING;
if (!ReadParam(aMsg, aIter, &(aResult->stringVal)))
return false;
break;
case PrefTuple::PREF_INT:
aResult->type = PrefTuple::PREF_INT;
if (!ReadParam(aMsg, aIter, &(aResult->intVal)))
return false;
break;
case PrefTuple::PREF_BOOL:
aResult->type = PrefTuple::PREF_BOOL;
if (!ReadParam(aMsg, aIter, &(aResult->boolVal)))
return false;
break;
}
return true;
}
} ;
}
#endif

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

@ -0,0 +1,62 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla preference service code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mike Kristoffersen <moz@mikek.dk> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef preftuple_included
#define preftuple_included
#include "nsTArray.h"
#include "nsString.h"
struct PrefTuple
{
nsCAutoString key;
// We don't use a union to avoid allocations when using the string component
// NOTE: Only one field will be valid at any given time, as indicated by the type enum
nsCAutoString stringVal;
PRInt32 intVal;
bool boolVal;
enum {
PREF_STRING,
PREF_INT,
PREF_BOOL
} type;
};
#endif

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

@ -40,6 +40,15 @@
#include "nsISupports.idl"
#include "nsIPrefBranch.idl"
%{C++
struct PrefTuple;
template<class E> class nsTArray;
%}
[ptr] native nsPreferencesArrayPtr(nsTArray<PrefTuple>);
[ptr] native nsPreferencePtr(PrefTuple);
[ptr] native nsPreferencePtrConst(const PrefTuple);
interface nsIFile;
interface nsILocalFile;
@ -169,19 +178,19 @@ interface nsIPrefServiceInternal : nsISupports
*/
void readExtensionPrefs(in nsILocalFile aFile);
ACString serializePreferences();
ACString serializePreference(in ACString aPrefName);
void readPrefBuffer(in ACString aBuffer);
[noscript] void mirrorPreferences(in nsPreferencesArrayPtr aArray);
[noscript] void mirrorPreference(in ACString aPrefName, in nsPreferencePtr aPref);
[noscript] void setPreference(in nsPreferencePtrConst aPref);
};
%{C++
#define NS_PREFSERVICE_CID \
{ /* {1cd91b88-1dd2-11b2-92e1-ed22ed298000} */ \
0x1cd91b88, \
0x1dd2, \
0x11b2, \
{ 0x92, 0xe1, 0xed, 0x22, 0xed, 0x29, 0x80, 0x00 } \
0x91ca2441, \
0x050f, \
0x4f7c, \
{ 0x9d, 0xf8, 0x75, 0xb4, 0x0e, 0xa4, 0x01, 0x56 } \
}
#define NS_PREFSERVICE_CONTRACTID "@mozilla.org/preferences-service;1"

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

@ -68,6 +68,7 @@
#include "prefapi.h"
#include "prefread.h"
#include "prefapi_private_data.h"
#include "PrefTuple.h"
#include "nsITimelineService.h"
@ -143,12 +144,15 @@ nsresult nsPrefService::Init()
#ifdef MOZ_IPC
using mozilla::dom::ContentChild;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
nsTArray<PrefTuple> array;
ContentChild::GetSingleton()->SendReadPrefsArray(&array);
ContentChild* cpc = ContentChild::GetSingleton();
nsCAutoString prefs;
cpc->SendReadPrefs(&prefs);
return ReadPrefBuffer(prefs);
// Store the array
nsTArray<PrefTuple>::size_type index = array.Length();
while (index-- > 0) {
pref_SetPrefTuple(array[index], PR_TRUE);
}
return NS_OK;
}
#endif
@ -328,58 +332,31 @@ NS_IMETHODIMP nsPrefService::ReadExtensionPrefs(nsILocalFile *aFile)
return rv;
}
NS_IMETHODIMP nsPrefService::SerializePreferences(nsACString& prefs)
NS_IMETHODIMP nsPrefService::SetPreference(const PrefTuple *aPref)
{
char** valueArray = (char **)PR_Calloc(sizeof(char *), gHashTable.entryCount);
if (!valueArray)
return NS_ERROR_OUT_OF_MEMORY;
pref_saveArgs saveArgs;
saveArgs.prefArray = valueArray;
saveArgs.saveTypes = SAVE_ALL_AND_DEFAULTS;
// get the lines that we're supposed to be writing
PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs);
char** walker = valueArray;
for (PRUint32 valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) {
if (*walker) {
prefs.Append(*walker);
prefs.Append(NS_LINEBREAK);
NS_Free(*walker);
}
}
PR_Free(valueArray);
return NS_OK;
return pref_SetPrefTuple(*aPref, PR_TRUE);
}
NS_IMETHODIMP nsPrefService::SerializePreference(const nsACString& aPrefName, nsACString& aBuffer)
NS_IMETHODIMP nsPrefService::MirrorPreference(const nsACString& aPrefName,
PrefTuple *aPref)
{
PrefHashEntry *pref = pref_HashTableLookup(nsDependentCString(aPrefName).get());
if (!pref)
return NS_ERROR_NOT_AVAILABLE;
char* prefArray = nsnull;
pref_saveArgs saveArgs;
saveArgs.prefArray = &prefArray;
saveArgs.saveTypes = SAVE_ALL_AND_DEFAULTS;
pref_savePref(&gHashTable, pref, 0, &saveArgs);
aBuffer = prefArray;
PR_Free(prefArray);
pref_GetTupleFromEntry(pref, aPref);
return NS_OK;
}
NS_IMETHODIMP nsPrefService::ReadPrefBuffer(const nsACString& aBuffer)
NS_IMETHODIMP nsPrefService::MirrorPreferences(nsTArray<PrefTuple> *aArray)
{
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, NULL);
nsresult rv = PREF_ParseBuf(&ps, nsDependentCString(aBuffer).get(), aBuffer.Length());
PREF_FinalizeParseState(&ps);
return rv;
aArray->SetCapacity(PL_DHASH_TABLE_SIZE(&gHashTable));
PL_DHashTableEnumerate(&gHashTable, pref_MirrorPrefs, aArray);
return NS_OK;
}
NS_IMETHODIMP nsPrefService::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)

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

@ -37,6 +37,7 @@
#include "prefapi.h"
#include "prefapi_private_data.h"
#include "PrefTuple.h"
#include "prefread.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
@ -310,6 +311,24 @@ PREF_SetBoolPref(const char *pref_name, PRBool value, PRBool set_default)
return pref_HashPref(pref_name, pref, PREF_BOOL, set_default);
}
nsresult
pref_SetPrefTuple(const PrefTuple &aPref, PRBool set_default)
{
switch (aPref.type) {
case PrefTuple::PREF_STRING:
return PREF_SetCharPref(aPref.key.get(), aPref.stringVal.get(), set_default);
case PrefTuple::PREF_INT:
return PREF_SetIntPref(aPref.key.get(), aPref.intVal, set_default);
case PrefTuple::PREF_BOOL:
return PREF_SetBoolPref(aPref.key.get(), aPref.boolVal, set_default);
}
NS_NOTREACHED("Unknown type");
return NS_ERROR_INVALID_ARG;
}
PLDHashOperator
pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg)
{
@ -367,6 +386,49 @@ pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg)
return PL_DHASH_NEXT;
}
PLDHashOperator
pref_MirrorPrefs(PLDHashTable *table,
PLDHashEntryHdr *heh,
PRUint32 i,
void *arg)
{
if (heh) {
PrefHashEntry *entry = static_cast<PrefHashEntry *>(heh);
PrefTuple *newEntry =
static_cast<nsTArray<PrefTuple> *>(arg)->AppendElement();
pref_GetTupleFromEntry(entry, newEntry);
}
return PL_DHASH_NEXT;
}
void
pref_GetTupleFromEntry(PrefHashEntry *aHashEntry, PrefTuple *aTuple)
{
aTuple->key = aHashEntry->key;
PrefValue *value = PREF_HAS_USER_VALUE(aHashEntry) ?
&(aHashEntry->userPref) : &(aHashEntry->defaultPref);
switch (aHashEntry->flags & PREF_VALUETYPE_MASK) {
case PREF_STRING:
aTuple->stringVal = value->stringVal;
aTuple->type = PrefTuple::PREF_STRING;
return;
case PREF_INT:
aTuple->intVal = value->intVal;
aTuple->type = PrefTuple::PREF_INT;
return;
case PREF_BOOL:
aTuple->boolVal = !!value->boolVal;
aTuple->type = PrefTuple::PREF_BOOL;
return;
}
}
int
pref_CompareStrings(const void *v1, const void *v2, void *unused)
{

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

@ -40,6 +40,8 @@
extern PLDHashTable gHashTable;
extern PRBool gDirty;
struct PrefTuple;
enum pref_SaveTypes { SAVE_NONSHARED, SAVE_SHARED, SAVE_ALL, SAVE_ALL_AND_DEFAULTS };
// Passed as the arg to pref_savePref
@ -51,5 +53,13 @@ struct pref_saveArgs {
PLDHashOperator
pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg);
PLDHashOperator
pref_MirrorPrefs(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg);
nsresult
pref_SetPrefTuple(const PrefTuple &aPref,PRBool set_default = PR_FALSE);
int pref_CompareStrings(const void *v1, const void *v2, void* unused);
PrefHashEntry* pref_HashTableLookup(const void *key);
void pref_GetTupleFromEntry(PrefHashEntry *aHashEntry, PrefTuple *aTuple);