如何识字调用资源密集型功能

Tom*_*Tom 0 scala

(1)我有一个资源密集型函数f,其调用导致大量内存分配。因为在f内部,将存在大量异议关系集合以构造到内存中。

(2)但是,在我的工作量中,我碰巧需要反复调用函数,例如在for循环和map函数中调用超过1K次。这样,调用f的循环会迅速关闭JVM。

for {
    calling f here
}
Run Code Online (Sandbox Code Playgroud)

为了使上述工作负载正常工作,我在调用f之前引入Thread.sleep来引入间隔以延迟f调用的每次迭代,如下所示

for {
    Thread.sleep (10)
    calling f here
}
Run Code Online (Sandbox Code Playgroud)

这个经过时间的确会减少总内存使用量,以使工作量超过大型工作量。

(3)但是,有以下已知作用:(a)增加GC的频率,(b)增加总响应时间。因此,我需要根据客户端和服务器的超时配置进行调整。(c)延迟可以线性增长,当需要增加迭代时,延迟不会扩大。(d)如果有同时请求触发上述相同工作量的请求,则其他请求将超时。

我的问题:如何从字面上调用资源密集型功能:

(A)(2)以合理的响应时间同时处理上述一个大工作量的最佳方法是什么?(B)(2)同时处理多个大型工作负载的最佳方法是什么?

sim*_*djo 5

如果f不泄漏资源,那么在单个线程中调用它1000次将不会使jvm崩溃,因为在任何给定时间它只会为一个调用分配资源。

因此,我想您要么发生内存泄漏,要么从太多不同的线程调用它。既然Thread.sleep有帮助,我敢打赌第二。但这不是一个可靠的解决方案。

要限制并发调用的数量,f可以在专用上运行它ExecutionContext

val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
..
..
Future {
   call f
}(ec)
Run Code Online (Sandbox Code Playgroud)

在的ec所有调用者之间共享实例f

increase the frequency of GC这个问题通常无法解决:无论您如何安排执行时间,都必须收集您产生的所有垃圾。但是,如果程序必须具有较低的延迟,则可以稍微使用GC设置。如果有许多线程会产生大量短寿命垃圾,则您需要更多空间来存储新垃圾,而减少长寿命垃圾。它曾经XX:NewSize设置过,但是现代垃圾收集器的工作方式可能有所不同。