From c00d5fb305abff370f869dec0e9404f8a4a5646b Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 7 Apr 2015 12:50:07 +0200 Subject: Use memcpy to copy tables into vectors. Ideally we wouldn't be copying at all, and somehow cast the table to a vector. Unfortunately I haven't figured out how to do that, and this solution at least gets us from 0.065 ms to 0.028 ms in testCreateCommand. --- common/entitybuffer.cpp | 27 +++++++++++++++++---------- common/entitybuffer.h | 7 +++++++ tests/CMakeLists.txt | 1 + tests/dummyresourcebenchmark.cpp | 22 +++++++++++++++++++++- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/common/entitybuffer.cpp b/common/entitybuffer.cpp index 5ba4afe..b555ac3 100644 --- a/common/entitybuffer.cpp +++ b/common/entitybuffer.cpp @@ -56,17 +56,24 @@ void EntityBuffer::extractResourceBuffer(void *dataValue, int dataSize, const st } } -void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) +flatbuffers::Offset > EntityBuffer::appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size) { - auto metadata = fbb.CreateVector(static_cast(metadataData), metadataSize); - auto resource = fbb.CreateVector(static_cast(resourceData), resourceSize); - auto local = fbb.CreateVector(static_cast(localData), localSize); - auto builder = Akonadi2::EntityBuilder(fbb); - builder.add_metadata(metadata); - builder.add_resource(resource); - builder.add_local(local); + //Since we do memcpy trickery, this will only work on little endian + assert(FLATBUFFERS_LITTLEENDIAN); + auto metadata = fbb.CreateUninitializedVector(size); + { + auto ptr = reinterpret_cast *>(fbb.GetBufferPointer())->Data(); + std::memcpy((void*)ptr, data, size); + } + return metadata; +} - auto buffer = builder.Finish(); - Akonadi2::FinishEntityBuffer(fbb, buffer); +void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) +{ + auto metadata = appendAsVector(fbb, metadataData, metadataSize); + auto resource = appendAsVector(fbb, resourceData, resourceSize); + auto local = appendAsVector(fbb, localData, localSize); + auto entity = Akonadi2::CreateEntity(fbb, metadata, resource, local); + Akonadi2::FinishEntityBuffer(fbb, entity); } diff --git a/common/entitybuffer.h b/common/entitybuffer.h index 097b450..f22c84e 100644 --- a/common/entitybuffer.h +++ b/common/entitybuffer.h @@ -15,7 +15,14 @@ public: const Entity &entity(); static void extractResourceBuffer(void *dataValue, int dataSize, const std::function &handler); + /* + * TODO: Ideally we would be passing references to vectors in the same bufferbuilder, to avoid needlessly copying data. + * Unfortunately I couldn't find a way to cast a table to a vector reference. + * We can't use union's either (which would allow to have a field that stores a selection of tables), as we don't want to modify + * the entity schema for each resource's buffers. + */ static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize); + static flatbuffers::Offset > appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size); private: const Entity *mEntity; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8257c8a..a38471f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(hawd) set(CMAKE_AUTOMOC ON) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/hawd) +include_directories (${CMAKE_CURRENT_BINARY_DIR}/../dummyresource) generate_flatbuffers(calendar) diff --git a/tests/dummyresourcebenchmark.cpp b/tests/dummyresourcebenchmark.cpp index 7375ff8..308a4e8 100644 --- a/tests/dummyresourcebenchmark.cpp +++ b/tests/dummyresourcebenchmark.cpp @@ -3,6 +3,7 @@ #include #include "dummyresource/resourcefactory.h" +#include "dummyresource/domainadaptor.h" #include "clientapi.h" #include "commands.h" #include "entitybuffer.h" @@ -11,7 +12,6 @@ #include "entity_generated.h" #include "metadata_generated.h" #include "createentity_generated.h" -#include "dummyresource/resourcefactory.h" static void removeFromDisk(const QString &name) { @@ -144,6 +144,26 @@ private Q_SLOTS: qDebug() << "Append to messagequeue " << appendTime; qDebug() << "All processed: " << allProcessedTime << "/sec " << num*1000/allProcessedTime; } + void testCreateCommand() + { + Akonadi2::Domain::Event event; + + QBENCHMARK { + auto mFactory = new DummyEventAdaptorFactory; + static flatbuffers::FlatBufferBuilder entityFbb; + entityFbb.Clear(); + mFactory->createBuffer(event, entityFbb); + + static flatbuffers::FlatBufferBuilder fbb; + fbb.Clear(); + //This is the resource buffer type and not the domain type + auto type = fbb.CreateString("event"); + // auto delta = fbb.CreateVector(entityFbb.GetBufferPointer(), entityFbb.GetSize()); + auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); + auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); + Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); + } + } }; QTEST_MAIN(DummyResourceBenchmark) -- cgit v1.2.3