diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 1905f2d..a8b8aed 100755
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -69,6 +69,15 @@ target_link_libraries(libsdbus-c++_unittests ${SYSTEMD_LIBRARIES} gmock gmock_ma
add_executable(libsdbus-c++_integrationtests ${INTEGRATIONTESTS_SRCS})
target_link_libraries(libsdbus-c++_integrationtests sdbus-c++ gmock gmock_main)
+# Manual performance tests
+option(ENABLE_PERFTESTS "Build and install manual performance tests (default OFF)" OFF)
+if(ENABLE_PERFTESTS)
+ add_executable(libsdbus-c++_perftests_client perftests/client.cpp perftests/perftest-proxy.h)
+ target_link_libraries(libsdbus-c++_perftests_client sdbus-c++)
+ add_executable(libsdbus-c++_perftests_server perftests/server.cpp perftests/perftest-adaptor.h)
+ target_link_libraries(libsdbus-c++_perftests_server sdbus-c++)
+endif()
+
#----------------------------------
# INSTALLATION
#----------------------------------
@@ -77,6 +86,12 @@ install(TARGETS libsdbus-c++_unittests DESTINATION /opt/test/bin)
install(TARGETS libsdbus-c++_integrationtests DESTINATION /opt/test/bin)
install(FILES ${INTEGRATIONTESTS_SOURCE_DIR}/files/libsdbus-cpp-test.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d)
+if(ENABLE_PERFTESTS)
+ install(TARGETS libsdbus-c++_perftests_client DESTINATION /opt/test/bin)
+ install(TARGETS libsdbus-c++_perftests_server DESTINATION /opt/test/bin)
+ install(FILES perftests/files/org.sdbuscpp.perftest.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d)
+endif()
+
#----------------------------------
# RUNNING THE TESTS UPON BUILD
#----------------------------------
diff --git a/test/perftests/client.cpp b/test/perftests/client.cpp
new file mode 100644
index 0000000..61b6a02
--- /dev/null
+++ b/test/perftests/client.cpp
@@ -0,0 +1,162 @@
+/**
+ * (C) 2019 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ *
+ * @file client.cpp
+ *
+ * Created on: Jan 25, 2019
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "perftest-proxy.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std::chrono_literals;
+
+class PerftestClient : public sdbus::ProxyInterfaces
+{
+public:
+ PerftestClient(std::string destination, std::string objectPath)
+ : sdbus::ProxyInterfaces(std::move(destination), std::move(objectPath))
+ {
+ }
+
+protected:
+ virtual void onDataSignal(const std::string& data) override
+ {
+ static unsigned int counter = 0;
+ static std::chrono::time_point startTime;
+
+ assert(data.size() == m_msgSize);
+
+ ++counter;
+
+ if (counter == 1)
+ startTime = std::chrono::steady_clock::now();
+ else if (counter == m_msgCount)
+ {
+ auto stopTime = std::chrono::steady_clock::now();
+ std::cout << "Received " << m_msgCount << " signals in: " << std::chrono::duration_cast(stopTime - startTime).count() << " ms" << std::endl;
+ counter = 0;
+ }
+ }
+
+public:
+ unsigned int m_msgSize{};
+ unsigned int m_msgCount{};
+};
+
+std::string createRandomString(size_t length)
+{
+ auto randchar = []() -> char
+ {
+ const char charset[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+ const size_t max_index = (sizeof(charset) - 1);
+ return charset[ rand() % max_index ];
+ };
+ std::string str(length, 0);
+ std::generate_n(str.begin(), length, randchar);
+ return str;
+}
+
+
+//-----------------------------------------
+int main(int /*argc*/, char */*argv*/[])
+{
+ const char* destinationName = "org.sdbuscpp.perftest";
+ const char* objectPath = "/org/sdbuscpp/perftest";
+ PerftestClient client(destinationName, objectPath);
+
+ const unsigned int repetitions{20};
+ unsigned int msgCount = 1000;
+ unsigned int msgSize{};
+
+ msgSize = 20;
+ std::cout << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
+ client.m_msgCount = msgCount; client.m_msgSize = msgSize;
+ for (unsigned int r = 0; r < repetitions; ++r)
+ {
+ client.sendDataSignals(msgCount, msgSize);
+
+ std::this_thread::sleep_for(1000ms);
+ }
+
+ msgSize = 1000;
+ std::cout << std::endl << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
+ client.m_msgCount = msgCount; client.m_msgSize = msgSize;
+ for (unsigned int r = 0; r < repetitions; ++r)
+ {
+ client.sendDataSignals(msgCount, msgSize);
+
+ std::this_thread::sleep_for(1000ms);
+ }
+
+ msgSize = 20;
+ std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
+ for (unsigned int r = 0; r < repetitions; ++r)
+ {
+ auto str1 = createRandomString(msgSize/2);
+ auto str2 = createRandomString(msgSize/2);
+
+ auto startTime = std::chrono::steady_clock::now();
+ for (unsigned int i = 0; i < msgCount; i++)
+ {
+ auto result = client.concatenateTwoStrings(str1, str2);
+
+ assert(result.size() == str1.size() + str2.size());
+ assert(result.size() == msgSize);
+ }
+ auto stopTime = std::chrono::steady_clock::now();
+ std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast(stopTime - startTime).count() << " ms" << std::endl;
+
+ std::this_thread::sleep_for(1000ms);
+ }
+
+ msgSize = 1000;
+ std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
+ for (unsigned int r = 0; r < repetitions; ++r)
+ {
+ auto str1 = createRandomString(msgSize/2);
+ auto str2 = createRandomString(msgSize/2);
+
+ auto startTime = std::chrono::steady_clock::now();
+ for (unsigned int i = 0; i < msgCount; i++)
+ {
+ auto result = client.concatenateTwoStrings(str1, str2);
+
+ assert(result.size() == str1.size() + str2.size());
+ assert(result.size() == msgSize);
+ }
+ auto stopTime = std::chrono::steady_clock::now();
+ std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast(stopTime - startTime).count() << " ms" << std::endl;
+
+ std::this_thread::sleep_for(1000ms);
+ }
+
+ return 0;
+}
diff --git a/test/perftests/files/org.sdbuscpp.perftest.conf b/test/perftests/files/org.sdbuscpp.perftest.conf
new file mode 100644
index 0000000..c5bae6e
--- /dev/null
+++ b/test/perftests/files/org.sdbuscpp.perftest.conf
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/perftests/org.sdbuscpp.perftest.xml b/test/perftests/org.sdbuscpp.perftest.xml
new file mode 100644
index 0000000..cb0f363
--- /dev/null
+++ b/test/perftests/org.sdbuscpp.perftest.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/perftests/perftest-adaptor.h b/test/perftests/perftest-adaptor.h
new file mode 100644
index 0000000..e06c0ed
--- /dev/null
+++ b/test/perftests/perftest-adaptor.h
@@ -0,0 +1,46 @@
+
+/*
+ * This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
+ */
+
+#ifndef __sdbuscpp__perftest_adaptor_h__adaptor__H__
+#define __sdbuscpp__perftest_adaptor_h__adaptor__H__
+
+#include
+#include
+#include
+
+namespace org {
+namespace sdbuscpp {
+
+class perftest_adaptor
+{
+public:
+ static constexpr const char* interfaceName = "org.sdbuscpp.perftest";
+
+protected:
+ perftest_adaptor(sdbus::IObject& object)
+ : object_(object)
+ {
+ object_.registerMethod("sendDataSignals").onInterface(interfaceName).implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); });
+ object_.registerMethod("concatenateTwoStrings").onInterface(interfaceName).implementedAs([this](const std::string& string1, const std::string& string2){ return this->concatenateTwoStrings(string1, string2); });
+ object_.registerSignal("dataSignal").onInterface(interfaceName).withParameters();
+ }
+
+public:
+ void dataSignal(const std::string& data)
+ {
+ object_.emitSignal("dataSignal").onInterface(interfaceName).withArguments(data);
+ }
+
+private:
+ virtual void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) = 0;
+ virtual std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) = 0;
+
+private:
+ sdbus::IObject& object_;
+};
+
+}} // namespaces
+
+#endif
diff --git a/test/perftests/perftest-proxy.h b/test/perftests/perftest-proxy.h
new file mode 100644
index 0000000..16b80ed
--- /dev/null
+++ b/test/perftests/perftest-proxy.h
@@ -0,0 +1,49 @@
+
+/*
+ * This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
+ */
+
+#ifndef __sdbuscpp__perftest_proxy_h__proxy__H__
+#define __sdbuscpp__perftest_proxy_h__proxy__H__
+
+#include
+#include
+#include
+
+namespace org {
+namespace sdbuscpp {
+
+class perftest_proxy
+{
+public:
+ static constexpr const char* interfaceName = "org.sdbuscpp.perftest";
+
+protected:
+ perftest_proxy(sdbus::IObjectProxy& object)
+ : object_(object)
+ {
+ object_.uponSignal("dataSignal").onInterface(interfaceName).call([this](const std::string& data){ this->onDataSignal(data); });
+ }
+
+ virtual void onDataSignal(const std::string& data) = 0;
+
+public:
+ void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize)
+ {
+ object_.callMethod("sendDataSignals").onInterface(interfaceName).withArguments(numberOfSignals, signalMsgSize);
+ }
+
+ std::string concatenateTwoStrings(const std::string& string1, const std::string& string2)
+ {
+ std::string result;
+ object_.callMethod("concatenateTwoStrings").onInterface(interfaceName).withArguments(string1, string2).storeResultsTo(result);
+ return result;
+ }
+
+private:
+ sdbus::IObjectProxy& object_;
+};
+
+}} // namespaces
+
+#endif
diff --git a/test/perftests/server.cpp b/test/perftests/server.cpp
new file mode 100644
index 0000000..490331f
--- /dev/null
+++ b/test/perftests/server.cpp
@@ -0,0 +1,94 @@
+/**
+ * (C) 2019 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ *
+ * @file server.cpp
+ *
+ * Created on: Jan 25, 2019
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "perftest-adaptor.h"
+#include
+#include
+#include
+#include
+#include
+
+using namespace std::chrono_literals;
+
+std::string createRandomString(size_t length);
+
+class PerftestServer : public sdbus::Interfaces
+{
+public:
+ PerftestServer(sdbus::IConnection& connection, std::string objectPath)
+ : sdbus::Interfaces(connection, std::move(objectPath))
+ {
+ }
+
+protected:
+ virtual void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) override
+ {
+ auto data = createRandomString(signalMsgSize);
+ char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+ auto start_time = std::chrono::steady_clock::now();
+ for (uint32_t i = 0; i < numberOfSignals; ++i)
+ {
+ // Emit signal
+ dataSignal(data);
+ }
+ auto stop_time = std::chrono::steady_clock::now();
+ std::cout << "Server sent " << numberOfSignals << " signals in: " << std::chrono::duration_cast(stop_time - start_time).count() << " ms" << std::endl;
+ }
+
+ virtual std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) override
+ {
+ return string1 + string2;
+ }
+};
+
+std::string createRandomString(size_t length)
+{
+ auto randchar = []() -> char
+ {
+ const char charset[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+ const size_t max_index = (sizeof(charset) - 1);
+ return charset[ rand() % max_index ];
+ };
+ std::string str(length, 0);
+ std::generate_n(str.begin(), length, randchar);
+ return str;
+}
+
+
+//-----------------------------------------
+int main(int /*argc*/, char */*argv*/[])
+{
+ const char* serviceName = "org.sdbuscpp.perftest";
+ auto connection = sdbus::createSystemBusConnection(serviceName);
+
+ const char* objectPath = "/org/sdbuscpp/perftest";
+ PerftestServer server(*connection, objectPath);
+
+ connection->enterProcessingLoop();
+}