【问题标题】:Scheduling memory-bound tasks in java在java中调度内存绑定任务
【发布时间】:2021-10-15 03:51:51
【问题描述】:

假设我有大量相互独立的内存密集型任务。具体来说,假设我可以为堆分配 30GB 的空间,并且每个任务在高峰期平均需要大约 3GB 的内存,但随着时间的推移和任务之间的变化会有所不同。这里和那里的一些任务甚至可能需要 6GB。

在这种情况下,尝试同时运行 10 个(或者甚至更多)任务似乎更有效,如果/当我们遇到内存限制时让任务等待,就像我们使用其他共享资源一样比如 I/O、特定的内存地址(通过锁访问)等等。

在 Java 中可以做到这一点吗?更普遍 在 Java 中处理内存绑定任务调度的最佳方法是什么?

一些相关问题和“未命中”

This question 询问是否可以让 java 中的线程等待内存而不是抛出 OOM 异常,但答案似乎集中在为什么这是一个坏主意——也许是因为问题表明了线程是不合理的。另外,我想将所有内存请求视为平等可能会导致死锁。所以我想强调的是,这里我们只讨论了 10 个任务,“最大化”内存使用的愿望似乎是很自然的。我不介意用一些合适的逻辑来包装我的任务,这些逻辑将它们的内存请求区分为具有较低优先级。我什至可以接受一个解决方案,我需要识别其实例正在填满内存的类,并可能添加一些合适的计数器 - 但我更喜欢“开箱即用”的独立于平台的解决方案,如果有的话.

This question 还询问了调度内存绑定任务的问题,但似乎预设了一个特定的解决方案框架。

【问题讨论】:

  • 把数据分配到堆外怎么样?
  • 最好的方法是使用直接访问堆外内存(例如,参见github.com/anatolygudkov/workshops/tree/master/offheap-memory)并确保尽可能以顺序方式(缓存友好)寻址内存。另外,请确保您在线程之间共享尽可能少的内存,并且共享在 JMM 方面是正确的。

标签: java multithreading memory-management scheduler


【解决方案1】:

问题在于,在单个 JVM 中,您几乎无法控制单个线程将使用多少内存。除非您使用堆外(例如使用 Unsafe 或直接内存,如 AnatolyG 已经提到的)。如果你有大量的数组分配,你也可以控制这些。但是我们需要更多地了解消耗内存最多的数据结构。

但是,如果您拥有无法控制的轨道物体图,那么使用多个进程对问题进行建模可能更明智。您有 1 个进气控制器进程,然后是一堆工作进程。您可以在每个进程上配置 JVM 允许使用的最大堆数。

在操作系统级别遇到内存限制可能是一个巨大的 PITA,因为它可能导致交换,这将使系统中的所有线程变慢。或者更糟糕的是,OOM​​ 杀手。确保将 vm.swappiness 设置为非常低的值以防止过早交换。

您是否预先知道一个进程将消耗多少内存?如果是这样,那么您可以跟踪系统中消耗的最大内存量,并且在任务完成之前不允许系统中的新任务。

如果您事先不知道内存限制,那么您可以假设每个任务都会使用最大值,但这可能会导致内存利用率不足。

【讨论】:

    猜你喜欢
    • 2014-04-14
    • 1970-01-01
    • 2015-03-20
    • 2011-01-08
    • 2012-06-29
    • 2011-07-02
    • 2016-03-19
    • 1970-01-01
    • 2012-10-06
    相关资源
    最近更新 更多