Hi all Igniters, I am trying to minimize Ignite's memory consumption on my server.
Some background: My server has 16GB RAM, and is supposed to run applications other than Ignite. I use Ignite to store a cache. I use the TRANSACTIONAL_SNAPSHOT mode and I don't use persistence (configuration file attached). To read and update the cache I use SQL queries, through ODBC Client in C++ and through an embedded client-mode node in C#. My data consists of a table with 5 columns, and I guess around tens of thousands of rows. Ignite metrics tell me that my data takes 167MB ("CFGDataRegion region [used=167MB, free=67.23%, comm=256MB]", This region contains mainly this one cache). At the beginning, when I didn't tune the JVM at all, the Apache.Ignite process consumed around 1.6-1.9GB of RAM. After I've done some reading and research, I use the following JVM options which have brought the process to consume around 760MB as of now: -J-Xms512m -J-Xmx512m -J-Xmn64m -J-XX:+UseG1GC -J-XX:SurvivorRatio=128 -J-XX:MaxGCPauseMillis=1000 -J-XX:InitiatingHeapOccupancyPercent=40 -J-XX:+DisableExplicitGC -J-XX:+UseStringDeduplication Currently Ignite is up for 29 hours on my server. When I only started the node, the Apache.Ignite process consumed around 600MB (after my data insertion, which doesn't change much after), and as stated, now it consumes around 760MB. I've been monitoring it every once in a while and this is not a sudden rise, it has been rising slowly but steadily ever since the node has started. I used DBeaver to look into node metrics system view <https://apacheignite.readme.io/docs/node_metrics>, and I turned on the garbage collector logs. The garbage collector log shows that heap is constantly growing, but I guess this is due to the SQL queries and their results being stored there. (There are a few queries in a second, the results normally contain one row but can contain tens or hundreds of rows). After every garbage collection the heap usage is between 80-220MB. This is in accordance to what I see under HEAP_MEMORY_USED system view metric. Also, I can see that NONHEAP_MEMORY_COMITTED is around 102MB and NONHEAP_MEMORY_USED is around 98MB. My question is, what could be causing the constant growth in memory usage? What else consumes memory that doesn't appear in these metrics? Thanks for your help!
<!-- Ignite Spring configuration file to startup Ignite cache. This file demonstrates how to configure cache using Spring. Provided cache will be created on node startup. Use this configuration file when running HTTP REST examples (see 'examples/rest' folder). When starting a standalone node, you need to execute the following command: {IGNITE_HOME}/bin/ignite.{bat|sh} examples/config/example-cache.xml When starting Ignite from Java IDE, pass path to this file to Ignition: Ignition.start("examples/config/example-cache.xml"); --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> <property name="discoverySpi"> <bean class="org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi"> <property name="zkConnectionString" value="vmnero:2181"/> <property name="sessionTimeout" value="30000"/> <property name="zkRootPath" value="/apacheIgnite"/> <property name="joinTimeout" value="10000"/> </bean> </property> <property name="clientConnectorConfiguration"> <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration"> <property name="host" value="0.0.0.0"/> <property name="port" value="11110"/> <property name="portRange" value="1"/> </bean> </property> <property name="ConnectorConfiguration.jettyPath" value="config\ignite_rest.xml"/> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <property name="dataRegionConfigurations"> <list> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="name" value="CFGDataRegion"/> <property name="initialSize" value="#{256L * 1024 * 1024}"/> <property name="maxSize" value="#{512L * 1024 * 1024}"/> <property name="persistenceEnabled" value="false"/> <property name="metricsEnabled" value="true"/> </bean> </list> </property> <!-- define Ignite's default data region's size --> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="name" value="Default_Region"/> <property name="initialSize" value="#{32L * 1024 * 1024}"/> </bean> </property> </bean> </property> <property name="cacheConfiguration"> <list> <bean parent="cfg-cache-template"> <property name="name" value="CFGCache"/> </bean> <bean parent="cfg-invalidated-cache-template"> <property name="name" value="CFGInvalidatedPathsCache"/> </bean> </list> </property> </bean> <!-- Template for CFG cache configurations --> <bean id="cfg-cache-template" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration"> <property name="groupName" value="CFGCacheGroup"/> <property name="cacheMode" value="REPLICATED"/> <property name="dataRegionName" value="CFGDataRegion"/> <property name="LoadPreviousValue" value="false"/> <property name="ReadFromBackup" value="false"/> <property name="atomicityMode" value="TRANSACTIONAL_SNAPSHOT"/> <property name="queryEntities"> <list> <bean class="org.apache.ignite.cache.QueryEntity"> <property name="keyType" value="java.lang.String"/> <property name="keyFieldName" value="path"/> <property name="valueType" value="Algotec.Cfg.DataGridCache.EntryData.CFG_CacheData"/> <property name="tableName" value="CFGCacheTable"/> <property name="fields"> <map> <entry key="path" value="java.lang.String"/> <entry key="CfgValue" value="java.lang.String"/> <entry key="IsValid" value="java.lang.Boolean"/> <entry key="IsSubTree" value="java.lang.Boolean"/> <entry key="lastInvalidationTime" value="java.sql.Timestamp"/> </map> </property> </bean> </list> </property> </bean> <bean id="cfg-invalidated-cache-template" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration"> <property name="groupName" value="CFGCacheGroup"/> <property name="cacheMode" value="REPLICATED"/> <property name="dataRegionName" value="CFGDataRegion"/> <property name="atomicityMode" value="TRANSACTIONAL_SNAPSHOT"/> <property name="LoadPreviousValue" value="false"/> <property name="ReadFromBackup" value="false"/> <property name="queryEntities"> <list> <bean class="org.apache.ignite.cache.QueryEntity"> <property name="keyType" value="java.lang.String"/> <property name="keyFieldName" value="path"/> <property name="valueType" value="java.lang.String"/> <property name="tableName" value="CFGInvalidatedTable"/> <property name="fields"> <map> <entry key="path" value="java.lang.String"/> </map> </property> </bean> </list> </property> </bean> <!-- Template for CFGConnector cache configurations --> <bean id="cfg-connector-cache-template" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration"> <property name="groupName" value="CFGConnectorCacheGroup"/> <property name="cacheMode" value="REPLICATED"/> <!-- Defines this cache to run under the CFGConnectorDataRegion --> <property name="dataRegionName" value="CFGConnectorDataRegion"/> <property name="LoadPreviousValue" value="false"/> <property name="ReadFromBackup" value="false"/> <property name="expiryPolicyFactory"> <bean class="javax.cache.expiry.TouchedExpiryPolicy" factory-method="factoryOf"> <constructor-arg> <bean class="javax.cache.expiry.Duration"> <constructor-arg value="MINUTES"/> <constructor-arg value="10"/> </bean> </constructor-arg> </bean> </property> </bean> </beans>