1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| #include <cerrno> #include <cstdio> #include <cstdlib> #include <cstring> #include <fstream> #include <string> #include <sys/mman.h> #include <unistd.h>
namespace {
constexpr size_t kGiB = 1024ULL * 1024 * 1024;
constexpr size_t kPassCapMiB = 15872;
constexpr size_t kFailCapGiB = 16;
static long read_meminfo_kb(const char* key) { std::ifstream f("/proc/meminfo"); std::string line; while (std::getline(f, line)) { if (line.find(key) == 0) { long v = 0; sscanf(line.c_str(), "%*s %ld", &v); return v; } } return -1; }
static void probe_mmap_vs_malloc() { size_t sz = 64 * kGiB; errno = 0; void* mp = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); printf("mmap(64 GiB): %s errno=%d (%s)\n", mp == MAP_FAILED ? "FAIL" : "OK", errno, strerror(errno)); if (mp != MAP_FAILED) munmap(mp, sz);
errno = 0; void* p = malloc(sz); printf("malloc(64 GiB): %s errno=%d (%s)\n", p ? "OK" : "NULL", errno, strerror(errno)); if (p) free(p); }
static void probe_noreserve() { for (size_t gb : {16ULL, 64ULL}) { size_t sz = gb * kGiB; errno = 0; void* d = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); printf("%zu GiB default: %s errno=%d\n", gb, d == MAP_FAILED ? "FAIL" : "OK", errno); if (d != MAP_FAILED) munmap(d, sz);
errno = 0; void* n = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); printf("%zu GiB NORESERVE: %s errno=%d\n", gb, n == MAP_FAILED ? "FAIL" : "OK", errno); if (n != MAP_FAILED) munmap(n, sz); } }
static void probe_threshold() { for (int mb : {15360, 15872, 15880, 16384, 65536}) { size_t sz = static_cast<size_t>(mb) * 1024 * 1024; errno = 0; void* p = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); printf("%5d MiB: %s errno=%d\n", mb, p == MAP_FAILED ? "FAIL" : "OK", errno); if (p != MAP_FAILED) munmap(p, sz); } }
static void probe_committed() { auto kib_to_gib = [](long kib) { return static_cast<double>(kib) / (1024.0 * 1024.0); }; auto committed = []() { return read_meminfo_kb("Committed_AS:"); };
long limit = read_meminfo_kb("CommitLimit:"); printf("CommitLimit: %ld KiB (%.2f GiB)\n", limit, kib_to_gib(limit));
long c0 = committed(); size_t sz_ok = kPassCapMiB * 1024ULL * 1024; void* p_ok = mmap(NULL, sz_ok, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); long c1 = committed(); printf("mmap(15872 MiB / 15.5 GiB): %s Committed_AS %ld KiB (%.2f GiB) -> %ld KiB (%.2f GiB)\n", p_ok == MAP_FAILED ? "FAIL" : "OK", c0, kib_to_gib(c0), c1, kib_to_gib(c1)); if (p_ok != MAP_FAILED) munmap(p_ok, sz_ok);
c0 = committed(); size_t sz_fail = kFailCapGiB * kGiB; void* p_fail = mmap(NULL, sz_fail, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); c1 = committed(); printf("mmap(16384 MiB / 16 GiB): %s Committed_AS %ld KiB (%.2f GiB) -> %ld KiB (%.2f GiB)\n", p_fail == MAP_FAILED ? "FAIL" : "OK", c0, kib_to_gib(c0), c1, kib_to_gib(c1)); if (p_fail != MAP_FAILED) munmap(p_fail, sz_fail); }
}
int main(int argc, char* argv[]) { const char* mode = argc > 1 ? argv[1] : "all"; if (!strcmp(mode, "mmap") || !strcmp(mode, "all")) probe_mmap_vs_malloc(); if (!strcmp(mode, "threshold") || !strcmp(mode, "all")) probe_threshold(); if (!strcmp(mode, "commit") || !strcmp(mode, "all")) probe_committed(); if (!strcmp(mode, "noreserve") || !strcmp(mode, "all")) probe_noreserve(); return 0; }
|