From c813f1464ce8ad98d45a6a132499247251e15d96 Mon Sep 17 00:00:00 2001 From: Martin Nowack Date: Tue, 23 Feb 2016 15:29:58 +0100 Subject: Add support for tcmalloc Beside improving performance of KLEE, tcmalloc allows to track used memory correctly. If available, tcmalloc is automatically used during compile time. This can be forced to be: - disabled using --without-tcmalloc - enabled using --with-tcmalloc In the second case, configure will fail if tcmalloc is not found or usable. Both versions of tcmalloc a minimal and normal version. --- lib/Support/MemoryUsage.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Support/MemoryUsage.cpp b/lib/Support/MemoryUsage.cpp index 32a7eb3b..a9f4026d 100644 --- a/lib/Support/MemoryUsage.cpp +++ b/lib/Support/MemoryUsage.cpp @@ -11,6 +11,10 @@ #include "klee/Config/config.h" +#ifdef HAVE_GPERFTOOLS_MALLOC_EXTENSION_H +#include "gperftools/malloc_extension.h" +#endif + #ifdef HAVE_MALLINFO #include #endif @@ -21,7 +25,12 @@ using namespace klee; size_t util::GetTotalMallocUsage() { -#ifdef HAVE_MALLINFO +#ifdef HAVE_GPERFTOOLS_MALLOC_EXTENSION_H + uint64_t value; + MallocExtension::instance()->GetNumericProperty( + "generic.current_allocated_bytes", &value); + return value; +#elif HAVE_MALLINFO struct mallinfo mi = ::mallinfo(); // The malloc implementation in glibc (pmalloc2) // does not include mmap()'ed memory in mi.uordblks -- cgit 1.4.1 From b9b40354336dfac0847041119f64c8d11db8b5e3 Mon Sep 17 00:00:00 2001 From: Martin Nowack Date: Tue, 23 Feb 2016 15:30:39 +0100 Subject: Refactoring: Extract checking memory limit into own function --- lib/Core/Executor.cpp | 67 ++++++++++++++++++++++++++------------------------- lib/Core/Executor.h | 3 ++- 2 files changed, 36 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 854754b0..33cee9f9 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2437,6 +2437,39 @@ void Executor::bindModuleConstants() { } } +void Executor::checkMemoryUsage() { + if (!MaxMemory) + return; + if ((stats::instructions & 0xFFFF) == 0) { + // We need to avoid calling GetTotalMallocUsage() often because it + // is O(elts on freelist). This is really bad since we start + // to pummel the freelist once we hit the memory cap. + unsigned mbs = util::GetTotalMallocUsage() >> 20; + if (mbs > MaxMemory) { + if (mbs > MaxMemory + 100) { + // just guess at how many to kill + unsigned numStates = states.size(); + unsigned toKill = std::max(1U, numStates - numStates * MaxMemory / mbs); + klee_warning("killing %d states (over memory cap)", toKill); + std::vector arr(states.begin(), states.end()); + for (unsigned i = 0, N = arr.size(); N && i < toKill; ++i, --N) { + unsigned idx = rand() % N; + // Make two pulls to try and not hit a state that + // covered new code. + if (arr[idx]->coveredNew) + idx = rand() % N; + + std::swap(arr[idx], arr[N - 1]); + terminateStateEarly(*arr[N - 1], "Memory limit exceeded."); + } + } + atMemoryLimit = true; + } else { + atMemoryLimit = false; + } + } +} + void Executor::run(ExecutionState &initialState) { bindModuleConstants(); @@ -2522,39 +2555,7 @@ void Executor::run(ExecutionState &initialState) { executeInstruction(state, ki); processTimers(&state, MaxInstructionTime); - if (MaxMemory) { - if ((stats::instructions & 0xFFFF) == 0) { - // We need to avoid calling GetMallocUsage() often because it - // is O(elts on freelist). This is really bad since we start - // to pummel the freelist once we hit the memory cap. - unsigned mbs = util::GetTotalMallocUsage() >> 20; - if (mbs > MaxMemory) { - if (mbs > MaxMemory + 100) { - // just guess at how many to kill - unsigned numStates = states.size(); - unsigned toKill = std::max(1U, numStates - numStates*MaxMemory/mbs); - - klee_warning("killing %d states (over memory cap)", toKill); - - std::vector arr(states.begin(), states.end()); - for (unsigned i=0,N=arr.size(); N && icoveredNew) - idx = rand() % N; - - std::swap(arr[idx], arr[N-1]); - terminateStateEarly(*arr[N-1], "Memory limit exceeded."); - } - } - atMemoryLimit = true; - } else { - atMemoryLimit = false; - } - } - } + checkMemoryUsage(); updateStates(&state); } diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 919d2124..8bfa278a 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -399,7 +399,8 @@ private: void initTimers(); void processTimers(ExecutionState *current, double maxInstTime); - + void checkMemoryUsage(); + public: Executor(const InterpreterOptions &opts, InterpreterHandler *ie); virtual ~Executor(); -- cgit 1.4.1 From 4d082d995e5404de0058f6db2b008a3f830c627d Mon Sep 17 00:00:00 2001 From: Martin Nowack Date: Sun, 21 Feb 2016 10:15:08 +0000 Subject: Use klee-provided GetMallocUsage for consistency --- lib/Core/StatsTracker.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index 2e107fb3..9995b7e2 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -16,6 +16,7 @@ #include "klee/Internal/Module/KModule.h" #include "klee/Internal/Module/KInstruction.h" #include "klee/Internal/Support/ModuleUtil.h" +#include "klee/Internal/System/MemoryUsage.h" #include "klee/Internal/System/Time.h" #include "klee/Internal/Support/ErrorHandling.h" #include "klee/SolverStats.h" @@ -404,11 +405,7 @@ void StatsTracker::writeStatsLine() { << "," << numBranches << "," << util::getUserTime() << "," << executor.states.size() -#if LLVM_VERSION_CODE > LLVM_VERSION(3, 2) - << "," << sys::Process::GetMallocUsage() -#else - << "," << sys::Process::GetTotalMemoryUsage() -#endif + << "," << util::GetTotalMallocUsage() << "," << stats::queries << "," << stats::queryConstructs << "," << 0 // was numObjects -- cgit 1.4.1