I’m using the new Garbage Collector, and in my cod...
# kotlin-native
l
I’m using the new Garbage Collector, and in my code I was unintentionally allocating a large UIntArray (~1.3MB) in a loop. The array was only referenced inside the loop. I got a crash on iOS and the stack trace shows that the symbol is
kotlin::mm::internal::ObjectFactoryStorage<8ul, kotlin::mm::internal::AllocatorWithGC<kotlin::mm::internal::SimpleAllocator, kotlin::gc::SameThreadMarkAndSweep::ThreadData> >::Node::~Node:
and the error is
Thread 1: EXC_BAD_ACCESS (code=1, address=0xff000000ff000000)
How can I confirm if this is a GC bug?
The Stack Trace shows that this happens inside the UIntArray constructor.
Moving the allocation of the array outside of the loop (it will always have the same size, and always be written to from start to end in the loop) and re-using the array seemed to fix the crash, but in theory, the Garbage Collector should have been able to collect the previous arrays before, just with a large performance hit.
a
Thanks for the report! A couple of questions: • which version of Kotlin are you using? • is it a debug or a release build? • also, could you share the full stack trace?
l
I am using 1.6.10 and the structure of my project is a library with a test app. I compile the library to a static library (.a file) on iOS and a shared library (.so file) on Android and link against the debug artifact in each test app. I only run into this issue on the iOS test app. I have not seen the crash using the Android NDK in the Android test app.
I can see if I can re-create the issue later today to get you a full stack trace.
I can't seem to reproduce the crash. The same code that consistently crashed during allocation of the UIntArray now runs fine, but the memory grows steadily, getting over 1GB, indicating the old arrays are not getting gc'ed.
a
Thanks!
the memory grows steadily, getting over 1GB
That's indeed weird: in 1.6.10 the GC scheduler should invoke GC after every 10MiB of Kotlin objects allocated; so if the array is ~1.3MiB, the GC should be called at least once every 8 iterations. Just to be clear, if
UIntArray
creation is pulled out of the loop, the memory growth goes away?
l
Yes. The memory usage stays steady near 120MB.
a
From what I can tell, this memory usage pattern comes from the system allocator: we do free the objects promptly, but the system keeps rather large underlying buffer. Also, starting with 1.6.20 we switched the allocator from system to mimalloc, which may help here.
l
That's interesting. I saw that y'all switched to mimalloc when I was looking at the kotlin native runtime code for another side project. I'll have to check this again when 1.6.20 is released. In the meantime, allocating the array inside the loop was a bug, so I switched to allocating it once outside and re-using it, which works much better.