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