performancekotlinmemoryjvmcompose-multiplatform

native memory leak of compose multiplatform


We have a native memory issue in our kotlin compose multiplatform application which targets jvm on desktop (using amazon java as runtime) and android. In order to fully benchmark our performance, I chose to repeat a set of expected user interactions on our app, in a fixed amount of time with the same speed, and then profile our performance. On android, our RAM usage this:

Android

enter image description here

Our problem is on desktop platform (linux, windows, macOs, they all have the same problem ). As I said, Heap + non-heap memory seems to be working just fine, graphed by different tools, and tested by playing with -Xmx values. I am sure there is no heap memory leak.

Heap

[Heap ram usage captured with jProfiler](https://i.sstatic.net/Tp9YMXwJ.png)

My non-heap memory ( codecash, heap space) is also just fine.

but when I measure the actual memory footage of the process:

Native

[Native ram footage on OS](https://i.sstatic.net/lQCodjB9.png) It is increased to 1.2 gigabytes!

Java NMI

I tried Java NMT , and I got the following:

java native memory capture with jcmd

Edit: More Info:

jemalloc

I also used jemalloc profiler: enter image description here

Questions


Solution

  • I ended up watching this resource. In linux, after using pmap in terminal, and sorting the output based on PSS memory usage ( which I had read was a better way that RSS in this article ), I realized there are many memory sections around 65 megabytes in my process:

    enter image description here

    If such thing happens ( you have so many blocks with 2^16 bytes of memory ), this probably means there is something wrong with the standard memory allocator that is malloc(Which seems to happen because ByteBuffer type in java uses memory directly with malloc and there is problem when releasing it ). So I changed malloc to jemalloc ( and after that to mimalloc ) and it worked! Right now our process has no longer these memory sections. although It's native memory usage can stil reach the same 1.2 limit, it generously frees up resources at specific points ( and drops to a baseline of 450 MB ) , as compared to when it did not really free anything as in malloc.

    Update: After further investigation, we I understood that the problem was with the skiko-windows-x64.dll ( a shared dll used by basically the entire compose multiplatform library ). This file manages all it's memory allocations by itself, and can not be tracked by usual java memory profiling tools ( like jprofiler, yourkit, jconsole or even with java native memory tracking ). Seems like our code is using the compose Canvas function in a way that makes the .dll consume so much memory, and seems like mimalloc and jemalloc could handle this pattern of memory usage better than malloc.