Limiting java application's memory and cpu usage

45,330

Solution 1

you can limit memory usage by -Xmx option and you can limit CPU usage by setting priority of the process and/or CPU affinity.

Solution 2

The JVM has no control over CPU usage nor priority.

JVM has control over max/min Memory usage.

There is a workaround. It is possible to run each JVM in a separate [Docker container][1]. And control the resource (Memory, CPU, Network, IO) allocation for each container. That is exactly the added value of the Docker containers.

[1]: The JVM has no control over CPU usage nor priority. Yet you can run each JVM in a separate Docker container. And control the resource allocation foreach container. That is exactly the added value of the Docker containers.

Solution 3

Linux:

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

Run a program and its child threads only on cores 0, 1, 2, and 3.

Solution 4

Docker offers up resource management options for limiting the cpu access for running docker containers. Have a look at the CFS scheduler options available with docker run from Limit a container's resources in the Docker documentation, such as:

  • --cpus=<value> - Specify how much of the available CPU resources a container can use. For instance, if the host machine has two CPUs and you set --cpus="1.5", the container is guaranteed at most one and a half of the CPUs. This is the equivalent of setting --cpu-period="100000" and --cpu-quota="150000". Available in Docker 1.13 and higher.
  • --cpuset-cpus - Limit the specific CPUs or cores a container can use. A comma-separated list or hyphen-separated range of CPUs a container can use, if you have more than one CPU. The first CPU is numbered 0. A valid value might be 0-3 (to use the first, second, third, and fourth CPU) or 1,3 (to use the second and fourth CPU).

These options are also available via docker-compose, when deploying a Docker swarm / stack, as mentioned in Compose file version 3 reference under resources:

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

Note: that the legacy resource options in docker compose v2 are now limited to stacks in the migration to v3.

Solution 5

For CPU you can try my new lib :).

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

Example of use:

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

demotics2002

Updated on December 06, 2020

Comments

  • demotics2002
    demotics2002 over 3 years

    Say, "run myApp.jar with cpu=800 and memory=1024"

    Ive been doing java programming for many years and it is an embarrasment to ask this question. I don't even know whether this is possible or not. And if so, how?

    What I just want know is if it is possible to set a java program's maximum memory and cpu usage. I suddenly thought of this because of I recently started developing mobile apps. I want to know how the app will behave on the device which has very limited memory and processor.

    I saw physics engines with demo apps that run on the browser or I can execute on my PC. What if I run them on a mobile device? Will the performance be the same? Rather than developing a sample mobile app to test the library's performance, I'd rather run it with a specific cpu and memory using my PC first.

    I tried googling by the way... all i found was monitoring and performance tuning. I may be using wrong keywords.

  • andersoj
    andersoj about 13 years
    On linux, you can run the JVM with specified CPU affinity using taskset(1), which is far from obvious for many people. There is no way to set CPU affinity from a run-of-the-mill JVM. (you can do JNI magic, but thar be dragons.)
  • bestsss
    bestsss about 13 years
    yes, you can't set neither affinity nor processor priority by standard java options I know of... on windows the command you need is start (on 32bit windows it doesn't have affinity option, though)
  • demotics2002
    demotics2002 about 13 years
    The memory usage can be set as an argument as you mentioned. For the CPU, the priority doesn't limit it. I checked google and found that there are tools that can limit the CPU usage of specific process. Im trying it now.
  • bestsss
    bestsss about 13 years
    @demotics2002, well if you are observing the process in task manager/top - yes, it goes to 100% (or whatever the threads are running at max), however that's b/c you get no other processes competing for CPU time. If so, they enjoy certain benefits. Yes, the CPU is not running the 'idle' process.
  • yuranos
    yuranos over 5 years
    You forgot to mention that older versions of JVM, including 8, do not understand Docker abstraction and will not rely on container settings. This is only applicable for the latest versions of JVM, and JVM 8 is still the predominant one.
  • Dudi Boy
    Dudi Boy over 5 years
    I would strongly disagree, please research again the architecture of Docker. JVM is unrelated and absolutely oblivious to container technology. We do agree: that It is precarious design choice for JVM to rely on container settings.
  • yuranos
    yuranos over 5 years
    You can disagree, but it would be more useful if you google "jvm docker" instead and check through the first couple or articles. After that you can simply run 2 commands in your terminal of choice based on blog.csanchez.org/2017/05/31/…. I just did and it confirmed my suspicion.
  • Dudi Boy
    Dudi Boy over 5 years
    The source of disagreement is how to specify and bound HW resources (CPU, mem, storage, NTWK). In all my cases I am hard-coding the boundaries to the resources. If you try to calculate/compute the boundaries from the current container features you get into programming challenges, most times can be avoided by using pre-bounded images.
  • Danilo Teodoro
    Danilo Teodoro about 3 years
    The JVM has a parameter -XX:ActiveProcessorCount=<number> that "Overrides the number of CPUs that the VM will use to calculate the size of thread pools it will use for various operations such as Garbage Collection and ForkJoinPool". You can check this parameter with Runtime.getRuntime().availableProcessors(). It might help in case your app actually uses more than 1 processor and you want to limit it.
  • j23
    j23 over 2 years
    Do you need to set additionally for GC: -XX:ActiveProcessorCount=<number>