Add a basic benchmark for subsession_add_fixed_size 25/324925/1
authorMichal Bloch <m.bloch@samsung.com>
Wed, 28 May 2025 19:49:36 +0000 (21:49 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Wed, 28 May 2025 21:05:55 +0000 (23:05 +0200)
Change-Id: Ib411a2ce77f27f9859476cc136fa3ec65bb0a7bf

tests/api_tests/CMakeLists.txt
tests/api_tests/test_benchmark_add.cpp [new file with mode: 0644]

index 1c8a907ee41345aaf5c0e92f425d4465f9845fd6..eb5d2ef7c71d626337c5dbb3b8a9b4cc9886109d 100644 (file)
@@ -23,3 +23,4 @@ add_libsd_target_test(api_switch_user_completion "")
 add_libsd_target_test(api_get_user_list  "")
 add_libsd_target_test(api_event_wait_done_err "")
 add_libsd_target_test(api_register_event_err "")
+add_libsd_target_test(benchmark_add  "")
diff --git a/tests/api_tests/test_benchmark_add.cpp b/tests/api_tests/test_benchmark_add.cpp
new file mode 100644 (file)
index 0000000..8892793
--- /dev/null
@@ -0,0 +1,83 @@
+#include <gio/gio.h>
+#include "sessiond.h"
+
+#include <cstdlib>
+#include <chrono>
+#include <iostream>
+#include <thread>
+
+using namespace std::literals;
+
+// tweakables
+static constexpr size_t CALLS_TO_MAKE = 10;
+static constexpr auto SUBSESSION_NAME = "benchmark"sv;
+static constexpr int UID = 5001;
+static constexpr int IMAGE_SIZE = 10 * 1024;
+
+using Clock = std::chrono::high_resolution_clock;
+using Timestamp = Clock::time_point;
+using Duration = Clock::duration;
+
+/* sessiond API mandates the use of GLib, this is just a test so use
+ * globals to avoid all that userdata pointer management nonsense */
+static GMainLoop *mainloop = nullptr;
+static bool waiting_for_reply = false;
+std::chrono::duration <double, std::milli> total_duration;
+static Timestamp start_timestamp;
+static auto calls_remaining = CALLS_TO_MAKE;
+static std::chrono::seconds sleep_duration;
+
+void callback(int result, void *userdata)
+{
+       total_duration += Clock::now() - start_timestamp;
+       if (result != SUBSESSION_ERROR_NONE) {
+               std::cout << "ERROR! Code: " << result << std::endl;
+               std::exit(EXIT_FAILURE);
+       }
+       -- calls_remaining;
+       waiting_for_reply = false;
+}
+
+gboolean periodic_check (gpointer data)
+{
+       if (waiting_for_reply) {
+               std::this_thread::yield();
+               return TRUE;
+       }
+
+       if (!calls_remaining) {
+               g_main_loop_quit(mainloop);
+               return TRUE;
+       }
+
+       waiting_for_reply = true;
+       subsession_remove_user(UID, SUBSESSION_NAME.data(), nullptr, nullptr);
+       std::this_thread::sleep_for(sleep_duration);
+       start_timestamp = Clock::now();
+       subsession_add_user_fixed_size(UID, SUBSESSION_NAME.data(), IMAGE_SIZE, callback, nullptr);
+       return TRUE;
+}
+
+int main(int argc, char **argv)
+{
+       if (argc != 2) {
+               std::cout << "usage: benchmark <seconds_to_sleep>" << std::endl;
+               return EXIT_FAILURE;
+       }
+       sleep_duration = std::chrono::seconds(std::stoi(argv[1]));
+       total_duration = total_duration.zero();
+
+       // cleanup any remnant garbage from earlier failed tests
+       subsession_remove_user(UID, SUBSESSION_NAME.data(), nullptr, nullptr);
+
+       const auto idle_id = g_idle_add(periodic_check, nullptr);
+       mainloop = g_main_loop_new(nullptr, false);
+       g_main_loop_run(mainloop);
+
+       std::cout << "Waited an average of " << total_duration.count() / CALLS_TO_MAKE << "ms per subsession add" << std::endl;
+
+       g_source_remove(idle_id);
+       g_main_loop_unref(mainloop);
+
+       return EXIT_SUCCESS;
+}