binderAddInts.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. *
  16. */
  17. /*
  18. * Binder add integers benchmark (Using google-benchmark library)
  19. *
  20. */
  21. #include <cerrno>
  22. #include <grp.h>
  23. #include <iostream>
  24. #include <iomanip>
  25. #include <libgen.h>
  26. #include <time.h>
  27. #include <unistd.h>
  28. #include <sys/syscall.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/wait.h>
  32. #include <binder/IPCThreadState.h>
  33. #include <binder/ProcessState.h>
  34. #include <binder/IServiceManager.h>
  35. #include <benchmark/benchmark.h>
  36. #include <utils/Log.h>
  37. #include <testUtil.h>
  38. using namespace android;
  39. using namespace std;
  40. const int unbound = -1; // Indicator for a thread not bound to a specific CPU
  41. String16 serviceName("test.binderAddInts");
  42. struct options {
  43. int serverCPU;
  44. int clientCPU;
  45. float iterDelay; // End of iteration delay in seconds
  46. } options = { // Set defaults
  47. unbound, // Server CPU
  48. unbound, // Client CPU
  49. 0.0, // End of iteration delay
  50. };
  51. class AddIntsService : public BBinder
  52. {
  53. public:
  54. explicit AddIntsService(int cpu = unbound);
  55. virtual ~AddIntsService() {}
  56. enum command {
  57. ADD_INTS = 0x120,
  58. };
  59. virtual status_t onTransact(uint32_t code,
  60. const Parcel& data, Parcel* reply,
  61. uint32_t flags = 0);
  62. private:
  63. int cpu_;
  64. };
  65. // File scope function prototypes
  66. static bool server(void);
  67. static void BM_addInts(benchmark::State& state);
  68. static void bindCPU(unsigned int cpu);
  69. static ostream &operator<<(ostream &stream, const String16& str);
  70. static ostream &operator<<(ostream &stream, const cpu_set_t& set);
  71. static bool server(void)
  72. {
  73. int rv;
  74. // Add the service
  75. sp<ProcessState> proc(ProcessState::self());
  76. sp<IServiceManager> sm = defaultServiceManager();
  77. if ((rv = sm->addService(serviceName,
  78. new AddIntsService(options.serverCPU))) != 0) {
  79. cerr << "addService " << serviceName << " failed, rv: " << rv
  80. << " errno: " << errno << endl;
  81. return false;
  82. }
  83. // Start threads to handle server work
  84. proc->startThreadPool();
  85. return true;
  86. }
  87. static void BM_addInts(benchmark::State& state)
  88. {
  89. int rv;
  90. sp<IServiceManager> sm = defaultServiceManager();
  91. // If needed bind to client CPU
  92. if (options.clientCPU != unbound) { bindCPU(options.clientCPU); }
  93. // Attach to service
  94. sp<IBinder> binder;
  95. for (int i = 0; i < 3; i++) {
  96. binder = sm->getService(serviceName);
  97. if (binder != 0) break;
  98. cout << serviceName << " not published, waiting..." << endl;
  99. usleep(500000); // 0.5 s
  100. }
  101. if (binder == 0) {
  102. cout << serviceName << " failed to publish, aborting" << endl;
  103. return;
  104. }
  105. unsigned int iter = 0;
  106. // Perform the IPC operations in the benchmark
  107. while (state.KeepRunning()) {
  108. Parcel send, reply;
  109. // Create parcel to be sent. Will use the iteration cound
  110. // and the iteration count + 3 as the two integer values
  111. // to be sent.
  112. state.PauseTiming();
  113. int val1 = iter;
  114. int val2 = iter + 3;
  115. int expected = val1 + val2; // Expect to get the sum back
  116. send.writeInt32(val1);
  117. send.writeInt32(val2);
  118. state.ResumeTiming();
  119. // Send the parcel, while timing how long it takes for
  120. // the answer to return.
  121. if ((rv = binder->transact(AddIntsService::ADD_INTS,
  122. send, &reply)) != 0) {
  123. cerr << "binder->transact failed, rv: " << rv
  124. << " errno: " << errno << endl;
  125. exit(10);
  126. }
  127. state.PauseTiming();
  128. int result = reply.readInt32();
  129. if (result != (int) (iter + iter + 3)) {
  130. cerr << "Unexpected result for iteration " << iter << endl;
  131. cerr << " result: " << result << endl;
  132. cerr << "expected: " << expected << endl;
  133. }
  134. if (options.iterDelay > 0.0) { testDelaySpin(options.iterDelay); }
  135. state.ResumeTiming();
  136. }
  137. }
  138. BENCHMARK(BM_addInts);
  139. AddIntsService::AddIntsService(int cpu): cpu_(cpu) {
  140. if (cpu != unbound) { bindCPU(cpu); }
  141. }
  142. // Server function that handles parcels received from the client
  143. status_t AddIntsService::onTransact(uint32_t code, const Parcel &data,
  144. Parcel* reply, uint32_t /* flags */) {
  145. int val1, val2;
  146. status_t rv(0);
  147. int cpu;
  148. // If server bound to a particular CPU, check that
  149. // were executing on that CPU.
  150. if (cpu_ != unbound) {
  151. cpu = sched_getcpu();
  152. if (cpu != cpu_) {
  153. cerr << "server onTransact on CPU " << cpu << " expected CPU "
  154. << cpu_ << endl;
  155. exit(20);
  156. }
  157. }
  158. // Perform the requested operation
  159. switch (code) {
  160. case ADD_INTS:
  161. val1 = data.readInt32();
  162. val2 = data.readInt32();
  163. reply->writeInt32(val1 + val2);
  164. break;
  165. default:
  166. cerr << "server onTransact unknown code, code: " << code << endl;
  167. exit(21);
  168. }
  169. return rv;
  170. }
  171. static void bindCPU(unsigned int cpu)
  172. {
  173. int rv;
  174. cpu_set_t cpuset;
  175. CPU_ZERO(&cpuset);
  176. CPU_SET(cpu, &cpuset);
  177. rv = sched_setaffinity(0, sizeof(cpuset), &cpuset);
  178. if (rv != 0) {
  179. cerr << "bindCPU failed, rv: " << rv << " errno: " << errno << endl;
  180. perror(NULL);
  181. exit(30);
  182. }
  183. }
  184. static ostream &operator<<(ostream &stream, const String16& str)
  185. {
  186. for (unsigned int n1 = 0; n1 < str.size(); n1++) {
  187. if ((str[n1] > 0x20) && (str[n1] < 0x80)) {
  188. stream << (char) str[n1];
  189. } else {
  190. stream << '~';
  191. }
  192. }
  193. return stream;
  194. }
  195. static ostream &operator<<(ostream &stream, const cpu_set_t& set)
  196. {
  197. for (unsigned int n1 = 0; n1 < CPU_SETSIZE; n1++) {
  198. if (CPU_ISSET(n1, &set)) {
  199. if (n1 != 0) { stream << ' '; }
  200. stream << n1;
  201. }
  202. }
  203. return stream;
  204. }
  205. int main(int argc, char *argv[])
  206. {
  207. int rv;
  208. ::benchmark::Initialize(&argc, argv);
  209. // Determine CPUs available for use.
  210. // This testcase limits its self to using CPUs that were
  211. // available at the start of the benchmark.
  212. cpu_set_t availCPUs;
  213. if ((rv = sched_getaffinity(0, sizeof(availCPUs), &availCPUs)) != 0) {
  214. cerr << "sched_getaffinity failure, rv: " << rv
  215. << " errno: " << errno << endl;
  216. exit(1);
  217. }
  218. // Parse command line arguments
  219. int opt;
  220. while ((opt = getopt(argc, argv, "s:c:d:?")) != -1) {
  221. char *chptr; // character pointer for command-line parsing
  222. switch (opt) {
  223. case 'c': // client CPU
  224. case 's': { // server CPU
  225. // Parse the CPU number
  226. int cpu = strtoul(optarg, &chptr, 10);
  227. if (*chptr != '\0') {
  228. cerr << "Invalid cpu specified for -" << (char) opt
  229. << " option of: " << optarg << endl;
  230. exit(2);
  231. }
  232. // Is the CPU available?
  233. if (!CPU_ISSET(cpu, &availCPUs)) {
  234. cerr << "CPU " << optarg << " not currently available" << endl;
  235. cerr << " Available CPUs: " << availCPUs << endl;
  236. exit(3);
  237. }
  238. // Record the choice
  239. *((opt == 'c') ? &options.clientCPU : &options.serverCPU) = cpu;
  240. break;
  241. }
  242. case 'd': // delay between each iteration
  243. options.iterDelay = strtod(optarg, &chptr);
  244. if ((*chptr != '\0') || (options.iterDelay < 0.0)) {
  245. cerr << "Invalid delay specified of: " << optarg << endl;
  246. exit(6);
  247. }
  248. break;
  249. case '?':
  250. default:
  251. cerr << basename(argv[0]) << " [options]" << endl;
  252. cerr << " options:" << endl;
  253. cerr << " -s cpu - server CPU number" << endl;
  254. cerr << " -c cpu - client CPU number" << endl;
  255. cerr << " -d time - delay after operation in seconds" << endl;
  256. exit(((optopt == 0) || (optopt == '?')) ? 0 : 7);
  257. }
  258. }
  259. fflush(stdout);
  260. switch (pid_t pid = fork()) {
  261. case 0: // Child
  262. ::benchmark::RunSpecifiedBenchmarks();
  263. return 0;
  264. default: // Parent
  265. if (!server()) { break; }
  266. // Wait for all children to end
  267. do {
  268. int stat;
  269. rv = wait(&stat);
  270. if ((rv == -1) && (errno == ECHILD)) { break; }
  271. if (rv == -1) {
  272. cerr << "wait failed, rv: " << rv << " errno: "
  273. << errno << endl;
  274. perror(NULL);
  275. exit(8);
  276. }
  277. } while (1);
  278. return 0;
  279. case -1: // Error
  280. exit(9);
  281. }
  282. }