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