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