Commit 6d379ea1 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

updated bench :

- eliminated allocations in qbytearray test to get best perf
- added xml
parent 3eb94c82
......@@ -229,7 +229,7 @@ class QCborVisitor : public IReader
Q_DISABLE_COPY(QCborVisitor)
public:
QCborVisitor(QCborValue* v) : cbor(v) { Q_ASSERT(v); }
void reset(QCborValue* v) { cbor=v; Q_ASSERT(v); steps.clear(); errors.clear(); }
void reset(QCborValue* v) { cbor=v; Q_ASSERT(v); steps.resize(0); errors.resize(0); }
struct Error { const char* error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error)+' '+path); } };
QVector<Error> errors;
......@@ -306,7 +306,7 @@ protected:
bool _bind ( QUtf8String& u) { QString s; if (_bind(s)) { u = s.toUtf8(); return true; } return false; }
bool _bind ( QString& s) { if (caching) { cacheLevel++; return caching->_bind(s) && cacheOut(); }
skipTag(); if (isString()) {
s.clear();
s.resize(0);
auto r = readString();
while (r.status == QCborStreamReader::Ok) {
s.append(r.data);
......@@ -315,7 +315,7 @@ protected:
if (r.status == QCborStreamReader::Error) {
if (!s.isEmpty()) {
_reportError(qBindIgnoredBytes);
s.clear();
s.resize(0);
}
return false;
}
......@@ -323,7 +323,7 @@ protected:
} else { _reportError(qBindExpectedBytes); return false; } }
bool _bind ( QByteArray& s) { if (caching) { cacheLevel++; return caching->_bind(s) && cacheOut(); }
skipTag(); if (isByteArray()) {
s.clear();
s.resize(0);
auto r = readByteArray();
while (r.status == QCborStreamReader::Ok) {
s.append(r.data);
......@@ -332,7 +332,7 @@ protected:
if (r.status == QCborStreamReader::Error) {
if (!s.isEmpty()) {
_reportError(qBindIgnoredBytes);
s.clear();
s.resize(0);
}
return false;
}
......
......@@ -51,7 +51,7 @@
//! \warning As with QDataStream, QDataWriter and QDataReader must bind compatible C++ data types, and QDataStream ByteOrder, FloatingPointPrecision and Version
//! \remark When not statically known, such information can be transmitted using meta({{"type",...}}) although some IBind implementations may not support it
class QDataWriter : public IWriter // allows runtime flexibility but requires QBind<T> in addition to T::operator<<(QDebug&) and does not warrant QDataStream operators compatibility if QBind<T> ignores qmDataStreamVersion in meta(QMetaData&)
class QDataWriter : public IWriter // allows runtime flexibility but requires QBind<T> in addition to T::operator<<(QDataStream&) and does not warrant QDataStream operators compatibility if QBind<T> ignores qmDataStreamVersion in meta(QMetaData&)
{
Q_DISABLE_COPY(QDataWriter)
public:
......@@ -87,8 +87,6 @@ private:
QString version;
};
template<typename T> struct BindSupport<T ,QDataWriter> : BindNative {}; //!< \remark Use meta() or QVariant to encapsulate Ts that are not statically known (provided qRegisterMetaType<T>() and qRegisterMetaTypeStreamOperators<T>() are called)
template<> struct BindSupport<QColor,QDataWriter> : BindNative {};
// TODO BindNative other types that should bind specifically for compatibility with QDataStream
// --------------------------------------------------------------------------
......
......@@ -57,7 +57,7 @@ class QJsonBuilder : public IWriter
Q_DISABLE_COPY(QJsonBuilder)
public:
QJsonBuilder(QJsonValue* v) : json(v) { Q_ASSERT(v); }
void reset(QJsonValue* v) { json=v; Q_ASSERT(v); steps.clear(); }
void reset(QJsonValue* v) { json=v; Q_ASSERT(v); steps.resize(0); }
// Shortcuts
/**/ Val<Cursor> value ( ) { return Cursor(this).value(); }
......@@ -102,7 +102,7 @@ class QJsonVisitor : public IReader
Q_DISABLE_COPY(QJsonVisitor)
public:
QJsonVisitor(const QJsonValue* v) : json(v) { Q_ASSERT(v); }
void reset(QJsonValue* v) { json=v; Q_ASSERT(v); steps.clear(); errors.clear(); }
void reset(QJsonValue* v) { json=v; Q_ASSERT(v); steps.resize(0); errors.resize(0); }
struct Error { const char* error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error)+' '+path); } };
QVector<Error> errors;
......@@ -159,7 +159,7 @@ class QJsonWriter : public IWriter
public:
QJsonWriter(QIODevice* io) : io(io) { Q_ASSERT(io); }
~QJsonWriter() { for (auto&& level : levels) io->write(level.end); }
void reset(QIODevice* io) { this->io=io; Q_ASSERT(io); levels.clear(); }
void reset(QIODevice* io) { this->io=io; Q_ASSERT(io); levels.resize(0); }
// Shortcuts
/**/ Val<Cursor> value ( ) { return Cursor(this).value(); }
......@@ -251,7 +251,7 @@ protected:
} else { _reportError(qBindExpectedNull); return false; } }
bool _bind ( QUtf8String& s) { if (caching) { cacheLevel++; return caching->_bind(s.constData()) && cacheOut(); }
QUtf8String u;
if ( get('"', "[{\"ntf-0123456789.")) { u.clear(); char c;
if ( get('"', "[{\"ntf-0123456789.")) { u.resize(0); char c;
while ((c=getCharInString()) != '\0' ) { u.append(c); }
s=u;
return get('"');
......
......@@ -122,7 +122,7 @@ protected:
return true;
}
if (d==I) {
io.buffer().clear(); io.open(QIODevice::WriteOnly); w.reset(&io);
io.buffer().resize(0); io.open(QIODevice::WriteOnly); w.reset(&io);
}
if (is(R)) {
row=-1; // set to 0 by mandatory _item() following
......@@ -137,7 +137,7 @@ protected:
return true;
}
if (d==I) {
io.buffer().clear(); io.open(QIODevice::WriteOnly); w.reset(&io);
io.buffer().resize(0); io.open(QIODevice::WriteOnly); w.reset(&io);
}
if (is(R)) {
row=-1; // set to 0 by mandatory _item() following
......
......@@ -53,7 +53,7 @@ class QVariantBuilder : public IWriter
public:
QVariantBuilder(QVariant* v) : variant(v) { Q_ASSERT(v); }
~QVariantBuilder() { while (!levels.isEmpty()) _out(); }
void reset(QVariant* v) { variant=v; Q_ASSERT(v); levels.clear(); }
void reset(QVariant* v) { variant=v; Q_ASSERT(v); levels.resize(0); }
// Shortcuts
/**/ Val<Cursor> value ( ) { return Cursor(this).value(); }
......@@ -99,7 +99,7 @@ class QVariantVisitor : public IReader
public:
Q_ENABLE_MOVE_DEFAULT(QVariantVisitor)
QVariantVisitor(const QVariant* v) : value(v) { Q_ASSERT(v); }
void reset(const QVariant* v) { value=v; Q_ASSERT(v); levels.clear(); errors.clear(); }
void reset(const QVariant* v) { value=v; Q_ASSERT(v); levels.resize(0); errors.resize(0); }
struct Error { const char* error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error)+' '+path); } };
QVector<Error> errors;
......
......@@ -15,7 +15,7 @@ is used in the field and diagnose complex issues:
### Serialization (Write)
W1. Fast: not as fast but comparable to protobuf/lttng/etl ; potentially without dynamic memory allocation or write thread locking
W1. Fast: similar to QDataStream ; same order of magnitude as protobuf/lttng/etl (up to 10x slower) ; potentially without dynamic memory allocation or write thread locking
W2. Easily extensible to user-defined and third-part types
W3. Support almost all features of simple Qt data (QJson*, QDataStream, QSettings) and most features of complex Qt data (QCbor*, QXml*, QMetaObject, QModel*)
W4. Provide most well-formedness guarantees with low impact on performance
......
......@@ -278,7 +278,7 @@ int main(int argc, char *argv[])
GROUP("builtin>")//========================================================
{
START {
s.clear();
s.resize(0);
QDebug(&s)
<< 1.333333333333f
<< PI
......@@ -289,7 +289,7 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
ba.clear();
ba.resize(0);
TextWriter(&ba)
<< 1.333333333333f
<< PI
......@@ -300,7 +300,7 @@ int main(int argc, char *argv[])
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).sequence()
.bind(1.333333333333f)
.bind(PI)
......@@ -310,6 +310,18 @@ int main(int argc, char *argv[])
;
}
STOP("Json",QString::fromUtf8(b.buffer()));
START {
ba.resize(0);
QXmlStreamWriter w(&ba);
QXmlWriter(&w).sequence()
.bind(1.333333333333f)
.bind(PI)
.bind(ascii)
.bind(false)
.bind(color)
;
}
STOP("Xml",QString::fromUtf8(ba));
START {
v.clear();
QVariantBuilder(&v).sequence()
......@@ -322,7 +334,7 @@ int main(int argc, char *argv[])
}
STOP("Variant",v.toString());
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).value().sequence(5)
.bind(1.333333333333f)
.bind(PI)
......@@ -333,7 +345,7 @@ int main(int argc, char *argv[])
}
STOP("Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QCborStreamWriter s(&b);
s.startArray(5);
s.append(1.333333333333f);
......@@ -353,7 +365,7 @@ int main(int argc, char *argv[])
}
STOP("QCborStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream d(&b);
QDataWriter(&d).sequence()
.bind(1.333333333333f)
......@@ -365,7 +377,7 @@ int main(int argc, char *argv[])
}
STOP("Data",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream(&b)
<< 1.333333333333f
<< PI
......@@ -376,12 +388,12 @@ int main(int argc, char *argv[])
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
float f = 1.333333333333f; bool boolean = false;
START {
ba.clear();
ba.append(reinterpret_cast<const char*>(&f ),sizeof(f ));
ba.resize(0);
ba.append(reinterpret_cast<const char*>(&f ),sizeof(f )); // endianness must be specified externally
ba.append(reinterpret_cast<const char*>(&PI ),sizeof(PI ));
ba.append( ascii );
ba.append(reinterpret_cast<const char*>(&boolean),sizeof(boolean));
ba.append(reinterpret_cast<const char*>(&color ),sizeof(color ));
ba.append(reinterpret_cast<const char*>(&color ),sizeof(color )); // schema evolution must be specified externally
}
STOP("QByteArray",ba.toHex());
......@@ -395,12 +407,12 @@ int main(int argc, char *argv[])
}
STOP("Writables","");
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).bind(writables);
}
STOP("Writables>Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).bind(writables);
}
STOP("Writables>Json",QString::fromUtf8(b.buffer()));
......@@ -409,7 +421,7 @@ int main(int argc, char *argv[])
GROUP("doubles>")//========================================================
{
START {
s.clear();
s.resize(0);
QDebug d(&s);
for (int i=0; i < 16; i++) {
d << transform[i];
......@@ -417,28 +429,35 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
ba.clear();
ba.resize(0);
TextWriter(&ba).bind(transform);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).bind(transform);
}
STOP("Json",b.buffer())
START {
ba.resize(0);
QXmlStreamWriter w(&ba);
QXmlWriter d(&w);
d.bind(transform);
}
STOP("Xml",QString::fromUtf8(ba));
START {
v.clear();
QVariantBuilder(&v).bind(transform);
}
STOP("Variant",v.toString());
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QCborWriter(&ba).bind(transform);
}
STOP("Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QCborStreamWriter s(&b);
quint64 size = 16;
s.startArray(size);
......@@ -449,23 +468,24 @@ int main(int argc, char *argv[])
}
STOP("QCborStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream d(&b);
QDataWriter(&d).value().bind(transform);
}
STOP("Data",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream data(&b);
data << transform.size();
for (int i=0; i < 16; i++) {
for (int i=0; i < transform.size(); i++) {
data << transform[i];
};
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
QByteArray str; str.reserve(500); int size=transform.size();
QByteArray str; str.reserve(500);
START {
str.clear();
str.resize(0);
int size=transform.size();
str.append(reinterpret_cast<char*>(&size),sizeof(size));
for (int i=0; i < size; i++) {
str.append(reinterpret_cast<char*>(&transform[i]),sizeof(transform[i]));
......@@ -479,12 +499,12 @@ int main(int argc, char *argv[])
}
STOP("Writable","");
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).bind(writable);
}
STOP("Writable>Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).bind(writable);
}
STOP("Writable>Json",QString::fromUtf8(b.buffer()));
......@@ -493,7 +513,7 @@ int main(int argc, char *argv[])
GROUP("Person>")//=========================================================
{
START {
s.clear();
s.resize(0);
QDebug(&s)
<< person.firstName
<< person. lastName
......@@ -506,28 +526,36 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
ba.clear();
ba.resize(0);
TextWriter(&ba).bind(person);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).bind(person);
}
STOP("Json",b.buffer())
START {
ba.resize(0);
QXmlStreamWriter w(&ba);
QXmlWriter d(&w);
d.bind(person);
w.writeEndDocument(); // FIXME
}
STOP("Xml",QString::fromUtf8(ba));
START {
v.clear();
QVariantBuilder(&v).bind(person);
}
STOP("Variant",v.toString());
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).bind(person);
}
STOP("Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QCborStreamWriter s(&b);
s.startMap();
s.append("names");s.startArray();
......@@ -551,27 +579,29 @@ int main(int argc, char *argv[])
}
STOP("QCborStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream d(&b);
QDataWriter(&d).value().bind(person);
}
STOP("Data",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QDataStream d(&b);
d << person;
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
QByteArray str; str.reserve(100); double dbl=1.75; int i=18;
QByteArray str; str.reserve(100); int s;
START {
str.clear();
str.append("John");
str.resize(0);
str.append("John"); // encoding must be specified externally
str.append("Doe");
str.append(reinterpret_cast<const char*>(&dbl),sizeof(dbl));
str.append(reinterpret_cast<const char*>(&i ),sizeof(i ));
str.append(reinterpret_cast<const char*>(&person.height),sizeof(person.height)); // endianness must be specified externally
str.append(reinterpret_cast<const char*>(&person.age ),sizeof(person.age ));
s=2; /*phones*/ str.append(reinterpret_cast<const char*>(&s),sizeof(s));
str.append("+44 1234567");
str.append("+44 2345678");
str.append("unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ");
str.append("unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ"); // byte order must be specified externally
s=0; /*children*/ str.append(reinterpret_cast<const char*>(&s),sizeof(s));
}
STOP("QByteArray",str.toHex());
#ifdef PROTOBUF
......@@ -585,19 +615,11 @@ int main(int argc, char *argv[])
pb.add_phones("+44 2345678");
pb.set_comments("unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ");
START {
buf.clear();
buf.resize(0);
buf = pb.SerializeAsString();
}
STOP("protobuf",QByteArray::fromStdString(buf).toHex());
#endif
START {
ba.clear();
QXmlStreamWriter w(&ba);
QXmlWriter d(&w);
d.bind(person);
w.writeEndDocument(); // FIXME
}
STOP("Xml",QString::fromUtf8(ba));
QBindable<> writable;
START {
......@@ -605,12 +627,12 @@ int main(int argc, char *argv[])
}
STOP("Writable","");
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).bind(writable);
}
STOP("Writable>Cbor",QString::fromUtf8(ba.toHex()));
START {
b.seek(0); b.buffer().clear();
b.seek(0); b.buffer().resize(0);
QJsonWriter(&b).bind(writable);
}
STOP("Writable>Json",QString::fromUtf8(b.buffer()));
......@@ -662,7 +684,7 @@ int main(int argc, char *argv[])
STOP("JsonValue>P",QString::fromUtf8(Text(p)+Text(visitorErrors)))
//---------------------------------------------------------------------
START {
roundtrip.seek(0); ba.clear();
roundtrip.seek(0); ba.resize(0);
QJsonReader r(&roundtrip);
r.bind(QCborWriter(&ba).value());
readerErrors = r.errors;
......@@ -698,7 +720,7 @@ int main(int argc, char *argv[])
}
STOP("Cbor>P",QString(Text(p)+Text(readerErrors)))
START {
roundtrip.buffer().clear();
roundtrip.buffer().resize(0);
QCborWriter(&roundtrip.buffer()).bind(p);
}
STOP("P>Cbor",QString::fromUtf8(roundtrip.buffer().toHex()))
......@@ -799,13 +821,13 @@ int main(int argc, char *argv[])
}
STOP("Cbor>CborValue",cv.toDiagnosticNotation()+QString::fromUtf8((Text(readerErrors))));
START {
ba.clear();
ba.resize(0);
QCborWriter(&ba).bind(cv);
}
STOP("Cbor<CborValue",ba.toHex());
//---------------------------------------------------------------------
START {
roundtrip.seek(0); b.seek(0); b.buffer().clear();
roundtrip.seek(0); b.seek(0); b.buffer().resize(0);
QCborReader r(&roundtrip);
r.bind(QJsonWriter(&b).value());
readerErrors = r.errors;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment