SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
## Targets
+SET(TARGET_MESSAGE_PORT_BENCHMARK "message-port-benchmark")
SET(TARGET_MESSAGE_PORT "message-port")
ENABLE_TESTING()
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(test)
+ADD_SUBDIRECTORY(benchmark)
--- /dev/null
+ADD_DEFINITIONS("-DFULLVER=\"${FULLVER}\"")
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} BENCHMARK_SRCS)
+
+ADD_EXECUTABLE(${TARGET_MESSAGE_PORT_BENCHMARK}
+ ${BENCHMARK_SRCS}
+)
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_MESSAGE_PORT_BENCHMARK} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include/)
+
+APPLY_PKG_CONFIG(${TARGET_MESSAGE_PORT_BENCHMARK} PUBLIC
+ AUL_DEPS
+ BUNDLE_DEPS
+ DLOG_DEPS
+ GLIB_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_MESSAGE_PORT_BENCHMARK} PUBLIC
+ ${TARGET_MESSAGE_PORT})
+SET_TARGET_PROPERTIES(${TARGET_MESSAGE_PORT_BENCHMARK} PROPERTIES
+ COMPILE_FLAGS "-fPIE")
+SET_TARGET_PROPERTIES(${TARGET_MESSAGE_PORT_BENCHMARK} PROPERTIES
+ LINK_FLAGS "-pie")
+
+INSTALL(TARGETS ${TARGET_MESSAGE_PORT_BENCHMARK} DESTINATION bin)
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "MESSAGE_PORT_BENCHMARK"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif // LOG_PRIVATE_HH_
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bundle_cpp.h>
+#include <glib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <ctime>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "log-private.hh"
+#include "message_port.h"
+#include "options.hh"
+
+namespace {
+
+class Tester {
+ public:
+ Tester() {
+ setenv("AUL_APPID", "messageport.benchmark", 1);
+ setenv(
+ "DBUS_SESSION_BUS_ADDRESS",
+ "kernel:path=/sys/fs/kdbus/5001-user/bus;unix:path=/run/user/5001/bus",
+ 1);
+ loop_ = g_main_loop_new(nullptr, FALSE);
+ }
+
+ ~Tester() { g_main_loop_unref(loop_); }
+
+ void Run(int argc, char** argv) {
+ options_ = message_port::benchmark::Options::Parse(argc, argv);
+ if (!options_) {
+ std::cerr << "options is unllptr" << std::endl;
+ return;
+ }
+
+ if (options_->ShouldPrintTime()) PrintStartTime();
+
+ printf("%15s\t%15s\t%15s\t\t%15s\t\t%15s\n", "Iterations", "Data size",
+ "Time", "Throughput", "Latency");
+
+ try {
+ if (options_->IsAll()) {
+ DoTest(4000, 10);
+ DoTest(4000, 20);
+ DoTest(4000, 100);
+ DoTest(4000, 200);
+ DoTest(2000, 1000);
+ DoTest(2000, 2000);
+ DoTest(1000, 10000);
+ } else {
+ DoTest(options_->GetIters(), options_->GetSize());
+ }
+ } catch (...) {
+ std::cerr << "test failed" << std::endl;
+ }
+ }
+
+ private:
+ void DoTest(int iters, int size) {
+ StartTime();
+ static int g_iters;
+ static int g_iters_org;
+ static int g_size;
+
+ g_iters = iters;
+ g_iters_org = iters;
+ g_size = size;
+ port_id_ = message_port_register_local_port(
+ "TestPort",
+ [](int local_port_id, const char* remote_app_id,
+ const char* remote_port, bool trusted_remote_port, bundle* message,
+ void* user_data) {
+ auto* tester = static_cast<Tester*>(user_data);
+ g_iters--;
+ if (g_iters <= 0) {
+ g_main_loop_quit(tester->loop_);
+ tester->EndTime(g_iters_org, g_size);
+ } else {
+ tizen_base::Bundle d = {{"ITER", std::to_string(g_iters)},
+ {"DATA", std::string(g_size, 'a')}};
+ message_port_send_message("messageport.benchmark", "TestPort",
+ d.GetHandle());
+ }
+ },
+ this);
+
+ tizen_base::Bundle d = {{"ITER", std::to_string(g_iters)},
+ {"DATA", std::string(size, 'a')}};
+ message_port_send_message("messageport.benchmark", "TestPort",
+ d.GetHandle());
+ g_main_loop_run(loop_);
+ message_port_unregister_local_port(port_id_);
+ }
+
+ int FakeFunction(std::string str) { return 0; }
+
+ void StartTime() { start_ = std::chrono::system_clock::now(); }
+
+ void EndTime(int iters, int size) {
+ std::chrono::duration<double> sec =
+ std::chrono::system_clock::now() - start_;
+ double t =
+ size * static_cast<double>(iters) * 8 / sec.count() / 1024 / 1024;
+ double l = sec.count() * 1000 / iters;
+
+ printf("%10d\t%10dByte\t%15.4fs\t%15.4fMb/s\t%15.4fms\n", iters, size,
+ sec.count(), t, l);
+ }
+
+ void PrintStartTime() {
+ std::ifstream stat_file("/proc/self/stat");
+ if (!stat_file) {
+ _E("Failed to open stat");
+ return;
+ }
+
+ std::string line;
+ getline(stat_file, line);
+ std::istringstream iss(line);
+
+ std::string value;
+ int pos = 21;
+ for (int i = 0; i < pos; ++i) iss >> value;
+
+ iss >> value;
+ stat_file.close();
+
+ long start_time = std::stol(value) / sysconf(_SC_CLK_TCK);
+ time_t start_time_seconds = start_time;
+ long start_time_microseconds = (start_time - start_time_seconds) * 1000000;
+
+ std::time_t start_time_utc = std::time(nullptr) - start_time_seconds;
+ std::tm* start_time_tm = std::localtime(&start_time_utc);
+
+ char buffer[26];
+ std::strftime(buffer, sizeof(buffer), "%Y-%m %H:%M:%S", start_time_tm);
+
+ std::string result = buffer;
+ result += ".";
+ result += std::to_string(start_time_microseconds);
+ result += " UTC";
+
+ std::cout << "Program start time: [" << value << "] " << result
+ << std::endl;
+ }
+
+ private:
+ std::unique_ptr<message_port::benchmark::Options> options_;
+ std::chrono::system_clock::time_point start_;
+ int port_id_ = -1;
+ GMainLoop* loop_ = nullptr;
+};
+
+} // namespace
+
+int main(int argc, char** argv) {
+ try {
+ Tester tester;
+ tester.Run(argc, argv);
+ } catch (...) {
+ _E("Exception occurs");
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "options.hh"
+
+#include <getopt.h>
+
+#include <cstring>
+#include <iostream>
+#include <memory>
+
+namespace message_port {
+namespace benchmark {
+
+Options::Options() {
+ help_ = R"__option_cb(
+Usage:
+ message-port-benchmark [OPTION...]
+
+Help Options:
+ -h, --help Show help options
+
+Additional Options:
+ -a, --all Test pre-defined test-cases
+ -i, --interations=<Iterations> Iterations
+ -s, --size=<Data size> Data size (byte)
+ -t, --time Print starting time of this tool
+
+Application Options:
+ -v, --version Show version information
+)__option_cb";
+}
+
+void Options::PrintUsage() { std::cerr << help_ << std::endl; }
+
+void Options::PrintVersion() {
+ std::cerr << "message-port-benchmark " << FULLVER << std::endl;
+}
+
+void Options::PrintSample() {
+ std::cerr << "message-port-benchmark -i 1000 -s 10000" << std::endl;
+}
+
+std::unique_ptr<Options> Options::Parse(int argc, char** argv) {
+ bool cmd[CMD_MAX] = {
+ false,
+ };
+ bool opt[OPT_MAX] = {
+ false,
+ };
+ auto options = std::unique_ptr<Options>(new Options());
+ int option_index = 0;
+
+ struct option long_options[] = {
+ {"version", no_argument, nullptr, 'v'},
+ {"help", no_argument, nullptr, 'h'},
+ {"iterations", required_argument, nullptr, 'i'},
+ {"size", required_argument, nullptr, 's'},
+ {"all", no_argument, nullptr, 'a'},
+ {"time", no_argument, nullptr, 't'},
+ {0, 0, 0, 0}};
+
+ while (true) {
+ int c = getopt_long(argc, argv, "vhati:s:", long_options, &option_index);
+ if (c == -1) break;
+
+ switch (c) {
+ case 0:
+ break;
+
+ case 'v':
+ cmd[CMD_VERSION] = true;
+ break;
+
+ case 'h':
+ cmd[CMD_HELP] = true;
+ break;
+
+ case 'i':
+ opt[OPT_ITER] = true;
+ options->iters_ = std::stoi(optarg);
+ break;
+
+ case 's':
+ opt[OPT_SIZE] = true;
+ options->size_ = std::stoi(optarg);
+ break;
+
+ case 'a':
+ opt[OPT_ALL] = true;
+ options->is_all_ = true;
+ break;
+
+ case 't':
+ opt[OPT_TIME] = true, options->should_print_time_ = true;
+ break;
+
+ default:
+ cmd[CMD_HELP] = true;
+ }
+ }
+
+ if (cmd[CMD_VERSION]) {
+ options->PrintVersion();
+ return std::unique_ptr<Options>(nullptr);
+ }
+
+ if (cmd[CMD_HELP]) {
+ options->PrintUsage();
+ return std::unique_ptr<Options>(nullptr);
+ } else if (opt[OPT_ALL]) {
+ return options;
+ } else if (!opt[OPT_ITER] || !opt[OPT_SIZE]) {
+ options->PrintSample();
+ return std::unique_ptr<Options>(nullptr);
+ }
+
+ return options;
+}
+
+} // namespace benchmark
+} // namespace message_port
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OPTIONS_HH_
+#define OPTIONS_HH_
+
+#include <memory>
+#include <string>
+
+namespace message_port {
+namespace benchmark {
+
+class Options {
+ public:
+ Options();
+ ~Options() = default;
+
+ static std::unique_ptr<Options> Parse(int argc, char** argv);
+
+ int GetIters() const { return iters_; }
+ int GetSize() const { return size_; }
+ bool IsAll() const { return is_all_; }
+ bool ShouldPrintTime() const { return should_print_time_; }
+
+ private:
+ enum Cmd { CMD_VERSION, CMD_HELP, CMD_MAX };
+ enum Opt { OPT_ITER, OPT_SIZE, OPT_ALL, OPT_TIME, OPT_MAX };
+
+ void PrintUsage();
+ void PrintVersion();
+ void PrintSample();
+
+ private:
+ int iters_ = 0;
+ int size_ = 0;
+ std::string help_;
+ bool is_function_ = false;
+ bool is_all_ = false;
+ bool should_print_time_ = false;
+};
+
+} // namespace benchmark
+} // namespace message_port
+
+#endif // OPTIONS_HH_
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
Source1001: %{name}.manifest
+Source1002: %{name}-benchmark.manifest
BuildRequires: cmake
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(bundle)
%description unittests
unittests binary
+%package -n %{name}-benchmark
+Summary: Benchmark for message-port API
+Group: Application Framework/Testing
+Requires: %{name}
+
+%description -n %{name}-benchmark
+Benchmark for message-port API
+
%prep
%setup -q
cp %{SOURCE1001} .
+cp %{SOURCE1002} .
%build
%if 0%{?gcov:1}
%attr(0755,root,root) %{_bindir}/message-port-unit-test
%attr(0755,root,root) %{_bindir}/tizen-unittests/%{name}/run-unittest.sh
+%files -n %{name}-benchmark
+%manifest %{name}-benchmark.manifest
+%{_bindir}/%{name}-benchmark
+
%if 0%{?gcov:1}
%files gcov
%{_datadir}/gcov/*