diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-11-19 12:46:34 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-19 14:39:26 +0100 |
commit | 2602390bdb0c67b6efc7433a00c4981243df8cc5 (patch) | |
tree | 1b0b276850f1e638f4d1cbc728764e775ce70d9b /src/qml/jsruntime/qv4internalclass_p.h | |
parent | 8b8f8382d66966b3916ea54021449240658bac48 (diff) |
Greatly reduce memory consumed by QQmlEngine instances
Due to a inefficiency in our InternalClass implementation,
we were not sharing the string and attribute table between
internal class instances.
This was extremely inefficient with the Qt object, as it created around
1000 internal classes with large string and property tables. With the
patch these tables are now shared.
Reduces memory consumption of a QQmlEngine instance from around 6.5M
to a couple of 100k.
Change-Id: Ib763f31deca0808c000ac2c30aa0b05e806bda40
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4internalclass_p.h')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass_p.h | 98 |
1 files changed, 92 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 659789b344..9586637b32 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -82,7 +82,7 @@ struct PropertyHashData free(entries); } - QBasicAtomicInt refCount; + int refCount; int alloc; int size; int numBits; @@ -97,15 +97,102 @@ inline PropertyHash::PropertyHash() inline PropertyHash::PropertyHash(const PropertyHash &other) { d = other.d; - d->refCount.ref(); + ++d->refCount; } inline PropertyHash::~PropertyHash() { - if (!d->refCount.deref()) + if (!--d->refCount) delete d; } + +template <typename T> +struct SharedInternalClassData { + struct Private { + Private(int alloc) + : refcount(1), + alloc(alloc), + size(0) + { data = new T [alloc]; } + ~Private() { delete [] data; } + + int refcount; + uint alloc; + uint size; + T *data; + }; + Private *d; + + inline SharedInternalClassData() { + d = new Private(8); + } + + inline SharedInternalClassData(const SharedInternalClassData &other) + : d(other.d) + { + ++d->refcount; + } + inline ~SharedInternalClassData() { + if (!--d->refcount) + delete d; + } + + void add(uint pos, T value) { + if (pos < d->size) { + Q_ASSERT(d->refcount > 1); + // need to detach + Private *dd = new Private(pos + 8); + memcpy(dd->data, d->data, pos*sizeof(T)); + dd->size = pos + 1; + dd->data[pos] = value; + if (!--d->refcount) + delete d; + d = dd; + return; + } + Q_ASSERT(pos == d->size); + if (pos == d->alloc) { + T *n = new T[d->alloc * 2]; + memcpy(n, d->data, d->alloc*sizeof(T)); + delete [] d->data; + d->data = n; + d->alloc *= 2; + } + d->data[pos] = value; + ++d->size; + } + + void set(uint pos, T value) { + Q_ASSERT(pos < d->size); + if (d->refcount > 1) { + // need to detach + Private *dd = new Private(d->alloc); + memcpy(dd->data, d->data, d->size*sizeof(T)); + dd->size = d->size; + if (!--d->refcount) + delete d; + d = dd; + } + d->data[pos] = value; + } + + T *constData() const { + return d->data; + } + T at(uint i) const { + Q_ASSERT(i < d->size); + return d->data[i]; + } + T operator[] (uint i) { + Q_ASSERT(i < d->size); + return d->data[i]; + } + +private: + SharedInternalClassData &operator=(const SharedInternalClassData &other); +}; + struct InternalClassTransition { union { @@ -124,9 +211,8 @@ struct InternalClass { ExecutionEngine *engine; Object *prototype; PropertyHash propertyTable; // id to valueIndex - QVector<String *> nameMap; - - QVector<PropertyAttributes> propertyData; + SharedInternalClassData<String *> nameMap; + SharedInternalClassData<PropertyAttributes> propertyData; typedef InternalClassTransition Transition; QHash<Transition, InternalClass *> transitions; // id to next class, positive means add, negative delete |