Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dynamic ram assignment when over 1GB #4921

Merged
merged 6 commits into from
Nov 2, 2023

Conversation

GregoryIvo
Copy link
Contributor

@GregoryIvo GregoryIvo commented Oct 26, 2023

Modifies the customize-installation script so that if there is more than 1GB of RAM available, kura will utilize 1/4th of it

Thinks to be figured out:

    1. is there a better way to do this with the default Java options
    1. is it the right implementation?
    1. is it safe to use MemTotal

Note: We are using the Conventional Commits convention for our pull request titles. Please take a look at the PR title format document for the supported types and scopes.

Brief description of the PR. [e.g. Added null check on object to avoid NullPointerException]

Related Issue: This PR fixes/closes {issue number}

Description of the solution adopted: A more detailed description of the changes made to solve/close one or more issues. If the PR is simple and easy to understand this section can be skipped

Screenshots: If applicable, add screenshots to help explain your solution
changed from the default 512 -> calculated 948
image

Manual Tests: Optional description of the tests performed to check correct functioning of changes, useful for an efficient review

Any side note on the changes made: Description of any other change that has been made, which is not directly linked to the issue resolution [e.g. Code clean up/Sonar issue resolution]

@GregoryIvo
Copy link
Contributor Author

@marcellorinaldo What do you think about this impl?

@GregoryIvo
Copy link
Contributor Author

GregoryIvo commented Oct 26, 2023

The rest of this PR is going to be research for the questions asked above.

This thoughts are all started becue of the following line in the docs.
"Do not choose a maximum value for the heap unless you know that the heap is greater than the default maximum heap size. Choose a throughput goal that is sufficient for your application." -https://docs.oracle.com/javase/6/docs/technotes/guides/vm/gc-ergonomics.html

Rather than setting stack limits, the Oracle docs suggest setting goals, so that the JVM can dynamically optimize.

A hint to the virtual machine that it's desirable that not more than 1 / (1 + nnn) of the application execution time be spent in the collector.
For example -XX:GCTimeRatio=19 sets a goal of 5% of the total time for GC and throughput goal of 95%. That is, the application should get 19 times as much time as the collector.

By default the value is 99, meaning the application should get at least 99 times as much time as the collector. That is, the collector should run for not more than 1% of the total time. This was selected as a good choice for server applications. A value that is too high will cause the size of the heap to grow to its maximum.
If you need to minimize the dynamic memory footprint (the maximum RAM consumed during
execution) for your application, then you can do this by minimizing the Java heap size. Java
SE Embedded applications may require this.
Minimize Java heap size by lowering the values of the options -XX:MaxHeapFreeRatio
(default value is 70%) and -XX:MinHeapFreeRatio (default value is 40%) with the commandline options -XX:MaxHeapFreeRatio and -XX:MinHeapFreeRatio. Lowering -
XX:MaxHeapFreeRatio to as low as 10% and -XX:MinHeapFreeRatio has shown to
successfully reduce the heap size without too much performance degradation; however,
results may vary greatly depending on your application. Try different values for these
parameters until they're as low as possible, yet still retain acceptable performance.
In addition, you can specify -XX:-ShrinkHeapInSteps, which immediately reduces the Java
heap to the target size (specified by the parameter -XX:MaxHeapFreeRatio). You may
encounter performance degradation with this setting. By default, the Java runtime
incrementally reduces the Java heap to the target size; this process requires multiple
garbage collection cycles.

@marcellorinaldo
Copy link
Contributor

marcellorinaldo commented Oct 27, 2023

@GregoryIvo You can dome some experiments to see how much memory is allocated at runtime with JVM default options and the hard-coded values passed with -Xms and -Xmx.

  1. First, install the JDK to have some debug commands available
  2. Reboot
  3. Switch to kurad user from root sudo -u kurad /bin/bash

Utils:

  • Retrieve the PID for the equinox jar:

    jps
  • Get parameters currently assigned to start script:

    jps -lv
  • Heap and metaspace info:

    jcmd <equinox-pid> GC.heap_info

References:

sed -i "s/-Xms[0-9]*m -Xmx[0-9]*m/$RAM_REPLACEMENT_STRING/g" /opt/eclipse/kura/bin/start_kura_background.sh
else
echo "Leaving kura ram as the default set in installer profile"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, on generic profiles this will default to 512MB: https://github.com/eclipse/kura/blob/c9c25c02d992be0981c2ac06befa0bc13ab45b10/kura/distrib/pom.xml#L1569C41-L1569C41

Are we ok with this even on devices with < 1GB of memory?

@GregoryIvo
Copy link
Contributor Author

With original parameters:

125640 Jps
125501 org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar
root@kevin:/opt/eclipse/kura/bin# jps -lv
126553 jdk.jcmd/sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-11-openjdk-arm64 -Xms8m -Djdk.module.main=jdk.jcmd
125501 /opt/eclipse/kura/plugins/org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar -Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/kura-heapdump.hprof -XX:ErrorFile=/var/log/kura-error.log -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-modules=ALL-SYSTEM -Dkura.os.version=raspbian -Dkura.arch=generic-arm64 -Dtarget.device=generic-aarch64 -Declipse.ignoreApp=true -Dkura.home=/opt/eclipse/kura -Dkura.configuration=file:/opt/eclipse/kura/framework/kura.properties -Dkura.custom.configuration=file:/opt/eclipse/kura/user/kura_custom.properties -Ddpa.configuration=/opt/eclipse/kura/packages/dpa.properties -Dlog4j.configurationFile=file:/opt/eclipse/kura/log4j/log4j.xml -Djava.security.policy=/opt/eclipse/kura/framework/jdk.dio.policy -Djdk.dio.registry=/opt/eclipse/kura/framework/jdk.dio.properties -Djdk.tls.trustNameService=true -Dosgi.console=5002 -Declipse.consoleLog=true
root@kevin:/opt/eclipse/kura/bin# jcmd 125501 GC.heap_info
125501:
garbage-first heap total 524288K, used 168271K [0x00000000e0000000, 0x0000000100000000)
region size 1024K, 127 young (130048K), 1 survivors (1024K)
Metaspace used 51107K, committed 52672K, reserved 1097728K
class space used 5818K, committed 6400K, reserved 1048576K
root@kevin:/opt/eclipse/kura/bin# jcmd 125501 GC.heap_info
125501:
garbage-first heap total 524288K, used 114209K [0x00000000e0000000, 0x0000000100000000)
region size 1024K, 72 young (73728K), 1 survivors (1024K)
Metaspace used 55165K, committed 56704K, reserved 1105920K
class space used 6336K, committed 691

@GregoryIvo
Copy link
Contributor Author

with 1GB (1/4th) allotted:

root@kevin:/opt/eclipse/kura/bin# jps
130705 Jps
130612 org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar
root@kevin:/opt/eclipse/kura/bin# jps -lv
130612 /opt/eclipse/kura/plugins/org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar -Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/kura-heapdump.hprof -XX:ErrorFile=/var/log/kura-error.log -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-modules=ALL-SYSTEM -Dkura.os.version=raspbian -Dkura.arch=generic-arm64 -Dtarget.device=generic-aarch64 -Declipse.ignoreApp=true -Dkura.home=/opt/eclipse/kura -Dkura.configuration=file:/opt/eclipse/kura/framework/kura.properties -Dkura.custom.configuration=file:/opt/eclipse/kura/user/kura_custom.properties -Ddpa.configuration=/opt/eclipse/kura/packages/dpa.properties -Dlog4j.configurationFile=file:/opt/eclipse/kura/log4j/log4j.xml -Djava.security.policy=/opt/eclipse/kura/framework/jdk.dio.policy -Djdk.dio.registry=/opt/eclipse/kura/framework/jdk.dio.properties -Djdk.tls.trustNameService=true -Dosgi.console=5002 -Declipse.consoleLog=true
131791 jdk.jcmd/sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-11-openjdk-arm64 -Xms8m -Djdk.module.main=jdk.jcmd
root@kevin:/opt/eclipse/kura/bin# jcmd 125501^CC.heap_info
root@kevin:/opt/eclipse/kura/bin#
root@kevin:/opt/eclipse/kura/bin#
root@kevin:/opt/eclipse/kura/bin# jcmd 130612 GC.heap_info
130612:
garbage-first heap total 524288K, used 324846K [0x00000000e0000000, 0x0000000100000000)
region size 1024K, 283 young (289792K), 5 survivors (5120K)
Metaspace used 53146K, committed 54656K, reserved 1097728K
class space used 6139K, committed 6720K, reserved 1048576K
root@kevin:/opt/eclipse/kura/bin#

@nicolatimeus
Copy link
Contributor

is it safe to use MemTotal

According to procfs documentation [1] MemTotal reports "Total usable RAM (i.e., physical RAM minus a few reserved bits and the kernel binary code).". What happens if the system has 1GB of physical memory?

[1] https://man7.org/linux/man-pages/man5/proc.5.html

@GregoryIvo
Copy link
Contributor Author

is it safe to use MemTotal

According to procfs documentation [1] MemTotal reports "Total usable RAM (i.e., physical RAM minus a few reserved bits and the kernel binary code).". What happens if the system has 1GB of physical memory?

[1] https://man7.org/linux/man-pages/man5/proc.5.html

in theory, it will report less than 1024, and the default set in the profile will be used. (unchanged)

@GregoryIvo GregoryIvo marked this pull request as ready for review October 27, 2023 15:41
@GregoryIvo
Copy link
Contributor Author

GregoryIvo commented Oct 30, 2023

With the changes today:

root@kevin:/opt/eclipse/kura/bin# cat start_*
#!/bin/sh

# Kura should be installed to the /opt/eclipse directory.
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/opt/jvm/bin:/usr/java/bin:$PATH
export MALLOC_ARENA_MAX=1

DIR=$(cd $(dirname $0)/..; pwd)
cd $DIR

# set up the configuration area
mkdir -p /tmp/.kura/configuration
cp ${DIR}/framework/config.ini /tmp/.kura/configuration/

KURA_RUNNING=`ps ax | grep java | grep "org.eclipse.equinox"`

#get java version
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
JAVA_VERSION_NUM=$(echo "$JAVA_VERSION" | awk -F. '{printf("%03d%03d",$1,$2);}')

OPEN_MODULE_OPTIONS=''

if [ $JAVA_VERSION_NUM -gt 001008 ] ; then
        OPEN_MODULE_OPTIONS="--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED"
fi

if [ -z "$KURA_RUNNING" ] ; then
  nohup java -Xms948m -Xmx948m \
        -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/kura-heapdump.hprof \
        -XX:ErrorFile=/var/log/kura-error.log \
        -XX:+IgnoreUnrecognizedVMOptions \
        ${OPEN_MODULE_OPTIONS} \
        --add-modules=ALL-SYSTEM \
        -Dkura.os.version=raspbian \
        -Dkura.arch=generic-arm64 \
        -Dtarget.device=generic-aarch64 \
        -Declipse.ignoreApp=true \
        -Dkura.home=${DIR} \
        -Dkura.configuration=file:${DIR}/framework/kura.properties \
        -Dkura.custom.configuration=file:${DIR}/user/kura_custom.properties \
        -Ddpa.configuration=${DIR}/packages/dpa.properties \
        -Dlog4j.configurationFile=file:${DIR}/log4j/log4j.xml \
        -Djava.security.policy=${DIR}/framework/jdk.dio.policy \
        -Djdk.dio.registry=${DIR}/framework/jdk.dio.properties \
        -Djdk.tls.trustNameService=true \
        -Dosgi.console=5002 \
        -Declipse.consoleLog=true >> /var/log/kura-console.log 2>> /var/log/kura-console.log \
        -jar ${DIR}/plugins/org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar \
        -configuration /tmp/.kura/configuration &

    #Save the PID
    KURA_PID=$!
    echo "Kura Started (pid="$KURA_PID") ..." >> /var/log/kura-console.log
    echo $KURA_PID > /var/run/kura.pid
else
    echo "Failed to start Kura. It is already running ..." >> /var/log/kura-console.log
fi
        #!/bin/sh

export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/opt/jvm/bin:/usr/java/bin:$PATH
export MALLOC_ARENA_MAX=1

DIR=$(cd $(dirname $0)/..; pwd)
cd $DIR

# set up the configuration area
mkdir -p /tmp/.kura/configuration
cp ${DIR}/framework/config.ini /tmp/.kura/configuration/

KURA_RUNNING=`ps ax | grep java | grep "org.eclipse.equinox"`

#get java version
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
JAVA_VERSION_NUM=$(echo "$JAVA_VERSION" | awk -F. '{printf("%03d%03d",$1,$2);}')

OPEN_MODULE_OPTIONS=''

if [ $JAVA_VERSION_NUM -gt 001008 ] ; then
        OPEN_MODULE_OPTIONS="--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED"
fi

if [ -z "$KURA_RUNNING" ] ; then
        exec java -Xms948m -Xmx948m \
        -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/log/kura-gc.log \
        -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M \
        -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/kura-heapdump.hprof \
        -XX:ErrorFile=/var/log/kura-error.log \
        -XX:+IgnoreUnrecognizedVMOptions \
        ${OPEN_MODULE_OPTIONS} \
        --add-modules=ALL-SYSTEM \
        -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
        -Dkura.os.version=raspbian \
        -Dkura.arch=generic-arm64 \
        -Dtarget.device=generic-aarch64 \
        -Declipse.ignoreApp=true \
        -Dkura.home=${DIR} \
        -Dkura.configuration=file:${DIR}/framework/kura.properties \
        -Dkura.custom.configuration=file:${DIR}/user/kura_custom.properties \
        -Ddpa.configuration=${DIR}/packages/dpa.properties \
        -Dlog4j.configurationFile=file:${DIR}/log4j/log4j.xml \
        -Djava.security.policy=${DIR}/framework/jdk.dio.policy \
        -Djdk.dio.registry=${DIR}/framework/jdk.dio.properties \
        -Djdk.tls.trustNameService=true \
        -Dosgi.console \
        -Declipse.consoleLog=true \
        -jar ${DIR}/plugins/org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar \
        -configuration  /tmp/.kura/configuration
else
        echo "Failed to start Kura. It is already running ..."
fi
        #!/bin/sh

export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/opt/jvm/bin:/usr/java/bin:$PATH
export MALLOC_ARENA_MAX=1

DIR=$(cd $(dirname $0)/..; pwd)
cd $DIR

# set up the configuration area
mkdir -p /tmp/.kura/configuration
cp ${DIR}/framework/config.ini /tmp/.kura/configuration/

KURA_RUNNING=`ps ax | grep java | grep "org.eclipse.equinox"`

#get java version
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
JAVA_VERSION_NUM=$(echo "$JAVA_VERSION" | awk -F. '{printf("%03d%03d",$1,$2);}')

OPEN_MODULE_OPTIONS=''

if [ $JAVA_VERSION_NUM -gt 001008 ] ; then
        OPEN_MODULE_OPTIONS="--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED"
fi

if [ -z "$KURA_RUNNING" ] ; then
        exec java -Xms948m -Xmx948m \
        -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/kura-heapdump.hprof \
        -XX:ErrorFile=/var/log/kura-error.log \
        -XX:+IgnoreUnrecognizedVMOptions \
        ${OPEN_MODULE_OPTIONS} \
        --add-modules=ALL-SYSTEM \
        -Dkura.os.version=raspbian \
        -Dkura.arch=generic-arm64 \
        -Dtarget.device=generic-aarch64 \
        -Declipse.ignoreApp=true \
        -Dkura.home=${DIR} \
        -Dkura.configuration=file:${DIR}/framework/kura.properties \
        -Dkura.custom.configuration=file:${DIR}/user/kura_custom.properties \
        -Ddpa.configuration=${DIR}/packages/dpa.properties \
        -Dlog4j.configurationFile=file:${DIR}/log4j/log4j.xml \
        -Djava.security.policy=${DIR}/framework/jdk.dio.policy \
        -Djdk.dio.registry=${DIR}/framework/jdk.dio.properties \
        -Djdk.tls.trustNameService=true \
        -Dosgi.console \
        -Declipse.consoleLog=true \
        -jar ${DIR}/plugins/org.eclipse.equinox.launcher_1.5.800.v20200727-1323.jar \
        -configuration  /tmp/.kura/configuration
else
        echo "Failed to start Kura. It is already running ..."
fi
        root@kevin:/opt/eclipse/kura/bin# 

Correctly Assigned RAM:
image

@MMaiero MMaiero merged commit 17814c7 into eclipse-kura:develop Nov 2, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants