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