Significantly speed up insertion into QJsonObject/Array
authorLars Knoll <lars.knoll@nokia.com>
Tue, 20 Mar 2012 19:45:27 +0000 (20:45 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 22 Mar 2012 17:59:45 +0000 (18:59 +0100)
The code was only allocating memory for the next insertion
leading to a reallocation of the whole data for every
single insertion.

The code now reserves some space and uses a decent growth
strategy to avoid repeated reallocs.

Change-Id: I48b0feab71ba8ca73e7037f8460080f198b2f009
Reviewed-by: Jamey Hicks <jamey.hicks@nokia.com>
src/corelib/json/qjson.cpp
src/corelib/json/qjson_p.h
tests/benchmarks/corelib/json/tst_bench_qtbinaryjson.cpp

index 4f7372a..26f26b2 100644 (file)
@@ -241,14 +241,6 @@ bool Entry::operator ==(const QString &key) const
         return (shallowKey() == key);
 }
 
-bool Entry::operator >=(const QString &key) const
-{
-    if (value.latinKey)
-        return (shallowLatin1Key() >= key);
-    else
-        return (shallowKey() >= key);
-}
-
 bool Entry::operator ==(const Entry &other) const
 {
     if (value.latinKey) {
index 0742ced..f8f41c2 100644 (file)
@@ -620,15 +620,24 @@ public:
 
     bool operator ==(const QString &key) const;
     inline bool operator !=(const QString &key) const { return !operator ==(key); }
-    bool operator >=(const QString &key) const;
+    inline bool operator >=(const QString &key) const;
 
     bool operator ==(const Entry &other) const;
     bool operator >=(const Entry &other) const;
 };
 
+inline bool Entry::operator >=(const QString &key) const
+{
+    if (value.latinKey)
+        return (shallowLatin1Key() >= key);
+    else
+        return (shallowKey() >= key);
+}
+
 inline bool operator <(const QString &key, const Entry &e)
 { return e >= key; }
 
+
 class Header {
 public:
     qle_uint tag; // 'qbjs'
@@ -735,7 +744,15 @@ public:
 
     Data *clone(Base *b, int reserve = 0)
     {
-        int size = sizeof(Header) + b->size + reserve;
+        int size = sizeof(Header) + b->size;
+        if (ref.load() == 1 && alloc >= size + reserve)
+            return this;
+
+        if (reserve) {
+            if (reserve < 128)
+                reserve = 128;
+            size = qMax(size + reserve, size *2);
+        }
         char *raw = (char *)malloc(size);
         Q_CHECK_PTR(raw);
         memcpy(raw + sizeof(Header), b, b->size);
index e4e10ba..c6956b4 100644 (file)
@@ -58,8 +58,12 @@ private Q_SLOTS:
     void parseNumbers();
     void parseJson();
     void parseJsonToVariant();
+
     void toByteArray();
     void fromByteArray();
+
+    void jsonObjectInsert();
+    void variantMapInsert();
 };
 
 BenchmarkQtBinaryJson::BenchmarkQtBinaryJson(QObject *parent) : QObject(parent)
@@ -159,6 +163,30 @@ void BenchmarkQtBinaryJson::fromByteArray()
     }
 }
 
+void BenchmarkQtBinaryJson::jsonObjectInsert()
+{
+    QJsonObject object;
+    QString test(QStringLiteral("testString"));
+    QJsonValue value(1.5);
+
+    QBENCHMARK {
+        for (int i = 0; i < 1000; i++)
+            object.insert("testkey_" + i, value);
+    }
+}
+
+void BenchmarkQtBinaryJson::variantMapInsert()
+{
+    QVariantMap object;
+    QString test(QStringLiteral("testString"));
+    QVariant variantValue(1.5);
+
+    QBENCHMARK {
+        for (int i = 0; i < 1000; i++)
+            object.insert("testkey_" + i, variantValue);
+    }
+}
+
 QTEST_MAIN(BenchmarkQtBinaryJson)
 #include "tst_bench_qtbinaryjson.moc"