限制java应用程序的内存和cpu使用

Posted

技术标签:

【中文标题】限制java应用程序的内存和cpu使用【英文标题】:Limiting java application's memory and cpu usage 【发布时间】:2011-06-24 13:31:41 【问题描述】:

说,“以 cpu=800 和 memory=1024 运行 myApp.jar”

我从事java编程多年,问这个问题很尴尬。我什至不知道这是否可能。如果有,怎么做?

我只想知道是否可以设置 java 程序的最大内存和 cpu 使用率。我突然想到这个,因为我最近开始开发移动应用程序。我想知道应用程序在内存和处理器非常有限的设备上的行为。

我看到带有演示应用程序的物理引擎可以在浏览器上运行,或者我可以在我的 PC 上执行。如果我在移动设备上运行它们会怎样?性能会一样吗?与其开发一个示例移动应用程序来测试库的性能,我宁愿先在我的 PC 上使用特定的 CPU 和内存运行它。

顺便说一句,我尝试用谷歌搜索...我发现的只是监控和性能调整。我可能使用了错误的关键字。

【问题讨论】:

【参考方案1】:

您可以通过 -Xmx 选项限制内存使用,并且可以通过设置进程的优先级和/或 CPU 亲和性来限制 CPU 使用。

【讨论】:

在linux上,你可以使用taskset(1)以指定的CPU亲和力运行JVM,这对很多人来说远非显而易见。无法从普通的 JVM 设置 CPU 亲和性。 (您可以使用 JNI 魔法,但要使用龙。) 是的,您不能通过我知道的标准 java 选项设置关联性和处理器优先级...在 Windows 上,您需要的命令是启动(在 32 位 Windows 上它没有关联选项不过) 内存使用量可以设置为您提到的参数。对于 CPU,优先级并没有限制。我查了谷歌,发现有工具可以限制特定进程的CPU使用率。我现在正在尝试。 @demotics2002,好吧,如果您在任务管理器/顶部观察进程 - 是的,它会达到 100%(或任何线程以最大运行速度),但是这是 b/c 你没有其他进程争夺 CPU 时间。如果是这样,他们将享受某些好处。是的,CPU 没有运行“空闲”进程。 JVM 有一个参数 -XX:ActiveProcessorCount= 表示“覆盖 VM 将用于计算线程池大小的 CPU 数量,它将用于垃圾收集等各种操作和 ForkJoinPool”。您可以使用 Runtime.getRuntime().availableProcessors() 检查此参数。如果您的应用实际使用超过 1 个处理器并且您想限制它,这可能会有所帮助。【参考方案2】:

JVM 无法控制 CPU 使用率或优先级。

JVM 可以控制最大/最小内存使用量。

有一个解决方法。可以在单独的 [Docker 容器][1] 中运行每个 JVM。并控制每个容器的资源(内存、CPU、网络、IO)分配。这正是 Docker 容器的附加值。

[1]:JVM 无法控制 CPU 使用率和优先级。然而,您可以在单独的 Docker 容器中运行每个 JVM。并控制每个容器的资源分配。这正是 Docker 容器的附加值。

【讨论】:

你忘了说老版本的JVM,包括8,不理解Docker抽象,不会依赖容器设置。这仅适用于最新版本的 JVM,并且 JVM 8 仍然是主要版本。 我强烈反对,请再研究一下 Docker 的架构。 JVM 与容器技术无关且完全无视。我们确实同意:JVM 依赖容器设置是一种不稳定的设计选择。 你可以不同意,但如果你用谷歌搜索“jvm docker”并检查前几篇文章或文章会更有用。之后,您可以根据blog.csanchez.org/2017/05/31/… 在您选择的终端中简单地运行 2 个命令。我刚刚做了,它证实了我的怀疑。 分歧的来源是如何指定和绑定HW资源(CPU、mem、storage、NTWK)。在我所有的情况下,我都在硬编码资源的边界。如果您尝试从您遇到编程挑战的当前容器功能计算/计算边界,大多数情况下都可以通过使用预边界图像来避免。【参考方案3】:

Docker 提供了资源管理选项来限制运行 docker 容器的 cpu 访问。查看 Docker 文档中 Limit a container's resources 中的 docker run 提供的 CFS 调度程序选项,例如:

--cpus=<value> - 指定容器可以使用多少可用 CPU 资源。例如,如果宿主机有两个 CPU,而您设置--cpus="1.5",则容器最多保证 1 个半的 CPU。这相当于设置--cpu-period="100000"--cpu-quota="150000"。在 Docker 1.13 及更高版本中可用。 --cpuset-cpus - 限制容器可以使用的特定 CPU 或内核。如果您有多个 CPU,则容器可以使用的逗号分隔列表或连字符分隔的 CPU 范围。第一个 CPU 编号为 0。有效值可能是 0-3(使用第一个、第二个、第三个和第四个 CPU)或 1,3(使用第二个和第四个 CPU)。

这些选项也可以通过 docker-compose 在部署 Docker swarm/stack 时使用,如 Compose file version 3 reference 下的 resources 所述:

version: '3'
services:
  redis:
    image: redis:alpine
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M```

注意: docker compose v2 中的 legacy resource options 现在仅限于 migration to v3 中的堆栈。

【讨论】:

【参考方案4】:

在运行 jvm 8 或更早版本时,请注意内存和 CPU 选项。 有几篇关于这个的非常好的文章。看看吧:

https://developers.redhat.com/blog/2017/03/14/java-inside-docker/

https://jaxenter.com/nobody-puts-java-container-139373.html

话虽如此,容器化是微服务架构的正确方法,无论堆栈如何,jvm 也不例外。但是,重要的是要注意这些警告。

【讨论】:

【参考方案5】:

Linux:

taskset -a -c 0,1,2,3 <program>

仅在核心 0、1、2 和 3 上运行程序及其子线程。

【讨论】:

【参考方案6】:

在这种情况下,在移动模拟器(例如 android)上运行应用程序可能会有所帮助。

使用它,您可以模拟具有特定 CPU/内存的移动设备。因此,您应该获得与具有较慢 CPU 和较少 RAM 的设备相当的性能。

Android/诺基亚模拟器是免费的,可从诺基亚/谷歌网站的开发者部分下载。

【讨论】:

【参考方案7】:

https://github.com/haosdent/jcgroup jcgroup 是您的最佳选择。您可以使用此库来限制 CPU 份额、磁盘 I/O 速度、网络带宽等。

【讨论】:

【参考方案8】:

对于 CPU,你可以试试我的新库 :)。

https://github.com/dyorgio/cpu-watcher

使用示例:

// Limit process by PID to 25% of host cpu usage
CpuWatcher cpuWatcher = new CpuWatcher(pid, 25f);
cpuWatcher.start();

【讨论】:

以上是关于限制java应用程序的内存和cpu使用的主要内容,如果未能解决你的问题,请参考以下文章

Docker——JVM 感知容器的 CPU 和 Memory 资源限制

Docker——JVM 感知容器的 CPU 和 Memory 资源限制

Java内存模型之总结

Java程序运行在Docker等容器环境有哪些新问题

Kubernetes 内存管理及调度

Docker: 限制容器可用的 CPU