Christopher Ferris | ee0ce44 | 2019-10-21 12:35:05 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 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 <gtest/gtest.h> |
| 18 | |
| 19 | #include <inttypes.h> |
| 20 | #include <malloc.h> |
| 21 | #include <limits.h> |
| 22 | #include <stdint.h> |
| 23 | #include <stdio.h> |
| 24 | #include <string.h> |
| 25 | #include <unistd.h> |
| 26 | |
| 27 | #include <thread> |
| 28 | #include <vector> |
| 29 | |
| 30 | #include <android-base/strings.h> |
| 31 | #if defined(__BIONIC__) |
| 32 | #include <meminfo/procmeminfo.h> |
| 33 | #include <procinfo/process_map.h> |
| 34 | #endif |
| 35 | |
| 36 | TEST(malloc_stress, multiple_threads_forever) { |
| 37 | constexpr size_t kMaxThreads = 256; |
| 38 | constexpr size_t kAllocSize = 4096; |
| 39 | #if defined(__BIONIC__) |
| 40 | uint64_t rss_min = UINT64_MAX; |
| 41 | uint64_t rss_max = 0; |
| 42 | uint64_t vss_min = UINT64_MAX; |
| 43 | uint64_t vss_max = 0; |
| 44 | ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1)); |
| 45 | #endif |
| 46 | uint64_t mallinfo_min = UINT64_MAX; |
| 47 | uint64_t mallinfo_max = 0; |
| 48 | for (size_t i = 0; ; i++) { |
| 49 | printf("Pass %zu\n", i); |
| 50 | |
| 51 | std::vector<std::thread*> threads; |
| 52 | for (size_t i = 0; i < kMaxThreads; i++) { |
| 53 | threads.push_back(new std::thread([]() { |
| 54 | void* buf = malloc(4096); |
| 55 | if (buf == nullptr) { |
| 56 | printf("Failed to allocate memory\n"); |
| 57 | _exit(1); |
| 58 | } |
| 59 | memset(buf, 0, kAllocSize); |
| 60 | sleep(1); |
| 61 | free(buf); |
| 62 | })); |
| 63 | } |
| 64 | |
| 65 | for (auto thread : threads) { |
| 66 | thread->join(); |
| 67 | delete thread; |
| 68 | } |
| 69 | threads.clear(); |
| 70 | |
| 71 | #if defined(__BIONIC__) |
| 72 | android::meminfo::ProcMemInfo proc_mem(getpid()); |
| 73 | const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats(); |
| 74 | uint64_t rss_bytes = 0; |
| 75 | uint64_t vss_bytes = 0; |
| 76 | for (auto& vma : maps) { |
Mitch Phillips | 242387d | 2020-02-11 16:08:17 -0800 | [diff] [blame] | 77 | if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") || |
| 78 | android::base::StartsWith(vma.name, "[anon:GWP-ASan")) { |
Christopher Ferris | ee0ce44 | 2019-10-21 12:35:05 -0700 | [diff] [blame] | 79 | android::meminfo::Vma update_vma(vma); |
| 80 | ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma)); |
| 81 | rss_bytes += update_vma.usage.rss; |
| 82 | vss_bytes += update_vma.usage.vss; |
| 83 | } |
| 84 | } |
| 85 | if (rss_bytes < rss_min) { |
| 86 | rss_min = rss_bytes; |
| 87 | } |
| 88 | if (rss_bytes > rss_max) { |
| 89 | rss_max = rss_bytes; |
| 90 | } |
| 91 | if (vss_bytes < vss_min) { |
| 92 | vss_min = vss_bytes; |
| 93 | } |
| 94 | if (vss_bytes > vss_max) { |
| 95 | vss_max = vss_bytes; |
| 96 | } |
| 97 | printf("RSS %" PRIu64 " %0.2fMB\n", rss_bytes, rss_bytes / (1024.0 * 1024.0)); |
| 98 | printf(" Min %" PRIu64 " %0.2fMB\n", rss_min, rss_min / (1024.0 * 1024.0)); |
| 99 | printf(" Max %" PRIu64 " %0.2fMB\n", rss_max, rss_max / (1024.0 * 1024.0)); |
| 100 | printf("VSS %" PRIu64 " %0.2f MB\n", vss_bytes, vss_bytes / (1024.0 * 1024.0)); |
| 101 | printf(" Min %" PRIu64 " %0.2fMB\n", vss_min, vss_min / (1024.0 * 1024.0)); |
| 102 | printf(" Max %" PRIu64 " %0.2fMB\n", vss_max, vss_max / (1024.0 * 1024.0)); |
| 103 | #endif |
| 104 | |
| 105 | size_t mallinfo_bytes = mallinfo().uordblks; |
| 106 | if (mallinfo_bytes < mallinfo_min) { |
| 107 | mallinfo_min = mallinfo_bytes; |
| 108 | } |
| 109 | if (mallinfo_bytes > mallinfo_max) { |
| 110 | mallinfo_max = mallinfo_bytes; |
| 111 | } |
| 112 | printf("Allocated memory %zu %0.2fMB\n", mallinfo_bytes, mallinfo_bytes / (1024.0 * 1024.0)); |
| 113 | printf(" Min %" PRIu64 " %0.2fMB\n", mallinfo_min, mallinfo_min / (1024.0 * 1024.0)); |
| 114 | printf(" Max %" PRIu64 " %0.2fMB\n", mallinfo_max, mallinfo_max / (1024.0 * 1024.0)); |
| 115 | } |
| 116 | } |