Add Runtimes document
This commit is contained in:
parent
9a64eef41f
commit
2e2de8f33c
3 changed files with 174 additions and 2 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.kdev4
|
|
@ -1,2 +1,5 @@
|
||||||
# Design
|
# Design and planning
|
||||||
Design and planning documentation
|
|
||||||
|
This is a dump for various documents describing parts of MultiMC - current and future.
|
||||||
|
|
||||||
|
It's stuff that does not fit into the user-facing wiki.
|
||||||
|
|
168
Runtimes.md
Normal file
168
Runtimes.md
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# JRE system overhaul
|
||||||
|
|
||||||
|
The idea is to do a complete rework of Java runtime management.
|
||||||
|
|
||||||
|
The game now requires different versions of the JRE and our current approach no longer works.
|
||||||
|
|
||||||
|
The complete shape of the system is undecided at this point.
|
||||||
|
|
||||||
|
Format decisions should aim for future extensibility - don't close doors that don't need to be closed forever.
|
||||||
|
|
||||||
|
## Runtime references
|
||||||
|
Runtime references are used in version metadata files
|
||||||
|
Along those, a hierarchy of options / variable defaults
|
||||||
|
|
||||||
|
Currently, vanilla hardcodes these for `x86`:
|
||||||
|
```
|
||||||
|
-Xmx2G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M
|
||||||
|
```
|
||||||
|
|
||||||
|
And these for `amd64`:
|
||||||
|
```
|
||||||
|
-Xmx800M -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=16M
|
||||||
|
```
|
||||||
|
|
||||||
|
This is how a Java runtime could be referenced in a Minecraft version:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"runtime": {
|
||||||
|
"majorVersion": 17,
|
||||||
|
"mojangReference": "java-runtime-beta",
|
||||||
|
"variables": {
|
||||||
|
"x86": {
|
||||||
|
"maxHeap": "800M",
|
||||||
|
"minStack": "1M"
|
||||||
|
},
|
||||||
|
"amd64": {
|
||||||
|
"maxHeap": "2048M"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is how a Java runtime could be referenced in a Minecraft version, with slightly different defaults:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"runtime": {
|
||||||
|
"majorVersion": 17,
|
||||||
|
"mojangReference": "java-runtime-beta",
|
||||||
|
"variables": {
|
||||||
|
"windows": {
|
||||||
|
"x86": {
|
||||||
|
"minHeap": "512M",
|
||||||
|
"maxHeap": "1450M",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"x86": {
|
||||||
|
"minHeap": "512M",
|
||||||
|
"maxHeap": "2048M",
|
||||||
|
"minStack": "1M"
|
||||||
|
},
|
||||||
|
"amd64": {
|
||||||
|
"minHeap": "512M",
|
||||||
|
"maxHeap": "2048M",
|
||||||
|
"minStack": "1M"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In a modpack (or instance), we could say there is an optimal heap size and minimal heap size:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"runtime": {
|
||||||
|
"minHeap": "2048M",
|
||||||
|
"optimalHeap": "4096M"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
With this, we could:
|
||||||
|
|
||||||
|
- Warn the user if they don't have enough memory for optimal use
|
||||||
|
- Warn them harder if they have below minimum available memory
|
||||||
|
- Determine the actual heap size dynamically based on the runtime, hardware, architecture and the instance/modpack variables.
|
||||||
|
|
||||||
|
## Runtimes
|
||||||
|
|
||||||
|
- Every runtime has a major version.
|
||||||
|
- Runtimes can come from Mojang
|
||||||
|
This is what we want to use by default.
|
||||||
|
- Runtimes can be local
|
||||||
|
This is what we had up to now.
|
||||||
|
|
||||||
|
## Major versions
|
||||||
|
|
||||||
|
The major version describes the basic properties of the runtime:
|
||||||
|
- Feature set
|
||||||
|
- Is it valuable to model these in detail?
|
||||||
|
- Possible garbage collectors?
|
||||||
|
- Is it valuable to model these in detail?
|
||||||
|
- Basic (not vendor specific) set of arguments
|
||||||
|
- Mapping of MultiMC traits and/or variables to arguments
|
||||||
|
|
||||||
|
## Garbage collectors and runtime parameters
|
||||||
|
|
||||||
|
This is a deep topic. We may simply want to have some default GC options for every major version of Java and let people override them.
|
||||||
|
|
||||||
|
Alternative is to map out all of these options and pick based on:
|
||||||
|
- Java version
|
||||||
|
- Available number of cores
|
||||||
|
- Size of heap
|
||||||
|
- etc.
|
||||||
|
|
||||||
|
Mojang practically uses Java 8, 16 and 17. Others do not have to be mapped out completely.
|
||||||
|
|
||||||
|
We can use the Java 8 options for all major versions up to 16.
|
||||||
|
|
||||||
|
We can use the Java 17 options for all versions above 17, until specified otherwise.
|
||||||
|
|
||||||
|
### Java 8
|
||||||
|
|
||||||
|
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html
|
||||||
|
|
||||||
|
#### Unusable GCs
|
||||||
|
|
||||||
|
- **SerialGC** - `-XX:+UseSerialGC` - Serial collection of up to 100MB heap space. Useless for Minecraft.
|
||||||
|
- **ParallelGC** - `-XX:+UseParallelGC` - high latency parallel collector. Useless for Minecraft.
|
||||||
|
- **ParallalGC with parallel compaction disabled** - `-XX:+UseParallelGC -XX:-UseParallelOldGC` - Why? It's just slower...
|
||||||
|
|
||||||
|
#### Potentially usable GCs
|
||||||
|
|
||||||
|
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/concurrent.html#mostly_concurrent
|
||||||
|
|
||||||
|
- **UseConcMarkSweepGC** - `-XX:+UseConcMarkSweepGC` - parallel, shares processing time with GC.
|
||||||
|
- Incremental Mode (deprecated):
|
||||||
|
This is useful on machines with one core, if we want to guarantree low latency.
|
||||||
|
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html#CJAGIIEJ
|
||||||
|
- **G1GC** - `-XX:+UseG1GC` - parallel, GC cycles run next to the actual computation.
|
||||||
|
|
||||||
|
#### Conclusion
|
||||||
|
|
||||||
|
By the looks of it, for Minecraft, only G1GC makes sense.
|
||||||
|
|
||||||
|
We could just say that `-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=16M` are the default args here, and combine that with stack, permgen and heap sizes.
|
||||||
|
|
||||||
|
The argument for modeling this would be running on VERY old hardware - think single core system with 2GB of memory. Then **ConcMarkSweepGC** with **Incremental Mode** could make sense.
|
||||||
|
|
||||||
|
Knowing we run with such constraints and selecting different GC based on it would be helpful to users of such systems.
|
||||||
|
|
||||||
|
### Java 16 and 17
|
||||||
|
|
||||||
|
https://docs.oracle.com/en/java/javase/16/gctuning/available-collectors.html
|
||||||
|
|
||||||
|
This adds the the Z Garbage Collector, which is fully parallel and aims for low latency (a few ms, still a lot for games, but better than the alternatives).
|
||||||
|
|
||||||
|
#### Conclusion
|
||||||
|
|
||||||
|
Practically, ZGC should be used: `-XX:+UseZGC`.
|
||||||
|
|
||||||
|
See: https://docs.oracle.com/en/java/javase/16/gctuning/z-garbage-collector.html
|
||||||
|
|
||||||
|
Interesting parameters:
|
||||||
|
- Number of GC threads - `-XX:ConcGCThreads` - possibly the default heuristics would be OK.
|
||||||
|
- Returning memory to the system is enabled by default, and can be disabled with `-XX:-ZUncommit`.
|
Loading…
Reference in a new issue