Skip to content

Commit

Permalink
Update memory calculation docs
Browse files Browse the repository at this point in the history
  • Loading branch information
glyn committed Apr 10, 2017
1 parent f58ce04 commit 2dd7180
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 157 deletions.
99 changes: 47 additions & 52 deletions docs/jre-open_jdk_jre.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ The JRE can be configured by modifying the [`config/open_jdk_jre.yml`][] file in

| Name | Description
| ---- | -----------
| `memory_sizes` | Optional memory sizes, described below under "Memory Sizes".
| `memory_heuristics` | Default memory size weightings, described below under "Memory Weightings".
| `memory_initials` | Initial memory sizes, described below under "Memory Initials".
| `memory_calculator` | Memory calculator defaults, described below under "Memory".
| `repository_root` | The URL of the OpenJDK repository index ([details][repositories]).
| `version` | The version of Java runtime to use. Candidate versions can be found in the listings for [mountainlion][], [precise][], and [trusty][]. Note: version 1.8.0 and higher require the `memory_sizes` and `memory_heuristics` mappings to specify `metaspace` rather than `permgen`.

Expand All @@ -36,81 +34,78 @@ To add the JCE Unlimited Strength `local_policy.jar`, add your file to `resource
To add custom SSL certificates, add your `cacerts` file to `resources/open_jdk_jre/lib/security/cacerts`. This file will be overlayed onto the OpenJDK distribution.

### Memory
The total available memory is specified when an application is pushed as part of it's configuration. The Java buildpack uses this value to control the JRE's use of various regions of memory. The JRE memory settings can be influenced by configuring the `memory_sizes`, `memory_heuristics`, `memory_initials` and/or `stack_threads` mappings.
The total available memory for the application's container is specified when an application is pushed.
The Java buildpack uses this value to control the JRE's use of various
regions of memory and logs the JRE memory settings when the application starts or restarts.
These settings can be influenced by configuring
the `stack_threads` and/or `class_count` mappings (both part of the `memory_calculator` mapping),
and/or Java options relating to memory.

Note: If the total available memory is scaled up or down, the Java buildpack will re-calculate the JRE memory settings the next time the application is started.

Note: If setting an initial Stack size, depending on the version of Java and the operating system used by Cloud Foundry the JRE will require a minimum `-Xss` value. This tends to be between `100k` and `250k`.
#### Total Memory

#### Memory Sizes
The following optional properties may be specified in the `memory_sizes` mapping.
The user can change the container's total memory available to influence the JRE memory settings.
Unless the user specifies the heap size Java option (`-Xmx`), increasing or decreasing the total memory
available results in the heap size setting increasing or decreasing by a corresponding amount.

| Name | Description
| ---- | -----------
| `heap` | The maximum heap size to use. It may be a single value such as `64m` or a range of acceptable values such as `128m..256m`. It is used to calculate the value of the Java command line options `-Xmx` and `-Xms`.
| `metaspace` | The maximum Metaspace size to use. It is applicable to versions of OpenJDK from 1.8 onwards. It may be a single value such as `64m` or a range of acceptable values such as `128m..256m`. It is used to calculate the value of the Java command line options `-XX:MaxMetaspaceSize=` and `-XX:MetaspaceSize=`.
| `native` | The amount of memory to reserve for native memory allocation. It should normally be omitted or specified as a range with no upper bound such as `100m..`. It does not correspond to a switch on the Java command line.
| `permgen` | The maximum PermGen size to use. It is applicable to versions of OpenJDK earlier than 1.8. It may be a single value such as `64m` or a range of acceptable values such as `128m..256m`. It is used to calculate the value of the Java command line options `-XX:MaxPermSize=` and `-XX:PermSize=`.
| `stack` | The stack size to use. It may be a single value such as `2m` or a range of acceptable values such as `2m..4m`. It is used to calculate the value of the Java command line option `-Xss`.

Memory sizes together with _memory weightings_ (described in the next section) are used to calculate the amount of memory for each memory type. The calculation is described later.

Memory sizes consist of a non-negative integer followed by a unit (`k` for kilobytes, `m` for megabytes, `g` for gigabytes; the case is not significant). Only the memory size `0` may be specified without a unit.

The above memory size properties may be omitted with an empty value, specified as a single value, or specified as a range. Ranges use the syntax `<lower bound>..<upper bound>`, although either bound may be omitted in which case the defaults of zero and the total available memory are used for the lower bound and upper bound, respectively. Examples of ranges are `100m..200m` (any value between 100 and 200 megabytes, inclusive) and `100m..` (any value greater than or equal to 100 megabytes).

Each form of memory size is equivalent to a range. Omitting a memory size is equivalent to specifying the range `0..`. Specifying a single value is equivalent to specifying the range with that value as both the lower and upper bound, for example `128m` is equivalent to the range `128m..128m`.
#### Stack Threads

#### Memory Weightings
Memory weightings are configured in the `memory_heuristics` mapping of [`config/open_jdk_jre.yml`][]. Each weighting is a non-negative number and represents a proportion of the total available memory (represented by the sum of all the weightings). For example, the following weightings:
The amount of memory that should be allocated to stacks is given as an amount of memory per
thread with the Java option `-Xss`. If an explicit number of
threads should be used for the calculation of stack memory, then it should be specified as in
the following example:

```yaml
memory_heuristics:
heap: 15
native: 2
permgen: 5
stack: 1
stack_threads: 500
```
represent a maximum heap size three times as large as the maximum PermGen size, and so on.
Memory weightings are used together with memory ranges to calculate the amount of memory for each memory type, as follows.
#### Loaded Classes
#### Memory Initials
Memory initials are configured in the `memory_initials` mapping of [`config/open_jdk_jre.yml`][]. Each initial is a percentage of the given type of memory. Valid memory types are `heap`, `permgen`, and `metaspace`. For example, the following initials:
The amount of memory that is allocated to metaspace and compressed class space (or, on Java 7, the permanent generation) is calculated from an estimate of the number of classes that will be loaded. The default behaviour is to estimate the number of loaded classes as a fraction of the number of class files in the application.
If a specific number of loaded classes should be used for calculations, then it should be specified as in the following example:
```yaml
memory_initials:
heap: 50%
permgen: 25%
class_count: 500
```
Given a maximum heap (Xmx) of 1G and a maximum permgen (-XX:MaxPermsize) of 256M an initial heap (Xms) of 512M and an initial permgen (-XX:Permsize) of 64M would be used.

If no initial value is specified for a memory type the JVM default will be used.

A value of 100% for each memory types is generally recommended for best performance. Smaller values will potentially preserve unused system memory for other tenants on the same host. Using the G1 garbage collector along with aggressive `MinHeapFreeRatio` and `MaxHeapFreeRatio` values the JVM will actually release unused heap back to the system up to the initial value.

#### Stack Threads

The amount of memory that should be allocated to the stack is given as an amount of memory per thread with the command line option `-Xss`. The default behaviour is to use an estimate of the number of threads based on the total memory for the application. If an explicit number of threads should be used for the calculation of stack memory then it should be specified like the following example:
#### Java Options
```yaml
stack_threads: 500
```
If the JRE memory settings need to be fine-tuned, the user can set one or more Java memory options to
specific values. The heap size can be set explicitly, but changing the value of options other
than the heap size can also affect the heap size. For example, if the user increases
the maximum direct memory size from its default value of 10 Mb to 20 Mb, then this will
reduce the calculated heap size by 10 Mb.
#### Memory Calculation
Memory calculation happens before every `start` of an application and is performed by an external program, the [Java Buildpack Memory Calculator]. There is no need to `restage` an application after scaling the memory as restarting will cause the memory settings to be recalculated.

The total available memory is allocated into heap, Metaspace or PermGen (depending on the version of Oracle), stack, and native memory types.
The container's total available memory is allocated into heap, metaspace and compressed class space (or permanent generation for Java 7),
direct memory, and stack memory settings.

The memory calculation is described in more detail in the [Memory Calculator's README].

The inputs to the memory calculation, except the container's total memory (which is unknown at staging time), are logged during staging, for example:
```
Loaded Classes: 13974, Threads: 300, JAVA_OPTS: ''
```

The total available memory is first allocated to each memory type in proportion to its weighting (this is called ‘balancing'). If the resultant size of any memory type lies outside its range, the size is constrained to the range, the constrained size is excluded from the remaining memory, and no further calculation is required for that memory type. The remaining memory is then balanced against the memory types that are left, and the check is repeated until no calculated memory sizes lie outside their ranges. The remaining memory is then allocated to the remaining memory types according to the last balance step. This iteration terminates when none of the sizes of the remaining memory types is constrained by their corresponding ranges.
The container's total memory is logged during `cf push` and `cf scale`, for example:
```
state since cpu memory disk details
#0 running 2017-04-10 02:20:03 PM 0.0% 896K of 1G 1.3M of 1G
```

Termination is guaranteed since there is a finite number of memory types and in each iteration either none of the remaining memory sizes is constrained by the corresponding range and allocation terminates or at least one memory size is constrained by the corresponding range and is omitted from the next iteration.
The JRE memory settings are logged when the application is started or re-started, for example:
```
JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=99199K \
-XX:ReservedCodeCacheSize=240M -XX:CompressedClassSpaceSize=18134K -Xss1M -Xmx368042K
```

[`config/open_jdk_jre.yml`]: ../config/open_jdk_jre.yml
[Configuration and Extension]: ../README.md#configuration-and-extension
[Java Buildpack Memory Calculator]: https://github.com/cloudfoundry/java-buildpack-memory-calculator
[Memory Calculator's README]: https://github.com/cloudfoundry/java-buildpack-memory-calculator
[mountainlion]: http://download.pivotal.io.s3.amazonaws.com/openjdk/mountainlion/x86_64/index.yml
[OpenJDK]: http://openjdk.java.net
[precise]: http://download.pivotal.io.s3.amazonaws.com/openjdk/precise/x86_64/index.yml
Expand Down
Loading

0 comments on commit 2dd7180

Please sign in to comment.