xref: /aosp_15_r20/system/unwinding/libunwindstack/benchmarks/remote_unwind_benchmarks.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <errno.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <stdio.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <sys/ptrace.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
22*eb293b8fSAndroid Build Coastguard Worker 
23*eb293b8fSAndroid Build Coastguard Worker #include <memory>
24*eb293b8fSAndroid Build Coastguard Worker 
25*eb293b8fSAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
26*eb293b8fSAndroid Build Coastguard Worker 
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/AndroidUnwinder.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
31*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
32*eb293b8fSAndroid Build Coastguard Worker 
33*eb293b8fSAndroid Build Coastguard Worker #include "MemoryRemote.h"
34*eb293b8fSAndroid Build Coastguard Worker #include "PidUtils.h"
35*eb293b8fSAndroid Build Coastguard Worker #include "tests/TestUtils.h"
36*eb293b8fSAndroid Build Coastguard Worker 
WaitForRemote(pid_t pid,volatile bool * ready_ptr)37*eb293b8fSAndroid Build Coastguard Worker static bool WaitForRemote(pid_t pid, volatile bool* ready_ptr) {
38*eb293b8fSAndroid Build Coastguard Worker   return unwindstack::WaitForPidState(pid, [pid, ready_ptr]() {
39*eb293b8fSAndroid Build Coastguard Worker     unwindstack::MemoryRemote memory(pid);
40*eb293b8fSAndroid Build Coastguard Worker     bool ready;
41*eb293b8fSAndroid Build Coastguard Worker     uint64_t ready_addr = reinterpret_cast<uint64_t>(ready_ptr);
42*eb293b8fSAndroid Build Coastguard Worker     if (memory.ReadFully(ready_addr, &ready, sizeof(ready)) && ready) {
43*eb293b8fSAndroid Build Coastguard Worker       return unwindstack::PID_RUN_PASS;
44*eb293b8fSAndroid Build Coastguard Worker     }
45*eb293b8fSAndroid Build Coastguard Worker     return unwindstack::PID_RUN_KEEP_GOING;
46*eb293b8fSAndroid Build Coastguard Worker   });
47*eb293b8fSAndroid Build Coastguard Worker }
48*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall6(volatile bool * ready)49*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall6(volatile bool* ready) {
50*eb293b8fSAndroid Build Coastguard Worker   *ready = true;
51*eb293b8fSAndroid Build Coastguard Worker   while (true)
52*eb293b8fSAndroid Build Coastguard Worker     ;
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall5(volatile bool * ready)55*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall5(volatile bool* ready) {
56*eb293b8fSAndroid Build Coastguard Worker   return RemoteCall6(ready);
57*eb293b8fSAndroid Build Coastguard Worker }
58*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall4(volatile bool * ready)59*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall4(volatile bool* ready) {
60*eb293b8fSAndroid Build Coastguard Worker   return RemoteCall5(ready);
61*eb293b8fSAndroid Build Coastguard Worker }
62*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall3(volatile bool * ready)63*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall3(volatile bool* ready) {
64*eb293b8fSAndroid Build Coastguard Worker   return RemoteCall4(ready);
65*eb293b8fSAndroid Build Coastguard Worker }
66*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall2(volatile bool * ready)67*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall2(volatile bool* ready) {
68*eb293b8fSAndroid Build Coastguard Worker   return RemoteCall3(ready);
69*eb293b8fSAndroid Build Coastguard Worker }
70*eb293b8fSAndroid Build Coastguard Worker 
RemoteCall1(volatile bool * ready)71*eb293b8fSAndroid Build Coastguard Worker size_t RemoteCall1(volatile bool* ready) {
72*eb293b8fSAndroid Build Coastguard Worker   return RemoteCall2(ready);
73*eb293b8fSAndroid Build Coastguard Worker }
74*eb293b8fSAndroid Build Coastguard Worker 
StartRemoteRun()75*eb293b8fSAndroid Build Coastguard Worker static pid_t StartRemoteRun() {
76*eb293b8fSAndroid Build Coastguard Worker   static volatile bool ready = false;
77*eb293b8fSAndroid Build Coastguard Worker 
78*eb293b8fSAndroid Build Coastguard Worker   pid_t pid;
79*eb293b8fSAndroid Build Coastguard Worker   if ((pid = fork()) == 0) {
80*eb293b8fSAndroid Build Coastguard Worker     RemoteCall1(&ready);
81*eb293b8fSAndroid Build Coastguard Worker     exit(0);
82*eb293b8fSAndroid Build Coastguard Worker   }
83*eb293b8fSAndroid Build Coastguard Worker   if (pid == -1) {
84*eb293b8fSAndroid Build Coastguard Worker     return -1;
85*eb293b8fSAndroid Build Coastguard Worker   }
86*eb293b8fSAndroid Build Coastguard Worker 
87*eb293b8fSAndroid Build Coastguard Worker   if (!WaitForRemote(pid, &ready)) {
88*eb293b8fSAndroid Build Coastguard Worker     kill(pid, SIGKILL);
89*eb293b8fSAndroid Build Coastguard Worker     waitpid(pid, nullptr, 0);
90*eb293b8fSAndroid Build Coastguard Worker     return -1;
91*eb293b8fSAndroid Build Coastguard Worker   }
92*eb293b8fSAndroid Build Coastguard Worker 
93*eb293b8fSAndroid Build Coastguard Worker   return pid;
94*eb293b8fSAndroid Build Coastguard Worker }
95*eb293b8fSAndroid Build Coastguard Worker 
RemoteUnwind(benchmark::State & state,bool cached)96*eb293b8fSAndroid Build Coastguard Worker static void RemoteUnwind(benchmark::State& state, bool cached) {
97*eb293b8fSAndroid Build Coastguard Worker   pid_t pid = StartRemoteRun();
98*eb293b8fSAndroid Build Coastguard Worker   if (pid == -1) {
99*eb293b8fSAndroid Build Coastguard Worker     state.SkipWithError("Failed to start remote process.");
100*eb293b8fSAndroid Build Coastguard Worker   }
101*eb293b8fSAndroid Build Coastguard Worker   unwindstack::TestScopedPidReaper reap(pid);
102*eb293b8fSAndroid Build Coastguard Worker 
103*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<unwindstack::Memory> process_memory;
104*eb293b8fSAndroid Build Coastguard Worker   if (cached) {
105*eb293b8fSAndroid Build Coastguard Worker     process_memory = unwindstack::Memory::CreateProcessMemoryCached(pid);
106*eb293b8fSAndroid Build Coastguard Worker   } else {
107*eb293b8fSAndroid Build Coastguard Worker     process_memory = unwindstack::Memory::CreateProcessMemory(pid);
108*eb293b8fSAndroid Build Coastguard Worker   }
109*eb293b8fSAndroid Build Coastguard Worker   unwindstack::RemoteMaps maps(pid);
110*eb293b8fSAndroid Build Coastguard Worker   if (!maps.Parse()) {
111*eb293b8fSAndroid Build Coastguard Worker     state.SkipWithError("Failed to parse maps.");
112*eb293b8fSAndroid Build Coastguard Worker   }
113*eb293b8fSAndroid Build Coastguard Worker 
114*eb293b8fSAndroid Build Coastguard Worker   for (const auto& _ : state) {
115*eb293b8fSAndroid Build Coastguard Worker     std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::RemoteGet(pid));
116*eb293b8fSAndroid Build Coastguard Worker     unwindstack::Unwinder unwinder(32, &maps, regs.get(), process_memory);
117*eb293b8fSAndroid Build Coastguard Worker     unwinder.Unwind();
118*eb293b8fSAndroid Build Coastguard Worker     if (unwinder.NumFrames() < 5) {
119*eb293b8fSAndroid Build Coastguard Worker       state.SkipWithError("Failed to unwind properly.");
120*eb293b8fSAndroid Build Coastguard Worker     }
121*eb293b8fSAndroid Build Coastguard Worker   }
122*eb293b8fSAndroid Build Coastguard Worker 
123*eb293b8fSAndroid Build Coastguard Worker   ptrace(PTRACE_DETACH, pid, 0, 0);
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker 
BM_remote_unwind_uncached(benchmark::State & state)126*eb293b8fSAndroid Build Coastguard Worker static void BM_remote_unwind_uncached(benchmark::State& state) {
127*eb293b8fSAndroid Build Coastguard Worker   RemoteUnwind(state, false);
128*eb293b8fSAndroid Build Coastguard Worker }
129*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_remote_unwind_uncached);
130*eb293b8fSAndroid Build Coastguard Worker 
BM_remote_unwind_cached(benchmark::State & state)131*eb293b8fSAndroid Build Coastguard Worker static void BM_remote_unwind_cached(benchmark::State& state) {
132*eb293b8fSAndroid Build Coastguard Worker   RemoteUnwind(state, true);
133*eb293b8fSAndroid Build Coastguard Worker }
134*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_remote_unwind_cached);
135*eb293b8fSAndroid Build Coastguard Worker 
RemoteAndroidUnwind(benchmark::State & state,bool cached)136*eb293b8fSAndroid Build Coastguard Worker static void RemoteAndroidUnwind(benchmark::State& state, bool cached) {
137*eb293b8fSAndroid Build Coastguard Worker   pid_t pid = StartRemoteRun();
138*eb293b8fSAndroid Build Coastguard Worker   if (pid == -1) {
139*eb293b8fSAndroid Build Coastguard Worker     state.SkipWithError("Failed to start remote process.");
140*eb293b8fSAndroid Build Coastguard Worker   }
141*eb293b8fSAndroid Build Coastguard Worker   unwindstack::TestScopedPidReaper reap(pid);
142*eb293b8fSAndroid Build Coastguard Worker 
143*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<unwindstack::Memory> process_memory;
144*eb293b8fSAndroid Build Coastguard Worker   if (cached) {
145*eb293b8fSAndroid Build Coastguard Worker     process_memory = unwindstack::Memory::CreateProcessMemoryCached(pid);
146*eb293b8fSAndroid Build Coastguard Worker   } else {
147*eb293b8fSAndroid Build Coastguard Worker     process_memory = unwindstack::Memory::CreateProcessMemory(pid);
148*eb293b8fSAndroid Build Coastguard Worker   }
149*eb293b8fSAndroid Build Coastguard Worker   unwindstack::AndroidRemoteUnwinder unwinder(pid, process_memory);
150*eb293b8fSAndroid Build Coastguard Worker   unwindstack::ErrorData error;
151*eb293b8fSAndroid Build Coastguard Worker   if (!unwinder.Initialize(error)) {
152*eb293b8fSAndroid Build Coastguard Worker     state.SkipWithError("Failed to initialize unwinder.");
153*eb293b8fSAndroid Build Coastguard Worker   }
154*eb293b8fSAndroid Build Coastguard Worker 
155*eb293b8fSAndroid Build Coastguard Worker   for (const auto& _ : state) {
156*eb293b8fSAndroid Build Coastguard Worker     unwindstack::AndroidUnwinderData data;
157*eb293b8fSAndroid Build Coastguard Worker     if (!unwinder.Unwind(data) || data.frames.size() < 5) {
158*eb293b8fSAndroid Build Coastguard Worker       state.SkipWithError("Failed to unwind properly.");
159*eb293b8fSAndroid Build Coastguard Worker     }
160*eb293b8fSAndroid Build Coastguard Worker   }
161*eb293b8fSAndroid Build Coastguard Worker 
162*eb293b8fSAndroid Build Coastguard Worker   ptrace(PTRACE_DETACH, pid, 0, 0);
163*eb293b8fSAndroid Build Coastguard Worker }
164*eb293b8fSAndroid Build Coastguard Worker 
BM_remote_android_unwind_uncached(benchmark::State & state)165*eb293b8fSAndroid Build Coastguard Worker static void BM_remote_android_unwind_uncached(benchmark::State& state) {
166*eb293b8fSAndroid Build Coastguard Worker   RemoteAndroidUnwind(state, true);
167*eb293b8fSAndroid Build Coastguard Worker }
168*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_remote_android_unwind_uncached);
169*eb293b8fSAndroid Build Coastguard Worker 
BM_remote_android_unwind_cached(benchmark::State & state)170*eb293b8fSAndroid Build Coastguard Worker static void BM_remote_android_unwind_cached(benchmark::State& state) {
171*eb293b8fSAndroid Build Coastguard Worker   RemoteAndroidUnwind(state, true);
172*eb293b8fSAndroid Build Coastguard Worker }
173*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_remote_android_unwind_cached);
174