2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <sys/types.h>
30 #include "BenchmarkProxy.h"
31 #include "dbus-proxy.hh"
32 #include "grpc-proxy.hh"
33 #include "log-private.hh"
38 #define SERVER_PROC_NAME "d::org.tizen.appfw.rpc_port.benchmark"
39 #define SERVER_BIN_TIDL "/usr/bin/rpc-port-benchmark-server-tidl"
40 #define SERVER_BIN_DBUS "/usr/bin/rpc-port-benchmark-server-dbus"
41 #define SERVER_BIN_GRPC "/usr/bin/rpc-port-benchmark-server-grpc"
43 namespace bp = rpc_port::BenchmarkProxy::proxy;
45 class ConnectionListener : public bp::Benchmark::IEventListener {
47 void OnConnected() override {
50 void OnDisconnected() override {
53 void OnRejected() override {
63 if (server_pid_ > 0) {
64 if (kill(server_pid_, SIGTERM) != 0) {
65 std::cerr << "kill() is failed. errno: " << errno << std::endl;
68 waitpid(server_pid_, &status, 0);
73 void Run(int argc, char** argv) {
74 options_ = rpc_port::benchmark::Options::Parse(argc, argv);
76 std::cerr << "options is unllptr" << std::endl;
80 if (options_->ShouldPrintTime()) PrintStartTime();
83 if (options_->IsDbus()) {
84 dbus_proxy_.Connect();
85 } else if (options_->IsGrpc()) {
86 grpc_proxy_.Connect();
88 std::string proc_name(SERVER_PROC_NAME);
89 if (getuid() >= 5000) proc_name = "u" + proc_name;
91 proxy_.reset(new bp::Benchmark(&listener_, proc_name.c_str()));
94 proxy_->Connect(true);
95 } catch (const bp::Exception& e) {
96 std::cerr << "Connect() failed" << std::endl;
98 } catch (const std::exception& e) {
99 std::cerr << "Connect() failed. " << e.what() << std::endl;
104 printf("%15s\t%15s\t%15s\t\t%15s\t\t%15s\n", "Iterations", "Data size",
105 "Time", "Throughput", "Latency");
108 if (options_->IsAll()) {
123 DoTest(options_->GetIters(), options_->GetSize());
125 } catch (const bp::Exception& e) {
126 std::cerr << "test failed" << std::endl;
131 void DoTest(int iters, int size) {
132 bool is_func = options_->IsFunction();
133 bool is_dbus = options_->IsDbus();
134 bool is_grpc = options_->IsGrpc();
136 if (is_dbus) dbus_proxy_.Start(getpid());
139 for (int i = 0; i < iters; i++) {
141 int ret = FakeFunction(std::string(size, 'a'));
143 std::cerr << "Invalid return" << std::endl;
151 int ret = dbus_proxy_.Test(std::string(size, 'a'));
153 std::cerr << "Invalid return" << std::endl;
161 int ret = grpc_proxy_.Test(std::string(size, 'a'));
163 std::cerr << "Invalid return" << std::endl;
170 int ret = proxy_->Test(std::string(size, 'a'));
172 std::cerr << "Invalid return" << std::endl;
176 EndTime(iters, size);
178 if (is_dbus) dbus_proxy_.Stop(getpid());
181 int FakeFunction(std::string str) {
186 start_ = std::chrono::system_clock::now();
189 void EndTime(int iters, int size) {
190 std::chrono::duration<double> sec =
191 std::chrono::system_clock::now() - start_;
192 double t = size * iters * 8 / sec.count() / 1024 / 1024;
193 double l = sec.count() * 1000 / iters;
195 printf("%10d\t%10dByte\t%15.4fs\t%15.4fMb/s\t%15.4fms\n", iters, size,
199 void ExecuteServer() {
200 bool is_dbus = options_->IsDbus();
201 bool is_grpc = options_->IsGrpc();
202 if (!is_grpc) return;
204 server_pid_ = fork();
205 if (server_pid_ == 0) {
209 char bin[] = { SERVER_BIN_DBUS };
210 char* argv[] = { bin, nullptr, nullptr };
211 ret = execv(argv[0], argv);
212 } else if (is_grpc) {
213 char bin[] = { SERVER_BIN_GRPC };
214 char* argv[] = { bin, nullptr, nullptr };
215 ret = execv(argv[0], argv);
217 char bin[] = { SERVER_BIN_TIDL };
218 char* argv[] = { bin, nullptr, nullptr };
219 ret = execv(argv[0], argv);
222 std::cerr << "execv() is failed. errno: " << errno << std::endl;
225 } else if (server_pid_ == -1) {
226 std::cerr << "fork() is failed. errno: " << errno << std::endl;
229 _W("benchmark server is running. pid: %d", server_pid_);
234 void PrintStartTime() {
235 std::ifstream stat_file("/proc/self/stat");
237 _E("Failed to open stat");
242 getline(stat_file, line);
243 std::istringstream iss(line);
247 for (int i = 0; i < pos; ++i) iss >> value;
252 long start_time = std::stol(value) / sysconf(_SC_CLK_TCK);
253 time_t start_time_seconds = start_time;
254 long start_time_microseconds = (start_time - start_time_seconds) * 1000000;
256 std::time_t start_time_utc = std::time(nullptr) - start_time_seconds;
257 std::tm* start_time_tm = std::localtime(&start_time_utc);
260 std::strftime(buffer, sizeof(buffer), "%Y-%m %H:%M:%S", start_time_tm);
262 std::string result = buffer;
264 result += std::to_string(start_time_microseconds);
267 std::cout << "Program start time: [" << value << "] " << result
272 std::unique_ptr<rpc_port::benchmark::Options> options_;
273 std::unique_ptr<bp::Benchmark> proxy_;
274 ConnectionListener listener_;
275 std::chrono::system_clock::time_point start_;
276 pid_t server_pid_ = -1;
277 rpc_port::benchmark::DbusProxy dbus_proxy_;
278 rpc_port::benchmark::GrpcProxy grpc_proxy_;
283 int main(int argc, char** argv) {
286 tester.Run(argc, argv);
287 } catch (const rpc_port::BenchmarkProxy::proxy::InvalidIOException& ie) {
288 _E("InvalidIOException occurs");
290 } catch (const std::bad_weak_ptr& be) {
291 _E("bad_weak_ptr occurs. error(%s)", be.what());