• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2020-2023. All rights reserved.
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 
16 #include "sys/types.h"
17 #include "sys/stat.h"
18 #include "fcntl.h"
19 #include "sys/mman.h"
20 #include "unistd.h"
21 #include "cstdio"
22 #if defined __APPLE__
23 #include <malloc/malloc.h>
24 #else
25 #include "malloc.h"
26 #endif
27 #include "util.h"
28 
29 using namespace std;
30 
31 static const vector<int> mmapFlags = {
32     MAP_PRIVATE | MAP_ANONYMOUS,
33 #if not defined __APPLE__
34     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
35     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGE_2MB,
36     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGE_1GB,
37     MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE,
38     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE,
39     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGE_2MB | MAP_POPULATE,
40     MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGE_1GB | MAP_POPULATE,
41 #endif
42 };
43 
44 static const vector<int> msyncFlags = {
45     MS_ASYNC,
46     MS_SYNC,
47     MS_INVALIDATE,
48 };
49 
50 static const vector<int> mmapLength {
51     8,
52     16,
53     64,
54     1 * K,
55     4 * K,
56     64 * K,
57     256 * K,
58     1 * M,
59     4 * M,
60     64 * M,
61     256 * M,
62     1 * G,
63 };
64 
65 static const vector<int> mdviseType {
66     MADV_NORMAL,
67     MADV_RANDOM,
68     MADV_SEQUENTIAL,
69     MADV_WILLNEED,
70     MADV_DONTNEED,
71     MADV_FREE,
72 #if not defined __APPLE__
73     MADV_REMOVE,
74     MADV_HUGEPAGE,
75     MADV_SOFT_OFFLINE
76 #endif
77 };
78 
79 static const vector<int> mprotectLength {
80     1,
81     2,
82     4,
83     32,
84     1 * K,
85     4 * K,
86     32 * K,
87     1 * M,
88 };
89 
PrepareArgs(benchmark::internal::Benchmark * b)90 static void PrepareArgs(benchmark::internal::Benchmark* b)
91 {
92     for (auto l : mmapLength) {
93         for (auto f : mmapFlags) {
94             b->Args({l, f});
95         }
96     }
97 }
98 
PrepareArgsInMdvise(benchmark::internal::Benchmark * b)99 static void PrepareArgsInMdvise(benchmark::internal::Benchmark* b)
100 {
101     for (auto l : mmapLength) {
102         for (auto t : mdviseType) {
103             b->Args({l, t});
104         }
105     }
106 }
107 
PrepareArgsInMremap(benchmark::internal::Benchmark * b)108 static void PrepareArgsInMremap(benchmark::internal::Benchmark* b)
109 {
110     for (auto oldLength : mmapLength) {
111         for (auto newLength : mmapLength) {
112             b->Args({oldLength, newLength});
113         }
114     }
115 }
116 
PrepareArgsInMsync(benchmark::internal::Benchmark * b)117 static void PrepareArgsInMsync(benchmark::internal::Benchmark* b)
118 {
119     for (auto l : mmapLength) {
120         for (auto f : msyncFlags) {
121             b->Args({l, f});
122         }
123     }
124 }
125 
Bm_function_Mmap_anonymous(benchmark::State & state)126 static void Bm_function_Mmap_anonymous(benchmark::State &state)
127 {
128     size_t length = state.range(0);
129     int flags = state.range(1);
130     for (auto _ : state) {
131         char* mem = (char *)mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0);
132         if (mem != MAP_FAILED) {
133             benchmark::DoNotOptimize(mem);
134             state.PauseTiming();
135             munmap(mem, length);
136             state.ResumeTiming();
137         }
138     }
139     state.SetItemsProcessed(state.iterations());
140 }
141 
Bm_function_Munmap_anonymous(benchmark::State & state)142 static void Bm_function_Munmap_anonymous(benchmark::State &state)
143 {
144     size_t length = state.range(0);
145     int flags = state.range(1);
146     for (auto _ : state) {
147         state.PauseTiming();
148         char* mem = (char *)mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0);
149         state.ResumeTiming();
150         if (mem != MAP_FAILED) {
151             benchmark::DoNotOptimize(mem);
152             munmap(mem, length);
153         }
154     }
155     state.SetItemsProcessed(state.iterations());
156 }
157 
Bm_function_Mmap_fd(benchmark::State & state)158 static void Bm_function_Mmap_fd(benchmark::State &state)
159 {
160     int fd = open("/dev/zero", O_RDWR, OPEN_MODE);
161     if (fd == -1) {
162         perror("open /dev/zero failed.");
163     }
164     size_t length = state.range(0);
165     int flags = state.range(1);
166     for (auto _ : state) {
167         char* mem = (char *)mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, fd, 0);
168         if (mem != MAP_FAILED) {
169             benchmark::DoNotOptimize(mem);
170             state.PauseTiming();
171             munmap(mem, length);
172             state.ResumeTiming();
173         }
174     }
175     close(fd);
176     state.SetItemsProcessed(state.iterations());
177 }
178 
Bm_function_Munmap_fd(benchmark::State & state)179 static void Bm_function_Munmap_fd(benchmark::State &state)
180 {
181     int fd = open("/dev/zero", O_RDWR, OPEN_MODE);
182     if (fd == -1) {
183         perror("open /dev/zero failed.");
184     }
185     size_t length = state.range(0);
186     int flags = state.range(1);
187     for (auto _ : state) {
188         state.PauseTiming();
189         char* mem = (char *)mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, fd, 0);
190         state.ResumeTiming();
191         if (mem != MAP_FAILED) {
192             benchmark::DoNotOptimize(mem);
193             munmap(mem, length);
194         }
195     }
196     close(fd);
197     state.SetItemsProcessed(state.iterations());
198 }
199 
Bm_function_Madvise(benchmark::State & state)200 static void Bm_function_Madvise(benchmark::State &state)
201 {
202     size_t length = state.range(0);
203     int type = state.range(1);
204     int *addr = (int*)mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
205     for (auto _ : state) {
206         benchmark::DoNotOptimize(madvise(addr, length, type));
207     }
208     madvise(addr, length, MADV_NORMAL);
209     munmap(addr, length);
210 }
211 
Bm_function_Mremap(benchmark::State & state)212 static void Bm_function_Mremap(benchmark::State &state)
213 {
214     size_t oldLength = state.range(0);
215     size_t newLength = state.range(1);
216 
217     for (auto _ : state) {
218         state.PauseTiming();
219         void *oldAddr = mmap(nullptr, oldLength, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
220         state.ResumeTiming();
221 
222         if (oldAddr != MAP_FAILED) {
223 #if defined __APPLE__
224             void *newAddr = MAP_FAILED;
225 #else
226             void *newAddr = mremap(oldAddr, oldLength, newLength, MREMAP_MAYMOVE);
227 #endif
228             if (newAddr != MAP_FAILED) {
229                 state.PauseTiming();
230                 munmap(newAddr, newLength);
231                 state.ResumeTiming();
232             } else {
233                 perror("mmap");
234             }
235         }
236     }
237 }
238 
Bm_function_Msync(benchmark::State & state)239 static void Bm_function_Msync(benchmark::State &state)
240 {
241     size_t length = state.range(0);
242     int flags = state.range(1);
243     for (auto _ : state) {
244         state.PauseTiming();
245         char* mem = (char *)mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
246         state.ResumeTiming();
247 
248         if (mem != MAP_FAILED) {
249             msync(mem, length, flags);
250 
251             state.PauseTiming();
252             munmap(mem, length);
253             state.ResumeTiming();
254         }
255     }
256 }
257 
Bm_function_mprotect(benchmark::State & state)258 static void Bm_function_mprotect(benchmark::State &state)
259 {
260     size_t pagesize = sysconf(_SC_PAGE_SIZE);
261     size_t size = pagesize * mprotectLength[state.range(0)];
262 #if defined __APPLE__
263     void *pages;
264     posix_memalign(&pages, pagesize, size);
265 #else
266     void *pages = memalign(pagesize, size);
267 #endif
268 
269     for (auto _ : state) {
270         benchmark::DoNotOptimize(mprotect(pages, size, PROT_READ | PROT_WRITE));
271     }
272     state.SetItemsProcessed(state.iterations());
273 
274     free(pages);
275 }
276 
277 // Used to unlock some or all of a process's virtual memory
278 // allowing it to be swapped out to swap space on disk
Bm_function_Mlock_Munlock(benchmark::State & state)279 static void Bm_function_Mlock_Munlock(benchmark::State &state)
280 {
281     size_t length = state.range(0);
282     void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
283     if (addr == MAP_FAILED) {
284         perror("mmap munlock");
285     }
286 
287     for (auto _ : state) {
288         if (mlock(addr, length) != 0) {
289             perror("mlock munlock");
290         }
291 
292         if (munlock(addr, length) != 0) {
293             perror("munlock proc");
294         }
295     }
296     munmap(addr, length);
297 }
298 
299 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Mmap_anonymous, PrepareArgs);
300 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Munmap_anonymous, PrepareArgs);
301 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Mmap_fd, PrepareArgs);
302 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Munmap_fd, PrepareArgs);
303 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Madvise, PrepareArgsInMdvise);
304 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Mremap, PrepareArgsInMremap);
305 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Msync, PrepareArgsInMsync);
306 MUSL_BENCHMARK_WITH_ARG(Bm_function_mprotect, "BENCHMARK_8");
307 MUSL_BENCHMARK_WITH_ARG(Bm_function_Mlock_Munlock, "COMMON_ARGS");
308