1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #include <CommonAPI/SerializableStruct.h>
5 #include <CommonAPI/DBus/DBusInputStream.h>
6 #include <CommonAPI/DBus/DBusOutputStream.h>
8 #include <unordered_map>
9 #include <bits/functional_hash.h>
11 #include <gtest/gtest.h>
13 #include <dbus/dbus.h>
18 #include <unordered_map>
19 #include <bits/functional_hash.h>
22 class BenchmarkingTest: public ::testing::Test {
24 DBusMessage* libdbusMessage;
25 DBusMessageIter libdbusMessageWriteIter;
30 libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
31 ASSERT_TRUE(libdbusMessage != NULL);
32 dbus_message_iter_init_append(libdbusMessage, &libdbusMessageWriteIter);
36 dbus_message_unref(libdbusMessage);
40 template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
41 void prepareLibdbusArray(DBusMessage* libdbusMessage,
42 const int arrayElementLibdbusType,
43 const char* arrayElementLibdbusTypeAsString,
44 const _ArrayElementLibdbusType& arrayInitElementValue,
45 const uint32_t arrayInitTime,
46 size_t& libdbusInitElementCount) {
48 DBusMessageIter libdbusMessageIter;
49 DBusMessageIter libdbusMessageContainerIter;
51 dbus_message_iter_init_append(libdbusMessage, &libdbusMessageIter);
53 dbus_bool_t libdbusSuccess = dbus_message_iter_open_container(&libdbusMessageIter,
55 arrayElementLibdbusTypeAsString,
56 &libdbusMessageContainerIter);
57 ASSERT_TRUE(libdbusSuccess);
60 std::chrono::milliseconds libdbusInitTime;
61 std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
64 for (int i = 0; i < 1000; i++)
65 dbus_message_iter_append_basic(&libdbusMessageContainerIter,
66 arrayElementLibdbusType,
67 &arrayInitElementValue);
69 libdbusInitElementCount += 1000;
71 libdbusInitTime = std::chrono::duration_cast<std::chrono::milliseconds>(
72 std::chrono::high_resolution_clock::now() - clockStart);
73 } while (libdbusInitTime.count() < arrayInitTime);
75 libdbusSuccess = dbus_message_iter_close_container(&libdbusMessageIter, &libdbusMessageContainerIter);
76 ASSERT_TRUE(libdbusSuccess);
78 std::cout << "LibdbusInitTime = " << libdbusInitTime.count() << std::endl;
79 std::cout << "LibdbusInitElementCount = " << libdbusInitElementCount << std::endl;
83 template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
84 void measureLibdbusArrayReadTime(DBusMessage* libdbusMessage,
85 size_t& libdbusInitElementCount,
86 std::chrono::milliseconds& libdbusArrayReadTime) {
88 DBusMessageIter libdbusMessageIter;
89 DBusMessageIter libdbusMessageContainerIter;
91 dbus_bool_t libdbusSuccess;
93 libdbusSuccess = dbus_message_iter_init(libdbusMessage, &libdbusMessageIter);
94 ASSERT_TRUE(libdbusSuccess);
96 dbus_message_iter_recurse(&libdbusMessageIter, &libdbusMessageContainerIter);
98 size_t libdbusReadElementCount = 0;
99 std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
102 _ArrayElementLibdbusType libdbusValue;
104 dbus_message_iter_get_basic(&libdbusMessageContainerIter, &libdbusValue);
106 ++libdbusReadElementCount;
107 } while (dbus_message_iter_next(&libdbusMessageContainerIter));
109 libdbusArrayReadTime = std::chrono::duration_cast<std::chrono::milliseconds>(
110 std::chrono::high_resolution_clock::now() - clockStart);
112 ASSERT_EQ(libdbusInitElementCount, libdbusReadElementCount);
116 template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
117 void measureCommonApiArrayReadTime(DBusMessage* libdbusMessage,
118 std::chrono::milliseconds& commonArrayApiReadTime,
119 size_t& libdbusInitElementCount) {
121 CommonAPI::DBus::DBusMessage dbusMessage(libdbusMessage);
122 CommonAPI::DBus::DBusInputStream DBusInputStream(dbusMessage);
123 std::vector<_ArrayElementCommonApiType> commonApiVector;
125 std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
127 DBusInputStream >> commonApiVector;
129 commonArrayApiReadTime = std::chrono::duration_cast<std::chrono::milliseconds>(
130 std::chrono::high_resolution_clock::now() - clockStart);
132 ASSERT_EQ(libdbusInitElementCount, commonApiVector.size());
136 template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
137 void measureArrayReadTime(
138 const int arrayElementLibdbusType,
139 const char* arrayElementLibdbusTypeAsString,
140 const _ArrayElementLibdbusType arrayInitElementValue,
141 const uint32_t arrayInitTime,
142 std::chrono::milliseconds& libdbusArrayReadTime,
143 std::chrono::milliseconds& commonArrayApiReadTime) {
145 DBusMessage* libdbusMessage;
146 dbus_bool_t libdbusSuccess;
147 size_t libdbusInitElementCount = 0;
149 libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
150 ASSERT_TRUE(libdbusMessage != NULL);
152 prepareLibdbusArray<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
154 arrayElementLibdbusType,
155 arrayElementLibdbusTypeAsString,
156 arrayInitElementValue,
158 libdbusInitElementCount);
160 measureLibdbusArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
162 libdbusInitElementCount,
163 libdbusArrayReadTime);
165 measureCommonApiArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
167 commonArrayApiReadTime,
168 libdbusInitElementCount);
172 TEST_F(BenchmarkingTest, InputStreamReadsIntegerArrayFasterThanLibdbus) {
173 std::chrono::milliseconds libdbusArrayReadTime;
174 std::chrono::milliseconds commonApiArrayReadTime;
176 measureArrayReadTime<int32_t, int32_t>(DBUS_TYPE_INT32,
177 DBUS_TYPE_INT32_AS_STRING,
180 libdbusArrayReadTime,
181 commonApiArrayReadTime);
183 RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count());
184 RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count());
186 std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl;
187 std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl;
189 ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30)
190 << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!";
193 TEST_F(BenchmarkingTest, InputStreamReadsStringArrayFasterThanLibdbus) {
194 std::chrono::milliseconds libdbusArrayReadTime;
195 std::chrono::milliseconds commonApiArrayReadTime;
197 measureArrayReadTime<char*, std::string>(DBUS_TYPE_STRING,
198 DBUS_TYPE_STRING_AS_STRING,
199 const_cast<char*>("01234567890123456789"),
201 libdbusArrayReadTime,
202 commonApiArrayReadTime);
204 RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count());
205 RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count());
207 std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl;
208 std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl;
210 ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30)
211 << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!";
214 int main(int argc, char** argv) {
215 ::testing::InitGoogleTest(&argc, argv);
216 return RUN_ALL_TESTS();