summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao2017-12-19 17:08:19 -0600
committerJosh Gao2017-12-19 18:36:04 -0600
commita42314e43614f29fd93547a85784dc4f1975f477 (patch)
tree8d428c900b79b4c0eb7b5f4da3bab9313fbd4790 /debuggerd
parent51c2088f3be507f83c7580dd06c5e3c271116285 (diff)
downloadplatform-system-core-a42314e43614f29fd93547a85784dc4f1975f477.tar.gz
platform-system-core-a42314e43614f29fd93547a85784dc4f1975f477.tar.xz
platform-system-core-a42314e43614f29fd93547a85784dc4f1975f477.zip
debuggerd: add pause time benchmark.
Add a benchmark to measure how long we pause a process when dumping. Bug: http://b/62112103 Test: manually ran it Change-Id: Iceec2f722915b0ae26144c86dcbeb35793f963da
Diffstat (limited to 'debuggerd')
-rw-r--r--debuggerd/Android.bp10
-rw-r--r--debuggerd/debuggerd_benchmark.cpp128
2 files changed, 138 insertions, 0 deletions
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index c473e3395..7fec47dae 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -218,6 +218,16 @@ cc_test {
218 }, 218 },
219} 219}
220 220
221cc_benchmark {
222 name: "debuggerd_benchmark",
223 defaults: ["debuggerd_defaults"],
224 srcs: ["debuggerd_benchmark.cpp"],
225 shared_libs: [
226 "libbase",
227 "libdebuggerd_client",
228 ],
229}
230
221cc_binary { 231cc_binary {
222 name: "crash_dump", 232 name: "crash_dump",
223 srcs: [ 233 srcs: [
diff --git a/debuggerd/debuggerd_benchmark.cpp b/debuggerd/debuggerd_benchmark.cpp
new file mode 100644
index 000000000..37ee214d0
--- /dev/null
+++ b/debuggerd/debuggerd_benchmark.cpp
@@ -0,0 +1,128 @@
1/*
2 * Copyright 2017, 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 <err.h>
18#include <errno.h>
19#include <sched.h>
20#include <string.h>
21#include <sys/wait.h>
22#include <unistd.h>
23
24#include <chrono>
25#include <thread>
26
27#include <benchmark/benchmark.h>
28#include <debuggerd/client.h>
29
30using namespace std::chrono_literals;
31
32static_assert(std::chrono::high_resolution_clock::is_steady);
33
34enum class ThreadState { Starting, Started, Stopping };
35
36static void SetScheduler() {
37 struct sched_param param {
38 .sched_priority = 1,
39 };
40
41 if (sched_setscheduler(getpid(), SCHED_FIFO, &param) != 0) {
42 fprintf(stderr, "failed to set scheduler to SCHED_FIFO: %s", strerror(errno));
43 }
44}
45
46static std::chrono::duration<double> GetMaximumPause(std::atomic<ThreadState>& state) {
47 std::chrono::duration<double> max_diff(0);
48
49 const auto begin = std::chrono::high_resolution_clock::now();
50 auto last = begin;
51 state.store(ThreadState::Started);
52 while (state.load() != ThreadState::Stopping) {
53 auto now = std::chrono::high_resolution_clock::now();
54
55 auto diff = now - last;
56 if (diff > max_diff) {
57 max_diff = diff;
58 }
59
60 last = now;
61 }
62
63 return max_diff;
64}
65
66static void PerformDump() {
67 pid_t target = getpid();
68 pid_t forkpid = fork();
69 if (forkpid == -1) {
70 err(1, "fork failed");
71 } else if (forkpid != 0) {
72 int status;
73 pid_t pid = waitpid(forkpid, &status, 0);
74 if (pid == -1) {
75 err(1, "waitpid failed");
76 } else if (!WIFEXITED(status)) {
77 err(1, "child didn't exit");
78 } else if (WEXITSTATUS(status) != 0) {
79 errx(1, "child exited with non-zero status %d", WEXITSTATUS(status));
80 }
81 } else {
82 android::base::unique_fd output_fd(open("/dev/null", O_WRONLY | O_CLOEXEC));
83 if (output_fd == -1) {
84 err(1, "failed to open /dev/null");
85 }
86
87 if (!debuggerd_trigger_dump(target, kDebuggerdNativeBacktrace, 1000, std::move(output_fd))) {
88 errx(1, "failed to trigger dump");
89 }
90
91 _exit(0);
92 }
93}
94
95template <typename Fn>
96static void BM_maximum_pause_impl(benchmark::State& state, const Fn& function) {
97 SetScheduler();
98
99 for (auto _ : state) {
100 std::chrono::duration<double> max_pause;
101 std::atomic<ThreadState> thread_state(ThreadState::Starting);
102 auto thread = std::thread([&]() { max_pause = GetMaximumPause(thread_state); });
103
104 while (thread_state != ThreadState::Started) {
105 std::this_thread::sleep_for(1ms);
106 }
107
108 function();
109
110 thread_state = ThreadState::Stopping;
111 thread.join();
112
113 state.SetIterationTime(max_pause.count());
114 }
115}
116
117static void BM_maximum_pause_noop(benchmark::State& state) {
118 BM_maximum_pause_impl(state, []() {});
119}
120
121static void BM_maximum_pause_debuggerd(benchmark::State& state) {
122 BM_maximum_pause_impl(state, []() { PerformDump(); });
123}
124
125BENCHMARK(BM_maximum_pause_noop)->Iterations(128)->UseManualTime();
126BENCHMARK(BM_maximum_pause_debuggerd)->Iterations(128)->UseManualTime();
127
128BENCHMARK_MAIN();