1 // Copyright (C) 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <benchmark/benchmark.h>
16
17 #include "perfetto/heap_profile.h"
18 #include "src/profiling/memory/heap_profile_internal.h"
19
20 #include "src/profiling/memory/client.h"
21 #include "src/profiling/memory/client_api_factory.h"
22
23 namespace perfetto {
24 namespace profiling {
25
26 namespace {
GetHeapId()27 uint32_t GetHeapId() {
28 static uint32_t heap_id =
29 AHeapProfile_registerHeap(AHeapInfo_create("dev.perfetto.benchmark"));
30 return heap_id;
31 }
32
33 ClientConfiguration g_client_config;
34 int g_shmem_fd;
35
GlobalServerSocket()36 base::UnixSocketRaw& GlobalServerSocket() {
37 static base::UnixSocketRaw* srv_sock = new base::UnixSocketRaw;
38 return *srv_sock;
39 }
40
DisconnectGlobalServerSocket()41 void DisconnectGlobalServerSocket() {
42 base::UnixSocketRaw destroy;
43 std::swap(destroy, GlobalServerSocket());
44 }
45
46 } // namespace
47
48 // This is called by AHeapProfile_initSession (client_api.cc) to construct a
49 // client. The Client API requires to be linked against another compliation
50 // unit that provides this function. This way, it can be used in different
51 // circumstances (central heapprofd, fork heapprofd) and be agnostic about the
52 // details. This is is used to create a test Client here.
StartHeapprofdIfStatic()53 void StartHeapprofdIfStatic() {}
ConstructClient(UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator)54 std::shared_ptr<Client> ConstructClient(
55 UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
56 base::UnixSocketRaw cli_sock;
57 base::UnixSocketRaw& srv_sock = GlobalServerSocket();
58 std::tie(cli_sock, srv_sock) = base::UnixSocketRaw::CreatePairPosix(
59 base::SockFamily::kUnix, base::SockType::kStream);
60 auto ringbuf = SharedRingBuffer::Create(8 * 1048576);
61 ringbuf->InfiniteBufferForTesting();
62 PERFETTO_CHECK(ringbuf);
63 PERFETTO_CHECK(cli_sock);
64 PERFETTO_CHECK(srv_sock);
65 g_shmem_fd = ringbuf->fd();
66 return std::allocate_shared<Client>(unhooked_allocator, std::move(cli_sock),
67 g_client_config, std::move(*ringbuf),
68 getpid(), GetMainThreadStackRange());
69 }
70
BM_ClientApiOneTenthAllocation(benchmark::State & state)71 static void BM_ClientApiOneTenthAllocation(benchmark::State& state) {
72 const uint32_t heap_id = GetHeapId();
73
74 ClientConfiguration client_config{};
75 client_config.default_interval = 32000;
76 client_config.all_heaps = true;
77 g_client_config = client_config;
78 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
79
80 PERFETTO_CHECK(g_shmem_fd);
81 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
82
83 for (auto _ : state) {
84 AHeapProfile_reportAllocation(heap_id, 0x123, 3200);
85 }
86 DisconnectGlobalServerSocket();
87 ringbuf->SetShuttingDown();
88 }
89
90 BENCHMARK(BM_ClientApiOneTenthAllocation);
91
BM_ClientApiOneHundrethAllocation(benchmark::State & state)92 static void BM_ClientApiOneHundrethAllocation(benchmark::State& state) {
93 const uint32_t heap_id = GetHeapId();
94
95 ClientConfiguration client_config{};
96 client_config.default_interval = 32000;
97 client_config.all_heaps = true;
98 g_client_config = client_config;
99 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
100
101 PERFETTO_CHECK(g_shmem_fd);
102 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
103
104 for (auto _ : state) {
105 AHeapProfile_reportAllocation(heap_id, 0x123, 320);
106 }
107 DisconnectGlobalServerSocket();
108 ringbuf->SetShuttingDown();
109 }
110
111 BENCHMARK(BM_ClientApiOneHundrethAllocation);
112
BM_ClientApiAlmostNoAllocation(benchmark::State & state)113 static void BM_ClientApiAlmostNoAllocation(benchmark::State& state) {
114 const uint32_t heap_id = GetHeapId();
115
116 ClientConfiguration client_config{};
117 client_config.default_interval = 10000000000000000;
118 client_config.all_heaps = true;
119 g_client_config = client_config;
120 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
121
122 PERFETTO_CHECK(g_shmem_fd);
123 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
124
125 for (auto _ : state) {
126 AHeapProfile_reportAllocation(heap_id, 0x123, 1);
127 }
128 DisconnectGlobalServerSocket();
129 ringbuf->SetShuttingDown();
130 }
131
132 BENCHMARK(BM_ClientApiAlmostNoAllocation);
133
BM_ClientApiSample(benchmark::State & state)134 static void BM_ClientApiSample(benchmark::State& state) {
135 const uint32_t heap_id = GetHeapId();
136
137 ClientConfiguration client_config{};
138 client_config.default_interval = 32000;
139 client_config.all_heaps = true;
140 g_client_config = client_config;
141 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
142
143 PERFETTO_CHECK(g_shmem_fd);
144 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
145
146 for (auto _ : state) {
147 AHeapProfile_reportSample(heap_id, 0x123, 20);
148 }
149 DisconnectGlobalServerSocket();
150 ringbuf->SetShuttingDown();
151 }
152
153 BENCHMARK(BM_ClientApiSample);
154
BM_ClientApiDisabledHeapAllocation(benchmark::State & state)155 static void BM_ClientApiDisabledHeapAllocation(benchmark::State& state) {
156 const uint32_t heap_id = GetHeapId();
157
158 ClientConfiguration client_config{};
159 client_config.default_interval = 32000;
160 client_config.all_heaps = false;
161 g_client_config = client_config;
162 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
163
164 PERFETTO_CHECK(g_shmem_fd);
165 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
166
167 for (auto _ : state) {
168 AHeapProfile_reportAllocation(heap_id, 0x123, 20);
169 }
170 DisconnectGlobalServerSocket();
171 ringbuf->SetShuttingDown();
172 }
173
174 BENCHMARK(BM_ClientApiDisabledHeapAllocation);
175
BM_ClientApiDisabledHeapFree(benchmark::State & state)176 static void BM_ClientApiDisabledHeapFree(benchmark::State& state) {
177 const uint32_t heap_id = GetHeapId();
178
179 ClientConfiguration client_config{};
180 client_config.default_interval = 32000;
181 client_config.all_heaps = false;
182 g_client_config = client_config;
183 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
184
185 PERFETTO_CHECK(g_shmem_fd);
186 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
187
188 for (auto _ : state) {
189 AHeapProfile_reportFree(heap_id, 0x123);
190 }
191 DisconnectGlobalServerSocket();
192 ringbuf->SetShuttingDown();
193 }
194
195 BENCHMARK(BM_ClientApiDisabledHeapFree);
196
BM_ClientApiEnabledHeapFree(benchmark::State & state)197 static void BM_ClientApiEnabledHeapFree(benchmark::State& state) {
198 const uint32_t heap_id = GetHeapId();
199
200 ClientConfiguration client_config{};
201 client_config.default_interval = 32000;
202 client_config.all_heaps = true;
203 g_client_config = client_config;
204 PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
205
206 PERFETTO_CHECK(g_shmem_fd);
207 auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
208
209 for (auto _ : state) {
210 AHeapProfile_reportFree(heap_id, 0x123);
211 }
212 DisconnectGlobalServerSocket();
213 ringbuf->SetShuttingDown();
214 }
215
216 BENCHMARK(BM_ClientApiEnabledHeapFree);
217
BM_ClientApiMallocFree(benchmark::State & state)218 static void BM_ClientApiMallocFree(benchmark::State& state) {
219 for (auto _ : state) {
220 volatile char* x = static_cast<char*>(malloc(100));
221 if (x) {
222 x[0] = 'x';
223 free(const_cast<char*>(x));
224 }
225 }
226 }
227
228 BENCHMARK(BM_ClientApiMallocFree);
229
230 } // namespace profiling
231 } // namespace perfetto
232