Java 有没有一种方法可以用我的CompletableFuture代码解决这个内存泄漏问题?
在http1.1中,我们有一个服务器可以进行背压(是的,它关闭了套接字,如果我们在负载下,客户端实际上会冻结等待……这非常好)。我们在http2中也这样做,而http2规范没有在http2引擎中进行背压(即,我们不需要背压,但我们遵循规范,它还关闭插座)。当我说“关闭”时,我的意思是它取消注册,这样我们就停止读取nic,nic缓冲区填充,然后客户端nic填充,直到他冻结 无论如何,我们遇到了一个有趣的问题,并且一直在努力解决它,而不出现内存泄漏。我们最近的迭代是这样的Java 有没有一种方法可以用我的CompletableFuture代码解决这个内存泄漏问题?,java,completable-future,Java,Completable Future,在http1.1中,我们有一个服务器可以进行背压(是的,它关闭了套接字,如果我们在负载下,客户端实际上会冻结等待……这非常好)。我们在http2中也这样做,而http2规范没有在http2引擎中进行背压(即,我们不需要背压,但我们遵循规范,它还关闭插座)。当我说“关闭”时,我的意思是它取消注册,这样我们就停止读取nic,nic缓冲区填充,然后客户端nic填充,直到他冻结 无论如何,我们遇到了一个有趣的问题,并且一直在努力解决它,而不出现内存泄漏。我们最近的迭代是这样的 public Comple
public CompletableFuture<Void> runLoop(List<T> newData, Session session, Processor<T> processFunction) {
//All the below futures must be chained with previous ones in case previous ones are not
//done which will serialize it all to be in sequence
CompletableFuture<Void> future = session.getProcessFuture();
for(T data : newData) {
//VERY IMPORTANT: Writing the code like this would slam through calling process N times
//BUT it doesn't give the clients a chance to set a flag between packets
//Mainly done for exceptions and streaming so you can log exc, set a boolean so you
//don't get 100 exceptions while something is happening like socket disconnect
//In these 2 lines of code, processCorrectly is CALLED N times RIGHT NOW
//The code below this only calls them right now IF AND ONLY IF the client returns
//a completed future each time!!!
//CompletableFuture<Void> messageFuture = processFunction.process(data);
//future = future.thenCompose( f -> messageFuture);
future = future.thenCompose( voidd -> processFunction.process(data));
}
session.setProcessFuturee(future);
return future;
}
然后,我意识到如果等待我的原始代码会怎么样。这就是事情变得奇怪的地方。它只下降到196MB并保持不变。我不知道为什么,也不知道引用的是什么。我真的没有在MAT(eclipse)中看到任何东西,或者我用错了那个工具
我是否有内存泄漏?我对最后的结果感到困惑。它应该至少降低到<20MB
编辑(回答沙多夫的回答):我相信返回的未来不会与它的来源联系在一起。可以说,这是链条的“尾巴”。但事实恰恰相反,创造它的未来与之相连,因此当创造它的未来完成时,它可以解决这个未来。因此,在我看来,我每次都会在会话中发布列表的尾部(而不是创建越来越长的链)。期货的真正问题在于引用它的线程以及它是否得到了解决。这意味着唯一剩下的引用它的是解析它的匿名Runnable。一旦发生这种情况,它应该能够解决
完全的未来甚至不是内存(MAT eclipse)
天哪,又一重大发现。。如果我把这行注释掉
- future.complete(空)李>
然后,程序永远飞起来,内存在180MB和6MB之间跳跃。这方面不是很好,但你正在构建越来越大的未来,而且永远不会停止——不管列表的大小,它只会消耗越来越多的内存,永远不会释放它 您将看到您是否在测试中执行以下操作:
chain.runLoop(列表,s,p);
if(queue.size()==0){
System.out.println(“队列为空”);
s、 setProcessFuturee(CompletableFuture.completedFuture(null));
rt.gc();
}
因此,我认为您需要使用不同的工具,
CompletableFuture
可能不够强大。也许是一些成熟的反应库,比如rxjava或reactor?好的,我做了一个git推送和git提交。没有内存泄漏。现在发生的事情是,我们使劲地猛击主线程,所有线程都在累积……。当给时间来解决问题时,内存会回到6MB。这只需要很长的时间,但是日志帮助我看到了这一点,最重要的是,我错过了关键点的runtime.gc()调用
所以,有了背压,我们应该没有问题了,因为这使得所有的期货在增加负荷之前都会解决。谢谢您的尝试!我用一些似乎有用的东西编辑了这篇文章。我自己也在努力理解“锁链”。我编辑了我文章的底部以包含细节,以防你好奇。OMG。如果我注释掉future.complete(null),它“完成了未来”,那么就不会有内存问题,循环会在180MB和6MB之间反复跳转。到底发生了什么事?
public CompletableFuture<Void> runLoop(List<T> newData, Session session, Processor<T> processFunction) {
//All the below futures must be chained with previous ones in case previous ones are not
//done which will serialize it all to be in sequence
CompletableFuture<Void> future = session.getProcessFuture();
CompletableFuture<Void> newFuture = new CompletableFuture<Void>();
for(T data : newData) {
//VERY IMPORTANT: Writing the code like this would slam through calling process N times
//BUT it doesn't give the clients a chance to seet a flag between packets
//Mainly done for exceptions and streaming so you can log exc, set a boolean so you
//don't get 100 exceptions while something is happening like socket disconnect
//In these 2 lines of code, processCorrectly is CALLED N times RIGHT NOW
//The code below this only calls them right now IF AND ONLY IF the client returns
//a completed future each time!!!
//This seems to have memory issues as well....
//CompletableFuture<Void> temp = processFunction.process(data);
//future = future.thenCompose(f -> temp);
future = future.thenCompose( voidd -> processFunction.process(data));
}
future.handle((voidd, t) -> {
if(t != null) {
newFuture.completeExceptionally(t);
return 0;
}
newFuture.complete(null);
return 0;
});
//comment this out and memory leak goes away of course.......
session.setProcessFuturee(newFuture);
return newFuture;
}
future = future.thenComposeAsync( voidd -> processFunction.process(data), executor );