• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013-2014 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 #include <fcntl.h>
18 #include <inttypes.h>
19 #include <poll.h>
20 #include <sched.h>
21 #include <sys/socket.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <sys/uio.h>
25 #include <unistd.h>
26 
27 #include <unordered_set>
28 
29 #include <android-base/file.h>
30 #include <benchmark/benchmark.h>
31 #include <cutils/sockets.h>
32 #include <log/event_tag_map.h>
33 #include <private/android_logger.h>
34 
35 BENCHMARK_MAIN();
36 
37 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
38 // non-syscall libs. Since we are benchmarking, or using this in the emergency
39 // signal to stuff a terminating code, we do NOT want to introduce
40 // a syscall or usleep on EAGAIN retry.
41 #define LOG_FAILURE_RETRY(exp)                                           \
42   ({                                                                     \
43     typeof(exp) _rc;                                                     \
44     do {                                                                 \
45       _rc = (exp);                                                       \
46     } while (((_rc == -1) && ((errno == EINTR) || (errno == EAGAIN))) || \
47              (_rc == -EINTR) || (_rc == -EAGAIN));                       \
48     _rc;                                                                 \
49   })
50 
51 /*
52  *	Measure the fastest rate we can reliabley stuff print messages into
53  * the log at high pressure. Expect this to be less than double the process
54  * wakeup time (2ms?)
55  */
BM_log_maximum_retry(benchmark::State & state)56 static void BM_log_maximum_retry(benchmark::State& state) {
57   while (state.KeepRunning()) {
58     LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_INFO, "BM_log_maximum_retry", "%" PRIu64,
59                                           state.iterations()));
60   }
61 }
62 BENCHMARK(BM_log_maximum_retry);
63 
64 /*
65  *	Measure the fastest rate we can stuff print messages into the log
66  * at high pressure. Expect this to be less than double the process wakeup
67  * time (2ms?)
68  */
BM_log_maximum(benchmark::State & state)69 static void BM_log_maximum(benchmark::State& state) {
70   while (state.KeepRunning()) {
71     __android_log_print(ANDROID_LOG_INFO, "BM_log_maximum", "%" PRIu64, state.iterations());
72   }
73 }
74 BENCHMARK(BM_log_maximum);
75 
76 /*
77  *	Measure the time it takes to collect the time using
78  * discrete acquisition (state.PauseTiming() to state.ResumeTiming())
79  * under light load. Expect this to be a syscall period (2us) or
80  * data read time if zero-syscall.
81  *
82  * vdso support in the kernel and the library can allow
83  * clock_gettime to be zero-syscall, but there there does remain some
84  * benchmarking overhead to pause and resume; assumptions are both are
85  * covered.
86  */
BM_clock_overhead(benchmark::State & state)87 static void BM_clock_overhead(benchmark::State& state) {
88   while (state.KeepRunning()) {
89     state.PauseTiming();
90     state.ResumeTiming();
91   }
92 }
93 BENCHMARK(BM_clock_overhead);
94 
do_clock_overhead(benchmark::State & state,clockid_t clk_id)95 static void do_clock_overhead(benchmark::State& state, clockid_t clk_id) {
96   timespec t;
97   while (state.KeepRunning()) {
98     clock_gettime(clk_id, &t);
99   }
100 }
101 
BM_time_clock_gettime_REALTIME(benchmark::State & state)102 static void BM_time_clock_gettime_REALTIME(benchmark::State& state) {
103   do_clock_overhead(state, CLOCK_REALTIME);
104 }
105 BENCHMARK(BM_time_clock_gettime_REALTIME);
106 
BM_time_clock_gettime_MONOTONIC(benchmark::State & state)107 static void BM_time_clock_gettime_MONOTONIC(benchmark::State& state) {
108   do_clock_overhead(state, CLOCK_MONOTONIC);
109 }
110 BENCHMARK(BM_time_clock_gettime_MONOTONIC);
111 
BM_time_clock_gettime_MONOTONIC_syscall(benchmark::State & state)112 static void BM_time_clock_gettime_MONOTONIC_syscall(benchmark::State& state) {
113   timespec t;
114   while (state.KeepRunning()) {
115     syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
116   }
117 }
118 BENCHMARK(BM_time_clock_gettime_MONOTONIC_syscall);
119 
BM_time_clock_gettime_MONOTONIC_RAW(benchmark::State & state)120 static void BM_time_clock_gettime_MONOTONIC_RAW(benchmark::State& state) {
121   do_clock_overhead(state, CLOCK_MONOTONIC_RAW);
122 }
123 BENCHMARK(BM_time_clock_gettime_MONOTONIC_RAW);
124 
BM_time_clock_gettime_BOOTTIME(benchmark::State & state)125 static void BM_time_clock_gettime_BOOTTIME(benchmark::State& state) {
126   do_clock_overhead(state, CLOCK_BOOTTIME);
127 }
128 BENCHMARK(BM_time_clock_gettime_BOOTTIME);
129 
BM_time_clock_getres_MONOTONIC(benchmark::State & state)130 static void BM_time_clock_getres_MONOTONIC(benchmark::State& state) {
131   timespec t;
132   while (state.KeepRunning()) {
133     clock_getres(CLOCK_MONOTONIC, &t);
134   }
135 }
136 BENCHMARK(BM_time_clock_getres_MONOTONIC);
137 
BM_time_clock_getres_MONOTONIC_syscall(benchmark::State & state)138 static void BM_time_clock_getres_MONOTONIC_syscall(benchmark::State& state) {
139   timespec t;
140   while (state.KeepRunning()) {
141     syscall(__NR_clock_getres, CLOCK_MONOTONIC, &t);
142   }
143 }
144 BENCHMARK(BM_time_clock_getres_MONOTONIC_syscall);
145 
BM_time_time(benchmark::State & state)146 static void BM_time_time(benchmark::State& state) {
147   while (state.KeepRunning()) {
148     time_t now;
149     now = time(&now);
150   }
151 }
152 BENCHMARK(BM_time_time);
153 
154 /*
155  * Measure the time it takes to submit the android logging data to pstore
156  */
BM_pmsg_short(benchmark::State & state)157 static void BM_pmsg_short(benchmark::State& state) {
158   int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
159   if (pstore_fd < 0) {
160     state.SkipWithError("/dev/pmsg0");
161     return;
162   }
163 
164   /*
165    *  struct {
166    *      // what we provide to pstore
167    *      android_pmsg_log_header_t pmsg_header;
168    *      // what we provide to socket
169    *      android_log_header_t header;
170    *      // caller provides
171    *      union {
172    *          struct {
173    *              char     prio;
174    *              char     payload[];
175    *          } string;
176    *          struct {
177    *              uint32_t tag
178    *              char     payload[];
179    *          } binary;
180    *      };
181    *  };
182    */
183 
184   struct timespec ts;
185   clock_gettime(android_log_clockid(), &ts);
186 
187   android_pmsg_log_header_t pmsg_header;
188   pmsg_header.magic = LOGGER_MAGIC;
189   pmsg_header.len =
190       sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t);
191   pmsg_header.uid = getuid();
192   pmsg_header.pid = getpid();
193 
194   android_log_header_t header;
195   header.tid = gettid();
196   header.realtime.tv_sec = ts.tv_sec;
197   header.realtime.tv_nsec = ts.tv_nsec;
198 
199   static const unsigned nr = 1;
200   static const unsigned header_length = 2;
201   struct iovec newVec[nr + header_length];
202 
203   newVec[0].iov_base = (unsigned char*)&pmsg_header;
204   newVec[0].iov_len = sizeof(pmsg_header);
205   newVec[1].iov_base = (unsigned char*)&header;
206   newVec[1].iov_len = sizeof(header);
207 
208   android_log_event_int_t buffer;
209 
210   header.id = LOG_ID_EVENTS;
211   buffer.header.tag = 0;
212   buffer.payload.type = EVENT_TYPE_INT;
213   uint32_t snapshot = 0;
214   buffer.payload.data = snapshot;
215 
216   newVec[2].iov_base = &buffer;
217   newVec[2].iov_len = sizeof(buffer);
218 
219   while (state.KeepRunning()) {
220     ++snapshot;
221     buffer.payload.data = snapshot;
222     writev(pstore_fd, newVec, nr);
223   }
224   state.PauseTiming();
225   close(pstore_fd);
226 }
227 BENCHMARK(BM_pmsg_short);
228 
229 /*
230  * Measure the time it takes to submit the android logging data to pstore
231  * best case aligned single block.
232  */
BM_pmsg_short_aligned(benchmark::State & state)233 static void BM_pmsg_short_aligned(benchmark::State& state) {
234   int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
235   if (pstore_fd < 0) {
236     state.SkipWithError("/dev/pmsg0");
237     return;
238   }
239 
240   /*
241    *  struct {
242    *      // what we provide to pstore
243    *      android_pmsg_log_header_t pmsg_header;
244    *      // what we provide to socket
245    *      android_log_header_t header;
246    *      // caller provides
247    *      union {
248    *          struct {
249    *              char     prio;
250    *              char     payload[];
251    *          } string;
252    *          struct {
253    *              uint32_t tag
254    *              char     payload[];
255    *          } binary;
256    *      };
257    *  };
258    */
259 
260   struct timespec ts;
261   clock_gettime(android_log_clockid(), &ts);
262 
263   struct packet {
264     android_pmsg_log_header_t pmsg_header;
265     android_log_header_t header;
266     android_log_event_int_t payload;
267   };
268   alignas(8) char buf[sizeof(struct packet) + 8];
269   memset(buf, 0, sizeof(buf));
270   struct packet* buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
271   if (((uintptr_t)&buffer->pmsg_header) & 7) {
272     fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
273             state.iterations());
274   }
275 
276   buffer->pmsg_header.magic = LOGGER_MAGIC;
277   buffer->pmsg_header.len =
278       sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t);
279   buffer->pmsg_header.uid = getuid();
280   buffer->pmsg_header.pid = getpid();
281 
282   buffer->header.tid = gettid();
283   buffer->header.realtime.tv_sec = ts.tv_sec;
284   buffer->header.realtime.tv_nsec = ts.tv_nsec;
285 
286   buffer->header.id = LOG_ID_EVENTS;
287   buffer->payload.header.tag = 0;
288   buffer->payload.payload.type = EVENT_TYPE_INT;
289   uint32_t snapshot = 0;
290   buffer->payload.payload.data = snapshot;
291 
292   while (state.KeepRunning()) {
293     ++snapshot;
294     buffer->payload.payload.data = snapshot;
295     write(pstore_fd, &buffer->pmsg_header,
296           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
297               sizeof(android_log_event_int_t));
298   }
299   state.PauseTiming();
300   close(pstore_fd);
301 }
302 BENCHMARK(BM_pmsg_short_aligned);
303 
304 /*
305  * Measure the time it takes to submit the android logging data to pstore
306  * best case aligned single block.
307  */
BM_pmsg_short_unaligned1(benchmark::State & state)308 static void BM_pmsg_short_unaligned1(benchmark::State& state) {
309   int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
310   if (pstore_fd < 0) {
311     state.SkipWithError("/dev/pmsg0");
312     return;
313   }
314 
315   /*
316    *  struct {
317    *      // what we provide to pstore
318    *      android_pmsg_log_header_t pmsg_header;
319    *      // what we provide to socket
320    *      android_log_header_t header;
321    *      // caller provides
322    *      union {
323    *          struct {
324    *              char     prio;
325    *              char     payload[];
326    *          } string;
327    *          struct {
328    *              uint32_t tag
329    *              char     payload[];
330    *          } binary;
331    *      };
332    *  };
333    */
334 
335   struct timespec ts;
336   clock_gettime(android_log_clockid(), &ts);
337 
338   struct packet {
339     android_pmsg_log_header_t pmsg_header;
340     android_log_header_t header;
341     android_log_event_int_t payload;
342   };
343   alignas(8) char buf[sizeof(struct packet) + 8];
344   memset(buf, 0, sizeof(buf));
345   struct packet* buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
346   if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
347     fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
348             state.iterations());
349   }
350 
351   buffer->pmsg_header.magic = LOGGER_MAGIC;
352   buffer->pmsg_header.len =
353       sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t);
354   buffer->pmsg_header.uid = getuid();
355   buffer->pmsg_header.pid = getpid();
356 
357   buffer->header.tid = gettid();
358   buffer->header.realtime.tv_sec = ts.tv_sec;
359   buffer->header.realtime.tv_nsec = ts.tv_nsec;
360 
361   buffer->header.id = LOG_ID_EVENTS;
362   buffer->payload.header.tag = 0;
363   buffer->payload.payload.type = EVENT_TYPE_INT;
364   uint32_t snapshot = 0;
365   buffer->payload.payload.data = snapshot;
366 
367   while (state.KeepRunning()) {
368     ++snapshot;
369     buffer->payload.payload.data = snapshot;
370     write(pstore_fd, &buffer->pmsg_header,
371           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
372               sizeof(android_log_event_int_t));
373   }
374   state.PauseTiming();
375   close(pstore_fd);
376 }
377 BENCHMARK(BM_pmsg_short_unaligned1);
378 
379 /*
380  * Measure the time it takes to submit the android logging data to pstore
381  * best case aligned single block.
382  */
BM_pmsg_long_aligned(benchmark::State & state)383 static void BM_pmsg_long_aligned(benchmark::State& state) {
384   int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
385   if (pstore_fd < 0) {
386     state.SkipWithError("/dev/pmsg0");
387     return;
388   }
389 
390   /*
391    *  struct {
392    *      // what we provide to pstore
393    *      android_pmsg_log_header_t pmsg_header;
394    *      // what we provide to socket
395    *      android_log_header_t header;
396    *      // caller provides
397    *      union {
398    *          struct {
399    *              char     prio;
400    *              char     payload[];
401    *          } string;
402    *          struct {
403    *              uint32_t tag
404    *              char     payload[];
405    *          } binary;
406    *      };
407    *  };
408    */
409 
410   struct timespec ts;
411   clock_gettime(android_log_clockid(), &ts);
412 
413   struct packet {
414     android_pmsg_log_header_t pmsg_header;
415     android_log_header_t header;
416     android_log_event_int_t payload;
417   };
418   alignas(8) char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD];
419   memset(buf, 0, sizeof(buf));
420   struct packet* buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
421   if (((uintptr_t)&buffer->pmsg_header) & 7) {
422     fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
423             state.iterations());
424   }
425 
426   buffer->pmsg_header.magic = LOGGER_MAGIC;
427   buffer->pmsg_header.len =
428       sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t);
429   buffer->pmsg_header.uid = getuid();
430   buffer->pmsg_header.pid = getpid();
431 
432   buffer->header.tid = gettid();
433   buffer->header.realtime.tv_sec = ts.tv_sec;
434   buffer->header.realtime.tv_nsec = ts.tv_nsec;
435 
436   buffer->header.id = LOG_ID_EVENTS;
437   buffer->payload.header.tag = 0;
438   buffer->payload.payload.type = EVENT_TYPE_INT;
439   uint32_t snapshot = 0;
440   buffer->payload.payload.data = snapshot;
441 
442   while (state.KeepRunning()) {
443     ++snapshot;
444     buffer->payload.payload.data = snapshot;
445     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
446   }
447   state.PauseTiming();
448   close(pstore_fd);
449 }
450 BENCHMARK(BM_pmsg_long_aligned);
451 
452 /*
453  * Measure the time it takes to submit the android logging data to pstore
454  * best case aligned single block.
455  */
BM_pmsg_long_unaligned1(benchmark::State & state)456 static void BM_pmsg_long_unaligned1(benchmark::State& state) {
457   int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
458   if (pstore_fd < 0) {
459     state.SkipWithError("/dev/pmsg0");
460     return;
461   }
462 
463   /*
464    *  struct {
465    *      // what we provide to pstore
466    *      android_pmsg_log_header_t pmsg_header;
467    *      // what we provide to socket
468    *      android_log_header_t header;
469    *      // caller provides
470    *      union {
471    *          struct {
472    *              char     prio;
473    *              char     payload[];
474    *          } string;
475    *          struct {
476    *              uint32_t tag
477    *              char     payload[];
478    *          } binary;
479    *      };
480    *  };
481    */
482 
483   struct timespec ts;
484   clock_gettime(android_log_clockid(), &ts);
485 
486   struct packet {
487     android_pmsg_log_header_t pmsg_header;
488     android_log_header_t header;
489     android_log_event_int_t payload;
490   };
491   alignas(8) char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD];
492   memset(buf, 0, sizeof(buf));
493   struct packet* buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
494   if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
495     fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
496             state.iterations());
497   }
498 
499   buffer->pmsg_header.magic = LOGGER_MAGIC;
500   buffer->pmsg_header.len =
501       sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t);
502   buffer->pmsg_header.uid = getuid();
503   buffer->pmsg_header.pid = getpid();
504 
505   buffer->header.tid = gettid();
506   buffer->header.realtime.tv_sec = ts.tv_sec;
507   buffer->header.realtime.tv_nsec = ts.tv_nsec;
508 
509   buffer->header.id = LOG_ID_EVENTS;
510   buffer->payload.header.tag = 0;
511   buffer->payload.payload.type = EVENT_TYPE_INT;
512   uint32_t snapshot = 0;
513   buffer->payload.payload.data = snapshot;
514 
515   while (state.KeepRunning()) {
516     ++snapshot;
517     buffer->payload.payload.data = snapshot;
518     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
519   }
520   state.PauseTiming();
521   close(pstore_fd);
522 }
523 BENCHMARK(BM_pmsg_long_unaligned1);
524 
525 /*
526  *	Measure the time it takes to form sprintf plus time using
527  * discrete acquisition under light load. Expect this to be a syscall period
528  * (2us) or sprintf time if zero-syscall time.
529  */
530 /* helper function */
test_print(const char * fmt,...)531 static void test_print(const char* fmt, ...) {
532   va_list ap;
533   char buf[1024];
534 
535   va_start(ap, fmt);
536   vsnprintf(buf, sizeof(buf), fmt, ap);
537   va_end(ap);
538 }
539 
540 #define logd_yield() sched_yield()  // allow logd to catch up
541 #define logd_sleep() usleep(50)     // really allow logd to catch up
542 
543 /* performance test */
BM_sprintf_overhead(benchmark::State & state)544 static void BM_sprintf_overhead(benchmark::State& state) {
545   while (state.KeepRunning()) {
546     test_print("BM_sprintf_overhead:%" PRIu64, state.iterations());
547     state.PauseTiming();
548     logd_yield();
549     state.ResumeTiming();
550   }
551 }
552 BENCHMARK(BM_sprintf_overhead);
553 
554 /*
555  *	Measure the time it takes to submit the android printing logging call
556  * using discrete acquisition discrete acquisition under light load. Expect
557  * this to be a dozen or so syscall periods (40us) plus time to run *printf
558  */
BM_log_print_overhead(benchmark::State & state)559 static void BM_log_print_overhead(benchmark::State& state) {
560   while (state.KeepRunning()) {
561     __android_log_print(ANDROID_LOG_INFO, "BM_log_overhead", "%" PRIu64, state.iterations());
562     state.PauseTiming();
563     logd_yield();
564     state.ResumeTiming();
565   }
566 }
567 BENCHMARK(BM_log_print_overhead);
568 
569 /*
570  *	Measure the time it takes to submit the android event logging call
571  * using discrete acquisition under light load. Expect this to be a long path
572  * to logger to convert the unknown tag (0) into a tagname (less than 200us).
573  */
BM_log_event_overhead(benchmark::State & state)574 static void BM_log_event_overhead(benchmark::State& state) {
575   for (int64_t i = 0; state.KeepRunning(); ++i) {
576     // log tag number 0 is not known, nor shall it ever be known
577     __android_log_btwrite(0, EVENT_TYPE_LONG, &i, sizeof(i));
578     state.PauseTiming();
579     logd_yield();
580     state.ResumeTiming();
581   }
582 }
583 BENCHMARK(BM_log_event_overhead);
584 
585 /*
586  *	Measure the time it takes to submit the android event logging call
587  * using discrete acquisition under light load with a known logtag.  Expect
588  * this to be a dozen or so syscall periods (less than 40us)
589  */
BM_log_event_overhead_42(benchmark::State & state)590 static void BM_log_event_overhead_42(benchmark::State& state) {
591   for (int64_t i = 0; state.KeepRunning(); ++i) {
592     // In system/core/logcat/event.logtags:
593     // # These are used for testing, do not modify without updating
594     // # tests/framework-tests/src/android/util/EventLogFunctionalTest.java.
595     // # system/core/liblog/tests/liblog_benchmark.cpp
596     // # system/core/liblog/tests/liblog_test.cpp
597     // 42    answer (to life the universe etc|3)
598     __android_log_btwrite(42, EVENT_TYPE_LONG, &i, sizeof(i));
599     state.PauseTiming();
600     logd_yield();
601     state.ResumeTiming();
602   }
603 }
604 BENCHMARK(BM_log_event_overhead_42);
605 
606 /*
607  *	Measure the time it takes to submit the android event logging call
608  * using discrete acquisition under very-light load (<1% CPU utilization).
609  */
BM_log_light_overhead(benchmark::State & state)610 static void BM_log_light_overhead(benchmark::State& state) {
611   for (int64_t i = 0; state.KeepRunning(); ++i) {
612     __android_log_btwrite(0, EVENT_TYPE_LONG, &i, sizeof(i));
613     state.PauseTiming();
614     usleep(10000);
615     state.ResumeTiming();
616   }
617 }
618 BENCHMARK(BM_log_light_overhead);
619 
caught_latency(int)620 static void caught_latency(int /*signum*/) {
621   unsigned long long v = 0xDEADBEEFA55A5AA5ULL;
622 
623   LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
624 }
625 
caught_convert(char * cp)626 static unsigned long long caught_convert(char* cp) {
627   unsigned long long l = cp[0] & 0xFF;
628   l |= (unsigned long long)(cp[1] & 0xFF) << 8;
629   l |= (unsigned long long)(cp[2] & 0xFF) << 16;
630   l |= (unsigned long long)(cp[3] & 0xFF) << 24;
631   l |= (unsigned long long)(cp[4] & 0xFF) << 32;
632   l |= (unsigned long long)(cp[5] & 0xFF) << 40;
633   l |= (unsigned long long)(cp[6] & 0xFF) << 48;
634   l |= (unsigned long long)(cp[7] & 0xFF) << 56;
635   return l;
636 }
637 
638 static const int alarm_time = 3;
639 
640 /*
641  *	Measure the time it takes for the logd posting call to acquire the
642  * timestamp to place into the internal record.  Expect this to be less than
643  * 4 syscalls (3us).  This test uses manual injection of timing because it is
644  * comparing the timestamp at send, and then picking up the corresponding log
645  * end-to-end long path from logd to see what actual timestamp was submitted.
646  */
BM_log_latency(benchmark::State & state)647 static void BM_log_latency(benchmark::State& state) {
648   pid_t pid = getpid();
649 
650   struct logger_list* logger_list =
651       android_logger_list_open(LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 0, pid);
652 
653   if (!logger_list) {
654     fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
655     exit(EXIT_FAILURE);
656   }
657 
658   signal(SIGALRM, caught_latency);
659   alarm(alarm_time);
660 
661   for (size_t j = 0; state.KeepRunning() && j < 10 * state.iterations(); ++j) {
662   retry:  // We allow transitory errors (logd overloaded) to be retried.
663     log_time ts;
664     LOG_FAILURE_RETRY((ts = log_time(CLOCK_REALTIME),
665                        android_btWriteLog(0, EVENT_TYPE_LONG, &ts, sizeof(ts))));
666 
667     for (;;) {
668       log_msg log_msg;
669       int ret = android_logger_list_read(logger_list, &log_msg);
670       alarm(alarm_time);
671 
672       if (ret <= 0) {
673         state.SkipWithError("android_logger_list_read");
674         break;
675       }
676       if ((log_msg.entry.len != (4 + 1 + 8)) ||
677           (log_msg.id() != LOG_ID_EVENTS)) {
678         continue;
679       }
680 
681       char* eventData = log_msg.msg();
682 
683       if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
684         continue;
685       }
686       log_time tx(eventData + 4 + 1);
687       if (ts != tx) {
688         if (0xDEADBEEFA55A5AA5ULL == caught_convert(eventData + 4 + 1)) {
689           state.SkipWithError("signal");
690           break;
691         }
692         continue;
693       }
694 
695       uint64_t start = ts.nsec();
696       uint64_t end = log_msg.nsec();
697       if (end < start) goto retry;
698       state.SetIterationTime((end - start) / (double)NS_PER_SEC);
699       break;
700     }
701   }
702 
703   signal(SIGALRM, SIG_DFL);
704   alarm(0);
705 
706   android_logger_list_free(logger_list);
707 }
708 // Default gets out of hand for this test, so we set a reasonable number of
709 // iterations for a timely result.
710 BENCHMARK(BM_log_latency)->UseManualTime()->Iterations(200);
711 
caught_delay(int)712 static void caught_delay(int /*signum*/) {
713   unsigned long long v = 0xDEADBEEFA55A5AA6ULL;
714 
715   LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
716 }
717 
718 /*
719  *	Measure the time it takes for the logd posting call to make it into
720  * the logs. Expect this to be less than double the process wakeup time (2ms).
721  */
BM_log_delay(benchmark::State & state)722 static void BM_log_delay(benchmark::State& state) {
723   pid_t pid = getpid();
724 
725   struct logger_list* logger_list =
726       android_logger_list_open(LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 0, pid);
727 
728   if (!logger_list) {
729     fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
730     exit(EXIT_FAILURE);
731   }
732 
733   signal(SIGALRM, caught_delay);
734   alarm(alarm_time);
735 
736   while (state.KeepRunning()) {
737     log_time ts(CLOCK_REALTIME);
738 
739     LOG_FAILURE_RETRY(android_btWriteLog(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
740 
741     for (;;) {
742       log_msg log_msg;
743       int ret = android_logger_list_read(logger_list, &log_msg);
744       alarm(alarm_time);
745 
746       if (ret <= 0) {
747         state.SkipWithError("android_logger_list_read");
748         break;
749       }
750       if ((log_msg.entry.len != (4 + 1 + 8)) ||
751           (log_msg.id() != LOG_ID_EVENTS)) {
752         continue;
753       }
754 
755       char* eventData = log_msg.msg();
756 
757       if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
758         continue;
759       }
760       log_time tx(eventData + 4 + 1);
761       if (ts != tx) {
762         if (0xDEADBEEFA55A5AA6ULL == caught_convert(eventData + 4 + 1)) {
763           state.SkipWithError("signal");
764           break;
765         }
766         continue;
767       }
768 
769       break;
770     }
771   }
772   state.PauseTiming();
773 
774   signal(SIGALRM, SIG_DFL);
775   alarm(0);
776 
777   android_logger_list_free(logger_list);
778 }
779 BENCHMARK(BM_log_delay);
780 
781 /*
782  *	Measure the time it takes for __android_log_is_loggable.
783  */
BM_is_loggable(benchmark::State & state)784 static void BM_is_loggable(benchmark::State& state) {
785   static const char logd[] = "logd";
786 
787   while (state.KeepRunning()) {
788     __android_log_is_loggable_len(ANDROID_LOG_WARN, logd, strlen(logd),
789                                   ANDROID_LOG_VERBOSE);
790   }
791 }
792 BENCHMARK(BM_is_loggable);
793 
794 /*
795  *	Measure the time it takes for android_log_clockid.
796  */
BM_clockid(benchmark::State & state)797 static void BM_clockid(benchmark::State& state) {
798   while (state.KeepRunning()) {
799     android_log_clockid();
800   }
801 }
802 BENCHMARK(BM_clockid);
803 
804 /*
805  *	Measure the time it takes for __android_log_security.
806  */
BM_security(benchmark::State & state)807 static void BM_security(benchmark::State& state) {
808   while (state.KeepRunning()) {
809     __android_log_security();
810   }
811 }
812 BENCHMARK(BM_security);
813 
814 // Keep maps around for multiple iterations
815 static std::unordered_set<uint32_t> set;
816 static EventTagMap* map;
817 
prechargeEventMap()818 static bool prechargeEventMap() {
819   if (map) return true;
820 
821   fprintf(stderr, "Precharge: start\n");
822 
823   map = android_openEventTagMap(NULL);
824   for (uint32_t tag = 1; tag < USHRT_MAX; ++tag) {
825     size_t len;
826     if (android_lookupEventTag_len(map, &len, tag) == NULL) continue;
827     set.insert(tag);
828   }
829 
830   fprintf(stderr, "Precharge: stop %zu\n", set.size());
831 
832   return true;
833 }
834 
835 /*
836  *	Measure the time it takes for android_lookupEventTag_len
837  */
BM_lookupEventTag(benchmark::State & state)838 static void BM_lookupEventTag(benchmark::State& state) {
839   prechargeEventMap();
840 
841   std::unordered_set<uint32_t>::const_iterator it = set.begin();
842 
843   while (state.KeepRunning()) {
844     size_t len;
845     android_lookupEventTag_len(map, &len, (*it));
846     ++it;
847     if (it == set.end()) it = set.begin();
848   }
849 }
850 BENCHMARK(BM_lookupEventTag);
851 
852 /*
853  *	Measure the time it takes for android_lookupEventTag_len
854  */
855 static uint32_t notTag = 1;
856 
BM_lookupEventTag_NOT(benchmark::State & state)857 static void BM_lookupEventTag_NOT(benchmark::State& state) {
858   prechargeEventMap();
859 
860   while (set.find(notTag) != set.end()) {
861     ++notTag;
862     if (notTag >= USHRT_MAX) notTag = 1;
863   }
864 
865   while (state.KeepRunning()) {
866     size_t len;
867     android_lookupEventTag_len(map, &len, notTag);
868   }
869 
870   ++notTag;
871   if (notTag >= USHRT_MAX) notTag = 1;
872 }
873 BENCHMARK(BM_lookupEventTag_NOT);
874 
875 /*
876  *	Measure the time it takes for android_lookupEventFormat_len
877  */
BM_lookupEventFormat(benchmark::State & state)878 static void BM_lookupEventFormat(benchmark::State& state) {
879   prechargeEventMap();
880 
881   std::unordered_set<uint32_t>::const_iterator it = set.begin();
882 
883   while (state.KeepRunning()) {
884     size_t len;
885     android_lookupEventFormat_len(map, &len, (*it));
886     ++it;
887     if (it == set.end()) it = set.begin();
888   }
889 }
890 BENCHMARK(BM_lookupEventFormat);
891 
892 /*
893  *	Measure the time it takes for android_lookupEventTagNum plus above
894  */
BM_lookupEventTagNum(benchmark::State & state)895 static void BM_lookupEventTagNum(benchmark::State& state) {
896   prechargeEventMap();
897 
898   std::unordered_set<uint32_t>::const_iterator it = set.begin();
899 
900   while (state.KeepRunning()) {
901     size_t len;
902     const char* name = android_lookupEventTag_len(map, &len, (*it));
903     std::string Name(name, len);
904     const char* format = android_lookupEventFormat_len(map, &len, (*it));
905     std::string Format(format, len);
906     state.ResumeTiming();
907     android_lookupEventTagNum(map, Name.c_str(), Format.c_str(),
908                               ANDROID_LOG_UNKNOWN);
909     state.PauseTiming();
910     ++it;
911     if (it == set.end()) it = set.begin();
912   }
913 }
914 BENCHMARK(BM_lookupEventTagNum);
915 
916 // Must be functionally identical to liblog internal SendLogdControlMessage()
send_to_control(char * buf,size_t len)917 static void send_to_control(char* buf, size_t len) {
918   int sock =
919       socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM | SOCK_CLOEXEC);
920   if (sock < 0) return;
921   size_t writeLen = strlen(buf) + 1;
922 
923   ssize_t ret = TEMP_FAILURE_RETRY(write(sock, buf, writeLen));
924   if (ret <= 0) {
925     close(sock);
926     return;
927   }
928   while ((ret = read(sock, buf, len)) > 0) {
929     if (((size_t)ret == len) || (len < PAGE_SIZE)) {
930       break;
931     }
932     len -= ret;
933     buf += ret;
934 
935     struct pollfd p = {.fd = sock, .events = POLLIN, .revents = 0 };
936 
937     ret = poll(&p, 1, 20);
938     if ((ret <= 0) || !(p.revents & POLLIN)) {
939       break;
940     }
941   }
942   close(sock);
943 }
944 
BM_lookupEventTagNum_logd_new(benchmark::State & state)945 static void BM_lookupEventTagNum_logd_new(benchmark::State& state) {
946   fprintf(stderr,
947           "WARNING: "
948           "This test can cause logd to grow in size and hit DOS limiter\n");
949   // Make copies
950   static const char empty_event_log_tags[] = "# content owned by logd\n";
951   static const char dev_event_log_tags_path[] = "/dev/event-log-tags";
952   std::string dev_event_log_tags;
953   if (android::base::ReadFileToString(dev_event_log_tags_path,
954                                       &dev_event_log_tags) &&
955       (dev_event_log_tags.length() == 0)) {
956     dev_event_log_tags = empty_event_log_tags;
957   }
958   static const char data_event_log_tags_path[] =
959       "/data/misc/logd/event-log-tags";
960   std::string data_event_log_tags;
961   if (android::base::ReadFileToString(data_event_log_tags_path,
962                                       &data_event_log_tags) &&
963       (data_event_log_tags.length() == 0)) {
964     data_event_log_tags = empty_event_log_tags;
965   }
966 
967   while (state.KeepRunning()) {
968     char buffer[256];
969     memset(buffer, 0, sizeof(buffer));
970     log_time now(CLOCK_MONOTONIC);
971     char name[64];
972     snprintf(name, sizeof(name), "a%" PRIu64, now.nsec());
973     snprintf(buffer, sizeof(buffer), "getEventTag name=%s format=\"(new|1)\"",
974              name);
975     state.ResumeTiming();
976     send_to_control(buffer, sizeof(buffer));
977     state.PauseTiming();
978   }
979 
980   // Restore copies (logd still know about them, until crash or reboot)
981   if (dev_event_log_tags.length() &&
982       !android::base::WriteStringToFile(dev_event_log_tags,
983                                         dev_event_log_tags_path)) {
984     fprintf(stderr,
985             "WARNING: "
986             "failed to restore %s\n",
987             dev_event_log_tags_path);
988   }
989   if (data_event_log_tags.length() &&
990       !android::base::WriteStringToFile(data_event_log_tags,
991                                         data_event_log_tags_path)) {
992     fprintf(stderr,
993             "WARNING: "
994             "failed to restore %s\n",
995             data_event_log_tags_path);
996   }
997   fprintf(stderr,
998           "WARNING: "
999           "Restarting logd to make it forget what we just did\n");
1000   system("stop logd ; start logd");
1001 }
1002 BENCHMARK(BM_lookupEventTagNum_logd_new);
1003 
BM_lookupEventTagNum_logd_existing(benchmark::State & state)1004 static void BM_lookupEventTagNum_logd_existing(benchmark::State& state) {
1005   prechargeEventMap();
1006 
1007   std::unordered_set<uint32_t>::const_iterator it = set.begin();
1008 
1009   while (state.KeepRunning()) {
1010     size_t len;
1011     const char* name = android_lookupEventTag_len(map, &len, (*it));
1012     std::string Name(name, len);
1013     const char* format = android_lookupEventFormat_len(map, &len, (*it));
1014     std::string Format(format, len);
1015 
1016     char buffer[256];
1017     snprintf(buffer, sizeof(buffer), "getEventTag name=%s format=\"%s\"",
1018              Name.c_str(), Format.c_str());
1019 
1020     state.ResumeTiming();
1021     send_to_control(buffer, sizeof(buffer));
1022     state.PauseTiming();
1023     ++it;
1024     if (it == set.end()) it = set.begin();
1025   }
1026 }
1027 BENCHMARK(BM_lookupEventTagNum_logd_existing);
1028