Remy Benza

12/17/2021, 5:24 PM
When fetching a very large contact list from an Android device (4000+) is is beneficial to run mutliple coroutines concurrently with the
async { }
builder? Or does the performance large depends on the I/O speed of the UFS storage?
A pattern I was thinking about:
val job1 = async { fetchContactsA-F() }
val job2 = async { fetchContactsF-W() }

job1.await() + job2.await()


Adam Powell

12/17/2021, 5:29 PM
you could do some experiments but I suspect that if you're reading this out of a single cursor returned by a contentprovider query from the contacts provider, you might end up with worse performance rather than better if you try to do multiple reads at very different points in the result set concurrently. A cursor window is a couple MB in size and if you move the cursor out of the current window's range, it dumps the current data in the window and loads in data from the new requested location. The cursor is optimized to do these loads linearly, not random access.
or maybe a better way to put it is that they're optimized to load in local batches in the same relative position in the data set. If you can avoid actually reading all of the data at once and instead you only process the local chunk you need in the moment, you'll probably have a better time.

Remy Benza

12/17/2021, 5:35 PM
I'm not very invested in cursors / low level API's
I did a similar thing for getting all the app icons from the package manager and ran some test with it. The performance improved by 400-500ms (1 job took around 2000 ms to get 300+ app icons, 2 jobs around 1500)
so that was worth the effort / extra complexity
curious to hear if someone else tried this