xref: /aosp_15_r20/bionic/tests/malloc_stress_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <malloc.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
26*8d67ca89SAndroid Build Coastguard Worker 
27*8d67ca89SAndroid Build Coastguard Worker #include <thread>
28*8d67ca89SAndroid Build Coastguard Worker #include <vector>
29*8d67ca89SAndroid Build Coastguard Worker 
30*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
31*8d67ca89SAndroid Build Coastguard Worker #include <meminfo/procmeminfo.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <procinfo/process_map.h>
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker #include <log/log.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <log/log_read.h>
36*8d67ca89SAndroid Build Coastguard Worker #endif
37*8d67ca89SAndroid Build Coastguard Worker 
38*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
PrintLogStats(uint64_t & last_time)39*8d67ca89SAndroid Build Coastguard Worker static void PrintLogStats(uint64_t& last_time) {
40*8d67ca89SAndroid Build Coastguard Worker   logger_list* logger =
41*8d67ca89SAndroid Build Coastguard Worker       android_logger_list_open(android_name_to_log_id("main"), ANDROID_LOG_NONBLOCK, 0, getpid());
42*8d67ca89SAndroid Build Coastguard Worker   if (logger == nullptr) {
43*8d67ca89SAndroid Build Coastguard Worker     printf("Failed to open log for main\n");
44*8d67ca89SAndroid Build Coastguard Worker     return;
45*8d67ca89SAndroid Build Coastguard Worker   }
46*8d67ca89SAndroid Build Coastguard Worker 
47*8d67ca89SAndroid Build Coastguard Worker   uint64_t last_message_time = last_time;
48*8d67ca89SAndroid Build Coastguard Worker   while (true) {
49*8d67ca89SAndroid Build Coastguard Worker     log_msg entry;
50*8d67ca89SAndroid Build Coastguard Worker     ssize_t retval = android_logger_list_read(logger, &entry);
51*8d67ca89SAndroid Build Coastguard Worker     if (retval == 0) {
52*8d67ca89SAndroid Build Coastguard Worker       break;
53*8d67ca89SAndroid Build Coastguard Worker     }
54*8d67ca89SAndroid Build Coastguard Worker     if (retval < 0) {
55*8d67ca89SAndroid Build Coastguard Worker       if (retval == -EINTR) {
56*8d67ca89SAndroid Build Coastguard Worker         continue;
57*8d67ca89SAndroid Build Coastguard Worker       }
58*8d67ca89SAndroid Build Coastguard Worker       // EAGAIN means there is nothing left to read when ANDROID_LOG_NONBLOCK is set.
59*8d67ca89SAndroid Build Coastguard Worker       if (retval != -EAGAIN) {
60*8d67ca89SAndroid Build Coastguard Worker         printf("Failed to read log entry: %s\n", strerrordesc_np(retval));
61*8d67ca89SAndroid Build Coastguard Worker       }
62*8d67ca89SAndroid Build Coastguard Worker       break;
63*8d67ca89SAndroid Build Coastguard Worker     }
64*8d67ca89SAndroid Build Coastguard Worker     if (entry.msg() == nullptr) {
65*8d67ca89SAndroid Build Coastguard Worker       continue;
66*8d67ca89SAndroid Build Coastguard Worker     }
67*8d67ca89SAndroid Build Coastguard Worker     // Only print allocator tagged log entries.
68*8d67ca89SAndroid Build Coastguard Worker     std::string_view tag(entry.msg() + 1);
69*8d67ca89SAndroid Build Coastguard Worker     if (tag != "scudo" && tag != "jemalloc") {
70*8d67ca89SAndroid Build Coastguard Worker       continue;
71*8d67ca89SAndroid Build Coastguard Worker     }
72*8d67ca89SAndroid Build Coastguard Worker     if (entry.nsec() > last_time) {
73*8d67ca89SAndroid Build Coastguard Worker       printf("  %s\n", &tag.back() + 2);
74*8d67ca89SAndroid Build Coastguard Worker       // Only update the last time outside this loop just in case two or more
75*8d67ca89SAndroid Build Coastguard Worker       // messages have the same timestamp.
76*8d67ca89SAndroid Build Coastguard Worker       last_message_time = entry.nsec();
77*8d67ca89SAndroid Build Coastguard Worker     }
78*8d67ca89SAndroid Build Coastguard Worker   }
79*8d67ca89SAndroid Build Coastguard Worker   android_logger_list_close(logger);
80*8d67ca89SAndroid Build Coastguard Worker   last_time = last_message_time;
81*8d67ca89SAndroid Build Coastguard Worker }
82*8d67ca89SAndroid Build Coastguard Worker #endif
83*8d67ca89SAndroid Build Coastguard Worker 
TEST(malloc_stress,multiple_threads_forever)84*8d67ca89SAndroid Build Coastguard Worker TEST(malloc_stress, multiple_threads_forever) {
85*8d67ca89SAndroid Build Coastguard Worker   constexpr size_t kMaxThreads = 256;
86*8d67ca89SAndroid Build Coastguard Worker   constexpr size_t kAllocSize = 4096;
87*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
88*8d67ca89SAndroid Build Coastguard Worker   uint64_t rss_min = UINT64_MAX;
89*8d67ca89SAndroid Build Coastguard Worker   uint64_t rss_max = 0;
90*8d67ca89SAndroid Build Coastguard Worker   uint64_t vss_min = UINT64_MAX;
91*8d67ca89SAndroid Build Coastguard Worker   uint64_t vss_max = 0;
92*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
93*8d67ca89SAndroid Build Coastguard Worker #endif
94*8d67ca89SAndroid Build Coastguard Worker   uint64_t mallinfo_min = UINT64_MAX;
95*8d67ca89SAndroid Build Coastguard Worker   uint64_t mallinfo_max = 0;
96*8d67ca89SAndroid Build Coastguard Worker 
97*8d67ca89SAndroid Build Coastguard Worker   uint64_t last_message_time = 0;
98*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; ; i++) {
99*8d67ca89SAndroid Build Coastguard Worker     printf("Pass %zu\n", i);
100*8d67ca89SAndroid Build Coastguard Worker 
101*8d67ca89SAndroid Build Coastguard Worker     std::vector<std::thread*> threads;
102*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < kMaxThreads; i++) {
103*8d67ca89SAndroid Build Coastguard Worker       threads.push_back(new std::thread([]() {
104*8d67ca89SAndroid Build Coastguard Worker         void* buf = malloc(4096);
105*8d67ca89SAndroid Build Coastguard Worker         if (buf == nullptr) {
106*8d67ca89SAndroid Build Coastguard Worker           printf("Failed to allocate memory\n");
107*8d67ca89SAndroid Build Coastguard Worker           _exit(1);
108*8d67ca89SAndroid Build Coastguard Worker         }
109*8d67ca89SAndroid Build Coastguard Worker         memset(buf, 0, kAllocSize);
110*8d67ca89SAndroid Build Coastguard Worker         sleep(1);
111*8d67ca89SAndroid Build Coastguard Worker         free(buf);
112*8d67ca89SAndroid Build Coastguard Worker       }));
113*8d67ca89SAndroid Build Coastguard Worker     }
114*8d67ca89SAndroid Build Coastguard Worker 
115*8d67ca89SAndroid Build Coastguard Worker     for (auto thread : threads) {
116*8d67ca89SAndroid Build Coastguard Worker       thread->join();
117*8d67ca89SAndroid Build Coastguard Worker       delete thread;
118*8d67ca89SAndroid Build Coastguard Worker     }
119*8d67ca89SAndroid Build Coastguard Worker     threads.clear();
120*8d67ca89SAndroid Build Coastguard Worker 
121*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
122*8d67ca89SAndroid Build Coastguard Worker     android::meminfo::ProcMemInfo proc_mem(getpid());
123*8d67ca89SAndroid Build Coastguard Worker     const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
124*8d67ca89SAndroid Build Coastguard Worker     uint64_t rss_bytes = 0;
125*8d67ca89SAndroid Build Coastguard Worker     uint64_t vss_bytes = 0;
126*8d67ca89SAndroid Build Coastguard Worker     for (auto& vma : maps) {
127*8d67ca89SAndroid Build Coastguard Worker       if (vma.name == "[anon:libc_malloc]" || vma.name.starts_with("[anon:scudo:") ||
128*8d67ca89SAndroid Build Coastguard Worker           vma.name.starts_with("[anon:GWP-ASan")) {
129*8d67ca89SAndroid Build Coastguard Worker         android::meminfo::Vma update_vma(vma);
130*8d67ca89SAndroid Build Coastguard Worker         ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
131*8d67ca89SAndroid Build Coastguard Worker         rss_bytes += update_vma.usage.rss;
132*8d67ca89SAndroid Build Coastguard Worker         vss_bytes += update_vma.usage.vss;
133*8d67ca89SAndroid Build Coastguard Worker       }
134*8d67ca89SAndroid Build Coastguard Worker     }
135*8d67ca89SAndroid Build Coastguard Worker     if (rss_bytes < rss_min) {
136*8d67ca89SAndroid Build Coastguard Worker       rss_min = rss_bytes;
137*8d67ca89SAndroid Build Coastguard Worker     }
138*8d67ca89SAndroid Build Coastguard Worker     if (rss_bytes > rss_max) {
139*8d67ca89SAndroid Build Coastguard Worker       rss_max = rss_bytes;
140*8d67ca89SAndroid Build Coastguard Worker     }
141*8d67ca89SAndroid Build Coastguard Worker     if (vss_bytes < vss_min) {
142*8d67ca89SAndroid Build Coastguard Worker       vss_min = vss_bytes;
143*8d67ca89SAndroid Build Coastguard Worker     }
144*8d67ca89SAndroid Build Coastguard Worker     if (vss_bytes > vss_max) {
145*8d67ca89SAndroid Build Coastguard Worker       vss_max = vss_bytes;
146*8d67ca89SAndroid Build Coastguard Worker     }
147*8d67ca89SAndroid Build Coastguard Worker     printf("RSS %" PRIu64 " %0.2fMB\n", rss_bytes, rss_bytes / (1024.0 * 1024.0));
148*8d67ca89SAndroid Build Coastguard Worker     printf("  Min %" PRIu64 " %0.2fMB\n", rss_min, rss_min / (1024.0 * 1024.0));
149*8d67ca89SAndroid Build Coastguard Worker     printf("  Max %" PRIu64 " %0.2fMB\n", rss_max, rss_max / (1024.0 * 1024.0));
150*8d67ca89SAndroid Build Coastguard Worker     printf("VSS %" PRIu64 " %0.2f MB\n", vss_bytes, vss_bytes / (1024.0 * 1024.0));
151*8d67ca89SAndroid Build Coastguard Worker     printf("  Min %" PRIu64 " %0.2fMB\n", vss_min, vss_min / (1024.0 * 1024.0));
152*8d67ca89SAndroid Build Coastguard Worker     printf("  Max %" PRIu64 " %0.2fMB\n", vss_max, vss_max / (1024.0 * 1024.0));
153*8d67ca89SAndroid Build Coastguard Worker #endif
154*8d67ca89SAndroid Build Coastguard Worker 
155*8d67ca89SAndroid Build Coastguard Worker     size_t mallinfo_bytes = mallinfo().uordblks;
156*8d67ca89SAndroid Build Coastguard Worker     if (mallinfo_bytes < mallinfo_min) {
157*8d67ca89SAndroid Build Coastguard Worker       mallinfo_min = mallinfo_bytes;
158*8d67ca89SAndroid Build Coastguard Worker     }
159*8d67ca89SAndroid Build Coastguard Worker     if (mallinfo_bytes > mallinfo_max) {
160*8d67ca89SAndroid Build Coastguard Worker       mallinfo_max = mallinfo_bytes;
161*8d67ca89SAndroid Build Coastguard Worker     }
162*8d67ca89SAndroid Build Coastguard Worker     printf("Allocated memory %zu %0.2fMB\n", mallinfo_bytes, mallinfo_bytes / (1024.0 * 1024.0));
163*8d67ca89SAndroid Build Coastguard Worker     printf("  Min %" PRIu64 " %0.2fMB\n", mallinfo_min, mallinfo_min / (1024.0 * 1024.0));
164*8d67ca89SAndroid Build Coastguard Worker     printf("  Max %" PRIu64 " %0.2fMB\n", mallinfo_max, mallinfo_max / (1024.0 * 1024.0));
165*8d67ca89SAndroid Build Coastguard Worker 
166*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
167*8d67ca89SAndroid Build Coastguard Worker     if (((i + 1) % 100) == 0) {
168*8d67ca89SAndroid Build Coastguard Worker       // Send native allocator stats to the log
169*8d67ca89SAndroid Build Coastguard Worker       mallopt(M_LOG_STATS, 0);
170*8d67ca89SAndroid Build Coastguard Worker 
171*8d67ca89SAndroid Build Coastguard Worker       printf("Log stats:\n");
172*8d67ca89SAndroid Build Coastguard Worker       PrintLogStats(last_message_time);
173*8d67ca89SAndroid Build Coastguard Worker     }
174*8d67ca89SAndroid Build Coastguard Worker #endif
175*8d67ca89SAndroid Build Coastguard Worker   }
176*8d67ca89SAndroid Build Coastguard Worker }
177