Is it possible to disable GC in Kotlin/Native for ...
# kotlin-native
p
Is it possible to disable GC in Kotlin/Native for iOS? We see for instance when referencing ARFrames huge lags, as K/N retains instances and a GC cycles is roughly 30secs away. We can mitigate it only with a forceGC after every delegate callback.
b
What would be the alternative?
FWIW, I saw PRs recently that looked like prep for being able to profile the GC. You should submit sample code (GH issue). Might be able to see the perf issue fixed!
p
It is not a perf issue. The issue ist due to the low object count on mainThread. We do not generate sufficient objects to hit gcThreshold. Consequently, gc is not run. But ARKit tries to recycle and hits a barrier after 16 ARFrame not being released. I think the entire GC model is counter-intuitive for ARC ObjC/Swift interop as final release of NSObject.toKotlin wrapped ObjC instances is not garantueed with running out of scope. Especially if using non-local memory frames (e.g. we process ARFrame on different DispatchQueues)
👍 1
k
I’d be interested in seeing some code. Also, try with 1.3.31 instead of 1.3.40. In earlier versions, there was no threshold. Once refcount was zero, it would release the object and do whatever shutdown work was expected.
If that performs as expected, I think you have a good case for treating some objects differently
Presumably (I could look and confirm, but busy at the moment) objc interop runs objc destructor on killing the instance, and from what you describe, it sounds like ARKit needs to release resources? I’ve never looked at it. However, if that’s the case, and it seems logical (or at least some library might need that), then immediate GC on that instance for interop might be needed
If you need 1.3.40, I know this is more effort, but clone and build Kotlin Native locally at 1.3.40, but change the thresholds to be much lower and see what happens. You can point your project at a local KN with the following. In
gradle.properties
, add
org.jetbrains.kotlin.native.home=/[your directory]/kotlin-native/dist
I just looked at your github and see you have KN forked (and Stately and Testhelp. I would update them soon). Seems like you’ve built KN before, and you know about the threshold, so I probably don’t need to point in a direction, but the GC stuff if mostly here: https://github.com/idstein/kotlin-native/blob/master/runtime/src/main/cpp/Memory.cpp#L70
p
Can you explain what is the difference between the relaxed and strict memory model?
k
Not yet
Have to play with it, and it’s not done yet
p
If you have any update on with your experience that would be great. From Memory.cpp it looks like relaxed mode would do a direct GC on reference release https://github.com/JetBrains/kotlin-native/blob/81eb6b2be689591b4bd697464c910afdc0f2a456/runtime/src/main/cpp/Memory.cpp#L1296
k
The far bigger question about relaxed mode is if that will allow shared mutable data. If everything is shared there will be performance implications but the first pass was committed this past week so it’s very early
p
Good point. We have a programming model that only allows to pass immutable data classes and a frozen callback via DispatchQueues. So we comply with having immutable data (yet) not frozen data. Only our operations are frozen and we ensure that a single data point is only attached to a single thread at any moment
o
you could control GC threshold with those APIs: https://github.com/JetBrains/kotlin-native/blob/712c056a547b0da1ea7dfca38e3b452d75e0bff7/runtime/src/main/kotlin/kotlin/native/internal/GC.kt#L62. Strict model is memory model with more strict concurrency guarantees, relaxed mode is (unfinished, as cyclic garbage leaks) mode where behavior is more similar to Objective-C runtime, where mutable object can be accessed concurrently and such.
👌 1
🙏 4
p
Thx a lot for the clarification. We tried changing threshold, but the value does not seem to be fixed as „ergonomics“ GC will automatically increase low thresholds. What works for us is currrently only
GC.collect
. We basically call it at the end of every scheduled C Block on DispatchQueues and at critical places in our MainThread, e.g. in our ARSessionDelegate
o
You can periodically reset threshold, and maybe we can provide API to suspend ergonomics
k
As you can imagine, curious about relaxed mode. I have a ton of questions, but will just wait for code updates. Timing wise, though, is that a 1.3.50 thing?
2
o
it is not decided, but anyway it’s an experimental mode of operations
n
relaxed mode sounds awesome, looking forward to it 🙏