From 5d72fc796f21fb9714722e0006d72213fb300688 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 18 Mar 2013 13:55:33 +0000 Subject: tsan: better memory profiler git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177286 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_platform.h | 2 +- lib/tsan/rtl/tsan_platform_linux.cc | 73 ++++++++++++++++++++++++++++++++++++- lib/tsan/rtl/tsan_rtl.cc | 20 ++++------ 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index 8a17bb9b..d6b331a7 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -132,8 +132,8 @@ static inline uptr AlternativeAddress(uptr addr) { #endif } -uptr GetShadowMemoryConsumption(); void FlushShadowMemory(); +void WriteMemoryProfile(char *buf, uptr buf_size); const char *InitializePlatform(); void FinalizePlatform(); diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index a1e25293..02a66484 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -42,8 +42,10 @@ #include #define __need_res_state #include +#include extern "C" int arch_prctl(int code, __sanitizer::uptr *addr); +extern "C" struct mallinfo __libc_mallinfo(); namespace __tsan { @@ -68,8 +70,75 @@ ScopedInRtl::~ScopedInRtl() { } #endif -uptr GetShadowMemoryConsumption() { - return 0; +static bool ishex(char c) { + return (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f'); +} + +static uptr readhex(const char *p) { + uptr v = 0; + for (; ishex(p[0]); p++) { + if (p[0] >= '0' && p[0] <= '9') + v = v * 16 + p[0] - '0'; + else + v = v * 16 + p[0] - 'a' + 10; + } + return v; +} + +static uptr readdec(const char *p) { + uptr v = 0; + for (; p[0] >= '0' && p[0] <= '9' ; p++) + v = v * 10 + p[0] - '0'; + return v; +} + +void WriteMemoryProfile(char *buf, uptr buf_size) { + char *smaps = 0; + uptr smaps_cap = 0; + uptr smaps_len = ReadFileToBuffer("/proc/self/smaps", + &smaps, &smaps_cap, 64<<20); + uptr mem[6] = {}; + uptr total = 0; + uptr start = 0; + bool file = false; + const char *pos = smaps; + while (pos < smaps + smaps_len) { + if (ishex(pos[0])) { + start = readhex(pos); + for (; *pos != '/' && *pos > '\n'; pos++) {} + file = *pos == '/'; + } else if (internal_strncmp(pos, "Rss:", 4) == 0) { + for (; *pos < '0' || *pos > '9'; pos++) {} + uptr rss = readdec(pos) * 1024; + total += rss; + start >>= 40; + if (start < 0x10) // shadow + mem[0] += rss; + else if (start >= 0x20 && start < 0x30) // compat modules + mem[file ? 1 : 2] += rss; + else if (start >= 0x7e) // modules + mem[file ? 1 : 2] += rss; + else if (start >= 0x60 && start < 0x62) // traces + mem[3] += rss; + else if (start >= 0x7d && start < 0x7e) // heap + mem[4] += rss; + else // other + mem[5] += rss; + } + while (*pos++ != '\n') {} + } + UnmapOrDie(smaps, smaps_cap); + char *buf_pos = buf; + char *buf_end = buf + buf_size; + buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos, + "RSS %zd MB: shadow:%zd file:%zd mmap:%zd trace:%zd heap:%zd other:%zd\n", + total >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20, + mem[3] >> 20, mem[4] >> 20, mem[5] >> 20); + struct mallinfo mi = __libc_mallinfo(); + buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos, + "mallinfo: arena=%d mmap=%d fordblks=%d keepcost=%d\n", + mi.arena >> 20, mi.hblkhd >> 20, mi.fordblks >> 20, mi.keepcost >> 20); } void FlushShadowMemory() { diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index c25530cb..2e9a36b9 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -93,23 +93,19 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, , tls_size(tls_size) { } -static void WriteMemoryProfile(char *buf, uptr buf_size, int num) { - uptr n_threads; - uptr n_running_threads; - ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads); - uptr threadmem = n_threads * sizeof(ThreadContext) + - n_running_threads * sizeof(ThreadState); - - internal_snprintf(buf, buf_size, "%d: thread=%zuMB(total=%d/live=%d)\n", - num, threadmem >> 20, n_threads, n_running_threads); -} - static void MemoryProfileThread(void *arg) { ScopedInRtl in_rtl; fd_t fd = (fd_t)(uptr)arg; + Context *ctx = CTX(); for (int i = 0; ; i++) { InternalScopedBuffer buf(4096); - WriteMemoryProfile(buf.data(), buf.size(), i); + uptr n_threads; + uptr n_running_threads; + ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads); + internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n", + i, n_threads, n_running_threads); + internal_write(fd, buf.data(), internal_strlen(buf.data())); + WriteMemoryProfile(buf.data(), buf.size()); internal_write(fd, buf.data(), internal_strlen(buf.data())); SleepForSeconds(1); } -- cgit v1.2.3