Java 从Drool的工作内存中删除事实后堆大小没有减小
我正在创建并插入相当轻的人物对象,这些对象在Drool的工作记忆中只有一个字段年龄。但即使在删除事实之后,堆大小也没有减少。示例代码-使用maven的Drools 6.0.0.CR5Java 从Drool的工作内存中删除事实后堆大小没有减小,java,memory-management,memory-leaks,heap,drools,Java,Memory Management,Memory Leaks,Heap,Drools,我正在创建并插入相当轻的人物对象,这些对象在Drool的工作记忆中只有一个字段年龄。但即使在删除事实之后,堆大小也没有减少。示例代码-使用maven的Drools 6.0.0.CR5 long numOfFacts=1000000; long heapSize = Runtime.getRuntime().totalMemory(); System.out.println("Heapsize before insertion: "+heapSize); Sys
long numOfFacts=1000000;
long heapSize = Runtime.getRuntime().totalMemory();
System.out.println("Heapsize before insertion: "+heapSize);
System.out.println("Inserting objects");
ArrayList<FactHandle> factHandles = new ArrayList<FactHandle>(100);
for (int i = 0; i < numOfFacts; i++) {
Person person = new Person();
person.setAge(randomGenerator.nextInt(100));
FactHandle factHandle = wkmem.insert(person);
factHandles.add(factHandle);
}
long heapSizeAfter = Runtime.getRuntime().totalMemory();
System.out.println("Heapsize after insertion: "+heapSizeAfter);
long endTimeInsert = System.currentTimeMillis();
long elTime= endTimeInsert-startTimeInsert;
System.out.println("Time it took to insert " +numOfFacts+" objects :"+elTime+" milliseconds");
long startTime = System.currentTimeMillis();
System.out.println("Number of facts: " + wkmem.getFactCount());
wkmem.fireAllRules();
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("Time it took for evaluation: " + elapsedTime);
for(int i=0;i<numOfFacts;i++){
wkmem.retract(factHandles.get(i));
}
long heapSizeAfterRemoval = Runtime.getRuntime().totalMemory();
System.out.println("Heapsize after removal of facts: "+heapSizeAfterRemoval);
为什么治疗的次数实际上增加了 堆大小始终保持不变或增加,直到GC需要运行或决定为并发收集器运行 收集内存是昂贵的,所以它只在必要的时候做,而不是在可能的时候做 为什么治疗的次数实际上增加了 删除对象可以完成一些工作,最终可能会创建临时对象
基本上,您应该只在完全GC之后查看内存消耗,其他任何操作都是以最少的工作量为基础的。堆大小始终保持不变或增加,直到GC需要运行或决定为并发收集器运行为止 收集内存是昂贵的,所以它只在必要的时候做,而不是在可能的时候做 为什么治疗的次数实际上增加了 删除对象可以完成一些工作,最终可能会创建临时对象
基本上,你应该只在一个完整的GC之后查看内存消耗,其他任何事情都是在最不费力的基础上。
正如Peter Lawrey的回答中所提到的,在一个方法的中间你不会看到堆大小减少了。除非GC恰好在那一刻启动。为了测试这一点,您需要有一个长期运行的应用程序,并使用诸如JConsole之类的东西连接到它,或者使用某种探查器
但是,值得注意的是,收回的方式不可靠,在某些情况下会导致内存泄漏。事实是,在某些情况下,Drools会在内部生成FactHandles,因此在收回与您自己的事实句柄引用相关的所有事实之后,工作内存中可能会有更多的内容。如果我没记错的话,这些文件保留了对您的事实的引用,从而防止这些对象被垃圾收集。因此,收回所有事实句柄要安全得多:public void retractAll() {
for (FactHandle handle : ksession.getFactHandles()) {
retract(handle);
}
}
。。。或收回过滤器的所有FactHandle:
public void retractAll(ObjectFilter filter) {
for (FactHandle handle : ksession.getFactHandles(filter)) {
retract(handle);
}
}
我发现这很难。。。我的撤回代码与你最初的假设相同:正如Peter Lawrey的回答中提到的,在一个方法的中间,你不会看到堆大小减少了。除非GC恰好在那一刻启动。为了测试这一点,您需要有一个长期运行的应用程序,并使用诸如JConsole之类的东西连接到它,或者使用某种探查器 但是,值得注意的是,收回的方式不可靠,在某些情况下会导致内存泄漏。事实是,在某些情况下,Drools会在内部生成FactHandles,因此在收回与您自己的事实句柄引用相关的所有事实之后,工作内存中可能会有更多的内容。如果我没记错的话,这些文件保留了对您的事实的引用,从而防止这些对象被垃圾收集。因此,收回所有事实句柄要安全得多:
public void retractAll() {
for (FactHandle handle : ksession.getFactHandles()) {
retract(handle);
}
}
。。。或收回过滤器的所有FactHandle:
public void retractAll(ObjectFilter filter) {
for (FactHandle handle : ksession.getFactHandles(filter)) {
retract(handle);
}
}
我发现这很难。。。我的撤回代码与你最初的假设相同: 也谢谢你史蒂夫-在我找到这篇文章之前,这是我心中的一根刺…也谢谢史蒂夫-在我找到这篇文章之前,这是我心中的一根刺。。。。