20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored

Chapter 10: Scalability & System AdminLesson 57 of 65

How to Configure Mango JVM Memory Settings

Tune Java Virtual Machine memory allocation for Mango by Radix IoT to optimize performance based on your deployment size, avoid out-of-memory errors, and maintain system stability.

  • 8 min read
  • Advanced
  • Mango 4.x / 5.x

Overview

Mango by Radix IoT runs on the Java Virtual Machine (JVM). The JVM's memory allocation directly affects Mango's performance, stability, and ability to handle large numbers of data points. Too little memory causes crashes and slow performance; too much wastes server resources.

JVM Memory Basics

  • Heap memory (-Xmx) — the main memory pool where Mango stores objects, caches, and runtime data. This is the most important setting to tune
  • Initial heap (-Xms) — memory allocated at startup. Setting equal to -Xmx avoids dynamic resizing
  • Metaspace — memory for class definitions. Rarely needs tuning for Mango
  • Stack size (-Xss) — per-thread stack memory. Rarely needs tuning

Where to Set JVM Memory

Set heap flags in Mango's startup options file — not in mango.properties (formerly env.properties) for normal installs:

Installation TypeConfiguration Location
Linux (script or service)<data directory>/start-options.sh (create if missing). The launcher resolves it from the paths.start.options property, which defaults to start-options.sh inside the data directory; the data directory itself defaults to <mango-home> unless paths.data is set.
WindowsNo equivalent options file. The shipped launcher mango.cmd runs java -jar boot\ma-bootstrap.jar with no heap flags and reads neither start-options.sh nor mango.vmoptions — both are sourced by start-mango.sh on Linux only. Set heap through your Windows service wrapper's own configuration, or a JVM environment variable such as JDK_JAVA_OPTIONS. Confirm the supported route with Radix IoT before relying on it.

Example for Linux (start-options.sh):

# Heap size — restart Mango after changing
MA_JAVA_OPTS="$MA_JAVA_OPTS -Xms2g -Xmx2g"

There is no Windows equivalent of this file. mango.cmd launches the bootstrap jar directly and reads no options file, so the snippet above applies to Linux only.

Mango also supports a JVM options file: paths.vm.options defaults to mango.vmoptions in the data directory, and when present the launcher passes it to the JVM as -XX:VMOptionsFile. Either mechanism works; start-options.sh is the one most installs use.

Verify what actually took effect: start-mango.sh prints "Starting Mango with options '…'" with the assembled MA_JAVA_OPTS before it launches the JVM. If your flags are not in that line, the file you edited is not the one being read.

Warning

Mango treats an out-of-memory error as fatal, because it relies on in-memory caches, and its shipped start-options.sh says these two “should be enabled for all production systems”. They are commented out by default, so on a production instance uncomment them: -XX:+ExitOnOutOfMemoryError to terminate the JVM rather than limp on, and -XX:+HeapDumpOnOutOfMemoryError (with -XX:HeapDumpPath=) to leave something to diagnose.

Two things about the shipped file are worth knowing before you copy from it. Its garbage-collection section offers UseConcMarkSweepGC, UseSerialGC, UseParallelGC and UseParallelOldGC but not G1, and UseConcMarkSweepGC was removed from the JVM in Java 14 — so that list is older than the Java you are probably running. And its last block is nine --add-exports / --add-opens flags marked "required to use the chroniclePointValueCache module": Chronicle is not only an extra memory consumer, it needs JVM flags to run at all. The same flags ship in mango.vmoptions.

Recommended Memory Sizes

Heap depends on point count and on how those points are driven. Polling data sources hold far less in the heap than script-driven points, so the same point count can need very different heaps.

Data PointsMostly polling (BACnet, Modbus, SNMP)MixedScript heavy (Meta, Scripting)
Under 5001 to 2 GB2 GB2 to 3 GB
500 to 5,0002 to 4 GB4 GB4 to 6 GB
5,000 to 20,0004 to 8 GB6 to 10 GB8 to 12 GB
20,000 to 50,0008 to 12 GB10 to 16 GB12 to 20 GB
50,000 to 150,00012 to 20 GB16 to 24 GB20 to 32 GB

Sizing server RAM: budget the heap figure above plus 3 GB for the JVM's non-heap memory, plus the database allocation, plus 4 GB or more for the OS and page cache. Account separately for anything else running outside the JVM allocation — Chronicle's off-heap point value cache and any co-hosted services need memory of their own, and none of it comes out of -Xmx.

Tip

Do not size from the table alone if the instance is already running. Measure the live heap with the garbage-collection method below and size against the measured figure.

Symptoms of Insufficient Memory

SymptomLikely Cause
Mango crashes with "OutOfMemoryError" in ma.logHeap too small for the workload
UI becomes very slow periodicallyFrequent garbage collection pauses (heap nearly full)
Data sources stop polling temporarilyGC pauses interrupting poll threads
Charts take long to loadNot enough memory to cache query results
Mango uses 100% CPU for extended periodsGC thrashing — trying to free memory but can't

Monitoring JVM Memory

Monitor memory usage to validate your settings:

  • Internal metrics — System status is superadmin-only and not in the menu, so open Administration → Admin home, click More details on the Server status card, and choose Internal metrics under Choose a section. It lists JVM used memory (MB), JVM free memory (MB), and JVM maximum available memory (MB), so you can compare the live heap against the -Xmx you set
  • Internal Data Source — create data points for JVM memory, enabling trending and alerts
  • ma.log — OutOfMemoryError entries indicate immediate action needed
  • OS tools — top, htop, or Task Manager show total Java process memory

Tuning Tips

  • Set -Xms equal to -Xmx — prevents JVM from spending time resizing the heap. Allocate what you need upfront
  • Don't over-allocate — giving the JVM 28 GB on a 32 GB server leaves no room for the OS and database. This causes swapping and worse performance than a smaller heap
  • Use G1GC — the G1 garbage collector (default in modern Java) handles large heaps well. No change needed for most deployments
  • Restart after changes — JVM memory settings only take effect at startup
  • Monitor after changing — watch memory usage for 24-48 hours after a change to verify the new settings are appropriate

Garbage Collection Tuning

For most Mango deployments, the default garbage collector works fine. If you experience GC pauses:

# Enable G1GC with pause target (if not already default)
MA_JAVA_OPTS="$MA_JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

Only tune GC settings if you're experiencing specific problems and have monitoring data to guide decisions.

Measuring the Right Heap Size with Garbage Collection

Garbage collection is the most reliable way to learn the heap a given instance actually needs. Force a collection, then read the live set:

PID=$(cat <data directory>/ma.pid)
JAVA=<JAVA_HOME>/bin
sudo -u mango $JAVA/jcmd $PID GC.run
sudo -u mango $JAVA/jcmd $PID GC.heap_info

The PID file is ma.pid in the data directory by default (paths.pid.file), written by start-mango.sh when it launches the JVM.

Read the used figure from the line beginning garbage-first heap.

Four rules make the measurement valid:

  1. Run GC.run first. GC.heap_info on its own reports live objects plus uncollected garbage. On one measured instance that was 14.5 GiB against a true 10.26 GiB — a 41% overstatement that would have wasted 4 GB of heap.
  2. Wait for a full daily cycle. Script engines compile lazily: a function is compiled and retained the first time it runs, so scripts on hourly, daily, or weekly schedules contribute nothing to the heap until they fire. Measure at least 24 hours after start, and longer if any schedule is weekly or monthly.
  3. Measure with the final configuration in place. A live set measured with a module disabled is not valid once that module is enabled. One instance read 4.36 GiB with chroniclePointValueCache disabled and 10.26 GiB with it enabled; sizing against the earlier number produced a heap that thrashed.
  4. Run the tools as the JVM's own user. jstat reads a shared memory file owned by the service account and fails with Operation not permitted for any other user — including root, in some configurations.

Troubleshooting

IssueCauseFix
OutOfMemoryError: Java heap spaceHeap too smallIncrease -Xmx; check for memory leaks if problem persists
Mango won't start after increasing memoryMore RAM requested than availableReduce -Xmx to fit within available RAM
OS is swapping heavilyJVM + database + OS exceed physical RAMReduce JVM heap or add more RAM
Intermittent slowness every few minutesGC pauses on undersized heapIncrease heap; monitor GC logs

Summary

JVM memory configuration is critical for Mango stability and performance. Set -Xmx from both point count and workload type — script-heavy deployments need materially more heap than polling-only ones at the same point count. Keep -Xms equal to -Xmx. Size server RAM as heap plus 3 GB plus the database allocation plus 4 GB or more for the OS and page cache, and measure the live heap with GC.run followed by GC.heap_info rather than sizing from the table alone. Address OutOfMemoryErrors immediately — they indicate the system is undersized for the workload.

Get free access to all 65 Mango by Radix IoT training lessons

One short form unlocks every lesson and its video in this browser.

This form is hosted by Zoho. It loads only after you enable support cookies or choose to load it below.

We honored your browser’s Global Privacy Control signal — optional cookies are off and nothing is tracked.