Make deserialization benchmark more complicated

Use more complicated data structure when benchmarking the protobuf
deserialzer. This allows also to identify changes that have
performance impact onto the deserialization.

Pick-to: 6.8 6.9
Change-Id: Ibf3a312c18edb86d383d5e236f3dad47e8581532
Reviewed-by: Dennis Oberst <dennis.oberst@qt.io>
This commit is contained in:
Alexey Edelev 2024-10-03 16:25:09 +02:00
parent b614b9dc26
commit 76684a5ae7
3 changed files with 96 additions and 11 deletions

View File

@ -16,3 +16,5 @@ qt6_add_protobuf(tst_bench_deserialize_protobuf
data/bench.proto data/bench.proto
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated" OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated"
) )
set_target_properties(tst_bench_deserialize_protobuf PROPERTIES QT_USE_PROTOBUF_LIST_ALIASES FALSE)

View File

@ -5,7 +5,42 @@ syntax = "proto3";
package qtbench; package qtbench;
message EmptyMessage {} message ScalarTypes {
enum EnumType {
Value1 = 0;
Value2 = 1;
Value3 = 2;
}
int32 field1 = 1;
uint32 field2 = 2;
sint32 field3 = 3;
fixed32 field4 = 4;
sfixed32 field5 = 5;
int64 field6 = 6;
uint64 field7 = 7;
sint64 field8 = 8;
fixed64 field9 = 9;
sfixed64 field10 = 10;
float field11 = 11;
double field12 = 12;
string field13 = 13;
bytes field14 = 14;
EnumType field15 = 15;
}
message ScalarTypesRepeated {
repeated ScalarTypes field1 = 1;
repeated ScalarTypes.EnumType field2 = 2;
}
message MapTypes {
map<int32, ScalarTypesRepeated> field1 = 1;
map<string, ScalarTypesRepeated> field2 = 2;
}
message BenchmarkMessage {
repeated MapTypes field1 = 1;
}
message SimpleBoolMessage { message SimpleBoolMessage {
bool testFieldBool = 1; bool testFieldBool = 1;
@ -19,7 +54,3 @@ message RecursiveMessage {
int32 testFieldInt = 1; int32 testFieldInt = 1;
RecursiveMessage testFieldRecursive = 2; RecursiveMessage testFieldRecursive = 2;
} }
message ListOfObjects {
repeated SimpleBoolMessage testFieldBool = 1;
}

View File

@ -7,22 +7,74 @@
#include "bench.qpb.h" #include "bench.qpb.h"
using namespace Qt::StringLiterals;
class tst_ProtoDeserialize : public QObject class tst_ProtoDeserialize : public QObject
{ {
Q_OBJECT Q_OBJECT
private Q_SLOTS: private Q_SLOTS:
void initTestCase();
void deserialize_data(); void deserialize_data();
void deserialize(); void deserialize();
private:
QByteArray benchBuffer;
}; };
std::array<std::pair<QString, QByteArray>, 3> data = { std::array<std::pair<QString, QByteArray>, 3> data = {
std::make_pair("qtbench.SimpleBoolMessage", QByteArray::fromHex("0801")), std::make_pair("qtbench.SimpleBoolMessage", QByteArray::fromHex("0801")),
std::make_pair("qtbench.SimpleBytesMessage", QByteArray::fromHex("0a0c48656c6c6f20776f726c6421")), std::make_pair("qtbench.SimpleBytesMessage",
std::make_pair("qtbench.RecursiveMessage", QByteArray::fromHex("080112120802120e0803120a08041206080512020806")), QByteArray::fromHex("0a0c48656c6c6f20776f726c6421")),
std::make_pair("qtbench.RecursiveMessage",
QByteArray::fromHex("080112120802120e0803120a08041206080512020806")),
}; };
// This one can be repeated, so we will use it specially
auto listOfObject = std::make_pair("qtbench.ListOfObjects", QByteArray::fromHex("0a020801")); void tst_ProtoDeserialize::initTestCase()
{
qtbench::ScalarTypes s;
s.setField1(std::numeric_limits<QtProtobuf::int32>::min());
s.setField2(std::numeric_limits<QtProtobuf::uint32>::max());
s.setField3(std::numeric_limits<QtProtobuf::sint32>::max());
s.setField4(std::numeric_limits<QtProtobuf::fixed32>::max());
s.setField5(std::numeric_limits<QtProtobuf::sfixed32>::min());
s.setField6(std::numeric_limits<QtProtobuf::int64>::min());
s.setField7(std::numeric_limits<QtProtobuf::uint64>::max());
s.setField8(std::numeric_limits<QtProtobuf::sint64>::min());
s.setField9(std::numeric_limits<QtProtobuf::fixed64>::max());
s.setField10(std::numeric_limits<QtProtobuf::sfixed64>::min());
s.setField11(42.0);
s.setField12(42.0);
s.setField13("Hello Qt!"_L1);
s.setField14("Hello Qt!"_ba);
s.setField15(qtbench::ScalarTypes::EnumType::Value3);
qtbench::ScalarTypesRepeated r;
r.setField1({ s, s, s, s, s, s, s, s, s, s, });
r.setField2({ qtbench::ScalarTypes::EnumType::Value1, qtbench::ScalarTypes::EnumType::Value2,
qtbench::ScalarTypes::EnumType::Value3, qtbench::ScalarTypes::EnumType::Value3,
qtbench::ScalarTypes::EnumType::Value2, qtbench::ScalarTypes::EnumType::Value1,
qtbench::ScalarTypes::EnumType::Value2, qtbench::ScalarTypes::EnumType::Value3,
qtbench::ScalarTypes::EnumType::Value1, qtbench::ScalarTypes::EnumType::Value2,
qtbench::ScalarTypes::EnumType::Value1, qtbench::ScalarTypes::EnumType::Value3 });
qtbench::MapTypes m;
m.setField1({
{ 0, r },
{ std::numeric_limits<QtProtobuf::int32>::max(), r },
{ std::numeric_limits<QtProtobuf::int32>::min(), r }
});
m.setField2({
{ ""_L1, r },
{ "Hellow Qt!"_L1, r }
});
qtbench::BenchmarkMessage msg;
msg.setField1({ m });
QProtobufSerializer serializer;
benchBuffer = msg.serialize(&serializer);
}
void tst_ProtoDeserialize::deserialize_data() void tst_ProtoDeserialize::deserialize_data()
{ {
@ -33,8 +85,8 @@ void tst_ProtoDeserialize::deserialize_data()
QTest::newRow(qPrintable(name)) << name << value; QTest::newRow(qPrintable(name)) << name << value;
for (auto i : {1, 10, 100, 1000}) { for (auto i : {1, 10, 100, 1000}) {
QTest::addRow("qtbench.ListOfObjects x %d", i) QTest::addRow("qtbench.BenchmarkMessage x %d", i)
<< listOfObject.first << listOfObject.second.repeated(i); << "qtbench.BenchmarkMessage" << benchBuffer.repeated(i);
} }
} }