Hi, I'm testing how to free memory of a JIT'd function. I thought ExecutionEngine::freeMachineCodeForFunction() and Function::eraseFromParent() would work and did a test with the following sample code. But I found that the memory usage of the process is constantly growing as the while loop goes. Could someone shed light on this please? Here is the code. int main(int argc, char **argv) { InitializeNativeTarget(); LLVMContext Context; Module *M = new Module("test", Context); ExecutionEngine* EE llvm::EngineBuilder(M).setEngineKind(EngineKind::JIT).create(); while (true) { SMDiagnostic error; ParseAssemblyString("define i32 @factorial(i32 %X) nounwind uwtable {\n" " %1 = alloca i32, align 4\n" " %2 = alloca i32, align 4\n" " store i32 %X, i32* %2, align 4\n" " %3 = load i32* %2, align 4\n" " %4 = icmp eq i32 %3, 0\n" " br i1 %4, label %5, label %6\n" "\n" "; <label>:5 ; preds = %0\n" " store i32 1, i32* %1\n" " br label %12\n" "\n" "; <label>:6 ; preds = %0\n" " %7 = load i32* %2, align 4\n" " %8 = load i32* %2, align 4\n" " %9 = sub nsw i32 %8, 1\n" " %10 = call i32 @factorial(i32 %9)\n" " %11 = mul nsw i32 %7, %10\n" " store i32 %11, i32* %1\n" " br label %12\n" "\n" "; <label>:12 ; preds = %6, %5\n" " %13 = load i32* %1\n" " ret i32 %13\n" "}\n", M, error, Context); Function *func = M->getFunction("factorial"); uintptr_t tmp = (uintptr_t)(EE->getPointerToFunction(func)); EE->freeMachineCodeForFunction(func); func->eraseFromParent(); } delete EE; llvm_shutdown(); } Thank you for any help. Naosuke -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20111229/67decb88/attachment.html>
Hi, I put the sample code and a brief analysis using Valgrind to GitHub in order to make my problem clear. https://github.com/naosuke/how-to-free-memory-of-JIT-function The Valgrind heap profiler indicates memory leaking but I don't get what is wrong with the way to free memory. If someone could please offer some advice/suggestion on this, I would really appreciate it. Best, Naosuke On Thu, Dec 29, 2011 at 6:58 PM, OKUDA Naosuke <okudanaosuke at gmail.com> wrote:> Hi, > > I'm testing how to free memory of a JIT'd function. > I thought ExecutionEngine::freeMachineCodeForFunction() and > Function::eraseFromParent() > would work and did a test with the following sample code. > But I found that the memory usage of the process is constantly growing as > the while loop goes. > Could someone shed light on this please? > > Here is the code. > > int main(int argc, char **argv) { > InitializeNativeTarget(); > > LLVMContext Context; > > Module *M = new Module("test", Context); > ExecutionEngine* EE > llvm::EngineBuilder(M).setEngineKind(EngineKind::JIT).create(); > > while (true) { > SMDiagnostic error; > ParseAssemblyString("define i32 @factorial(i32 %X) nounwind uwtable {\n" > " %1 = alloca i32, align 4\n" > " %2 = alloca i32, align 4\n" > " store i32 %X, i32* %2, align 4\n" > " %3 = load i32* %2, align 4\n" > " %4 = icmp eq i32 %3, 0\n" > " br i1 %4, label %5, label %6\n" > "\n" > "; <label>:5 ; > preds = %0\n" > " store i32 1, i32* %1\n" > " br label %12\n" > "\n" > "; <label>:6 ; > preds = %0\n" > " %7 = load i32* %2, align 4\n" > " %8 = load i32* %2, align 4\n" > " %9 = sub nsw i32 %8, 1\n" > " %10 = call i32 @factorial(i32 %9)\n" > " %11 = mul nsw i32 %7, %10\n" > " store i32 %11, i32* %1\n" > " br label %12\n" > "\n" > "; <label>:12 ; > preds = %6, %5\n" > " %13 = load i32* %1\n" > " ret i32 %13\n" > "}\n", > M, > error, > Context); > > Function *func = M->getFunction("factorial"); > uintptr_t tmp = (uintptr_t)(EE->getPointerToFunction(func)); > > EE->freeMachineCodeForFunction(func); > func->eraseFromParent(); > } > > delete EE; > > llvm_shutdown(); > } > > > Thank you for any help. > > Naosuke >
There may be another explanation, but I've seen this sort of issues before: LLVM uses several object pools (associated w/ LLVM context and JIT engine), and often objects from these pools are leaked, or the pools grow infinitely due to implementation bugs. These are not an ordinary memory leaks, as destroying the LLVM context and/or JIT engine will successfully reclaim all the memory. The problem is only visible for long-running JIT processes, which repeatedly compile. I've submitted several fixes for this in the past (against 2.6) [1], but this is very easy to regress given that valgrind memcheck will not detect this. The only way to detect is either continuously repeat compilation, and track deltas, as you've done; or tweak the source to use ordinay allocators instead of pool allocators (but this can't be done blindly, as in several cases LLVM code relies on the pool to managing the objective time lifetimes). Jose [1] I'd suggest you to try your sample against http://cgit.freedesktop.org/~jrfonseca/llvm/log/?h=backports_26 ----- Original Message -----> Hi, > > I put the sample code and a brief analysis using Valgrind to GitHub > in order to make my problem clear. > https://github.com/naosuke/how-to-free-memory-of-JIT-function > The Valgrind heap profiler indicates memory leaking but I don't get > what is wrong with the way to free memory. > > If someone could please offer some advice/suggestion on this, I would > really appreciate it. > > Best, > Naosuke > > On Thu, Dec 29, 2011 at 6:58 PM, OKUDA Naosuke > <okudanaosuke at gmail.com> wrote: > > Hi, > > > > I'm testing how to free memory of a JIT'd function. > > I thought ExecutionEngine::freeMachineCodeForFunction() and > > Function::eraseFromParent() > > would work and did a test with the following sample code. > > But I found that the memory usage of the process is constantly > > growing as > > the while loop goes. > > Could someone shed light on this please? > > > > Here is the code. > > > > int main(int argc, char **argv) { > > InitializeNativeTarget(); > > > > LLVMContext Context; > > > > Module *M = new Module("test", Context); > > ExecutionEngine* EE > > llvm::EngineBuilder(M).setEngineKind(EngineKind::JIT).create(); > > > > while (true) { > > SMDiagnostic error; > > ParseAssemblyString("define i32 @factorial(i32 %X) nounwind > > uwtable {\n" > > " %1 = alloca i32, align 4\n" > > " %2 = alloca i32, align 4\n" > > " store i32 %X, i32* %2, align 4\n" > > " %3 = load i32* %2, align 4\n" > > " %4 = icmp eq i32 %3, 0\n" > > " br i1 %4, label %5, label %6\n" > > "\n" > > "; <label>:5 > > ; > > preds = %0\n" > > " store i32 1, i32* %1\n" > > " br label %12\n" > > "\n" > > "; <label>:6 > > ; > > preds = %0\n" > > " %7 = load i32* %2, align 4\n" > > " %8 = load i32* %2, align 4\n" > > " %9 = sub nsw i32 %8, 1\n" > > " %10 = call i32 @factorial(i32 %9)\n" > > " %11 = mul nsw i32 %7, %10\n" > > " store i32 %11, i32* %1\n" > > " br label %12\n" > > "\n" > > "; <label>:12 > > ; > > preds = %6, %5\n" > > " %13 = load i32* %1\n" > > " ret i32 %13\n" > > "}\n", > > M, > > error, > > Context); > > > > Function *func = M->getFunction("factorial"); > > uintptr_t tmp = (uintptr_t)(EE->getPointerToFunction(func)); > > > > EE->freeMachineCodeForFunction(func); > > func->eraseFromParent(); > > } > > > > delete EE; > > > > llvm_shutdown(); > > } > > > > > > Thank you for any help. > > > > Naosuke > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >