I’m worried that capturing a stack trace on Kotlin...
# coroutines
j
I’m worried that capturing a stack trace on Kotlin/Native + iOS is much more expensive than on Android. We’re using coroutines and flows on iOS, and canceling them a lot, and the performance on iOS is bad! I was looking at a thread dump and see quite a lot of work is required to build a stack trace:
Copy code
Thread 9:: Treehouse
0   dyld_sim                      	       0x10af12f48 strcmp + 4
1   dyld_sim                      	       0x10af096c4 invocation function for block in dyld3::MachOLoaded::findSectionContent(char const*, char const*, unsigned long long&, bool) const + 44
2   dyld_sim                      	       0x10af05c48 invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 488
3   dyld_sim                      	       0x10af049ac dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 284
4   dyld_sim                      	       0x10af04cb8 dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 164
5   dyld_sim                      	       0x10af09670 dyld3::MachOLoaded::findSectionContent(char const*, char const*, unsigned long long&, bool) const + 108
6   dyld_sim                      	       0x10aefc878 dyld4::APIs::_dyld_find_unwind_sections(void*, dyld_unwind_sections*) + 288
7   libunwind.dylib               	       0x1bde56700 0x1bde51000 + 22272
8   libunwind.dylib               	       0x1bde5aa58 0x1bde51000 + 39512
9   libc++abi.dylib               	       0x18028df84 0x18027c000 + 73604
10  libunwind.dylib               	       0x1bde5a310 0x1bde51000 + 37648
11  libunwind.dylib               	       0x1bde5a1a8 0x1bde51000 + 37288
12  libc++abi.dylib               	       0x18028db2c 0x18027c000 + 72492
13  Cash                          	       0x107fb5788 ExceptionObjHolder::Throw(ObjHeader*) + 64
14  Cash                          	       0x107fb5748 ThrowException + 12
15  Cash                          	       0x10760cb3c kfun:kotlinx.coroutines.flow.StateFlowImpl.$collectCOROUTINE$0.invokeSuspend#internal + 1336 (StateFlow.kt:383)
16  Cash                          	       0x107ba1504 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#invokeSuspend(kotlin.Result<kotlin.Any?>){}kotlin.Any?-trampoline + 68 (ContinuationImpl.kt:50)
17  Cash                          	       0x10743bd78 <inlined-out:<anonymous>> + 120 (ContinuationImpl.kt:30) [inlined]
18  Cash                          	       0x10743bd78 kfun:kotlin#with(0:0;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}0:1 + 120 (Standard.kt:70) [inlined]
Would y’all consider promoting something like StacklessCancellationException from TakeBenchmark.kt to something we could use in production?
🔖 2
👀 3
k
Would this manifest in the public API as something like
Job#cancelStackless()
?
Or are you envisioning more of a configuration that would replace all cancellations with
StacklessCancellationException
?
j
Maybe I just need to create my own stackless exception class and use that when I cancel
But I believe the default is super slow
l
I'm wondering if union types will bring stacktrace-free cancellation in kotlinx.coroutines later down the road 🤔
z
I thought coroutines on jvm disable stack trace collection by default for CancellationExceptions, at least when they have no message. I added some messages once and it tanked our benchmarks because of that. Seems like a bug if iOS isn’t doing the same