Skip to content

CpuShares is always enforced to a minimum of 2 #1735

@xose

Description

@xose

Summary

The ECS agent forces the Docker's CpuShares setting to always be set for every container it runs, even if it's empty on the task definition. This negatively affects performance of containers that use this information to configure their threading.

Description

Programming languages may be "container-aware" and use cgroup information available inside a container, like memory limits or CPU shares, to make configuration decisions at runtime.

Java 10, 11 and recent builds of Java 8 (including Amazon Corretto) use Docker memory limits to configure the heap and CPU shares to set the amount of available CPUs for threading and garbage collection. See: https://blog.docker.com/2018/04/improved-docker-container-integration-with-java-10/

When leaving the CPU shares unset on a task definition, the ECS agent will always set "2" as the value passed to Docker to create the container. This makes Java services running in the container think it has only 1 CPU available (shares <1024) and will configure its threading to use a maximum of 1 CPU, greatly affecting performance.

Expected Behavior

When leaving CPU shares unset on a task definition, CpuShares is 0 and Java's Runtime.getRuntime().availableProcessors() returns the amount of CPUs of the host.

Observed Behavior

When leaving CPU shares unset, CpuShares is 2 and Runtime.getRuntime().availableProcessors() is always 1.

Example

A one-liner to quickly test with the openjdk:8 or openjdk:11 images:

sh -c 'echo "class Main { public static void main(String[] args) { System.out.println(Runtime.getRuntime().availableProcessors()); } }" > Main.java; javac Main.java; java Main'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions