-
Notifications
You must be signed in to change notification settings - Fork 1.9k
FastServiceLoader performs I/O on calling thread and prevents R8 optimization #1231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The developer still has to disable the FastServiceLoader manually if they're using R8. R8 is then able to optimize away the ServiceLoader and reflection entirely, resulting in direct class instantiation and no extra I/O on calling thread. Fixes Kotlin#1231
So if I understand this correctly, I'll need both a version of coroutine with #1232 and R8 with https://issuetracker.google.com/issues/120436373 fix to mitigate the issue, right? |
Yes, precisely. Once you have both the patched coroutines version and R8 from 1.5.x branch enabled, you will also need to disable the FastServiceLoader before any accesses to Dispathers.Main: I am working on making this automatic, but we need a new mechanism for reading R8-specific rules, so it won't come until Android Studio 3.6 at least, possibly later. For everyone on current Android Studio versions, you'll have to set the property manually. |
You can also add
to do this at compile-time with R8 instead of at runtime with a property. Your APK also gets a teeeeeeny bit smaller! |
@JakeWharton / @wojtek-kalicinski Sorry to bother you but I'm having an hard time checking the resulting byte code after those optimisations. I do not really understand what result should R8 generate, but I still see normal ServiceLoader calls (And correctly not the fast one so the assume values part did work) is this normal or is the R8 ServiceLoader optimisation not applied? Using R8 1.5.68 that is supposed to have the fix according to this thread. Would love a confirmation to finally drop my custom code after the initial report I made about this (#878)
|
Hey, the fix should work with AGP 3.6.0-alpha08 and coroutines 1.3.0. Unfortunately even though R8 1.5.x branch should support the optimization, there is a keep rule in coroutines that prevents it from working. (at least that's what I think is happening) A workaround in AGP 3.6.0-alpha08 makes sure that rule doesn't apply and hence R8 can optimize the ServiceLoader (on release builds). Please let me know if it works for you |
Thanks, I can confirm that latest R8 master seems to produce a proper bytecode. Unfortunately I'm not ready for R8 1.6 yet and will do my usual bug reports with Jinseong if any when AS 3.6 reach beta. After dozen of issues reported for 1.4/1.5 I'm playing safe now :) It may worth to add a note somewhere about the fact that it won't work with 1.5 as without checking bytecode they could think it works.
|
The fix to #878 that introduces a FastServiceLoader to mitigate the fact that ServiceLoader implementation on Android is slow is still inadequate for Android apps and moreover, the solution prevents the R8 optimization from working.
For Android apps to avoid doing I/O on the main thread, we should
ServiceLoader.load(MyClass::class.java, MyClass::class.java.classLoader).iterator()
Everything matters here: 2 argument constructor, class constants as arguments, and the only call to the returned ServiceLoader has to be
.iterator()
.The text was updated successfully, but these errors were encountered: