Open st4ycool opened 1 year ago
Thanks, I'll look into it about the SharedFlow.
The database mirroring is already planned but I didn't quite have the time to go through it right now
Something is also wrong with displaying. The gallery is heavily lagging during fast scroll. Do you know where the bottleneck is, maybe I will try to fix?
It's a memory handling issue with Glide, I'm still trying to figure it out, so far locally managed to diminish the issue, but not fix it completely.
If you have any suggestions lmk, fyi I've tried coil (it doesn't cache on disk) in the past and it wasn't as fast as glide, but I'll give it one more try, and maybe some library that wraps around compose to integrate glide
My first thought was that the issue was just about the absence of pagination. But for the memory handling ... I am not sure. It feels like it's not about caching, but about preloading in the right time
The pagination is already handled by the lazygrid, preloading as well by glide compose, I've tested with various devices and while the scrolling wasn't an issue for them, I've found other issues regarding the data update (a lot of blocking GC allocs to free up the memory).
I'm working to try to keep the data transfer to a minimum
I searched, and there are no built-it paging mechanisms. You need to use Paging3 for that...
By pagination I meant the lazy loading of the data.
The lazygrid displays the data the fastest without Pagination library, this is not the issue
With Memory Analyzer from AS you can deep dive and see a huge spike of the allocated bitmaps, which is the main issue. I'm trying to figure out a way to avoid blocking GC calls
So, Glide has preloader that preloads bitmaps as you scroll, and lazy nature of Grid makes this work as pagination, right? Do you have examples where this approach works? Maybe it's just wrong usecase
Glide has an example on glide-compose on their docs / and GitHub
I looked through it. Some notes:
Can you push somewhere the first thing?
yeah ok. But tell me what you think about other 3!
Initial loading time from HEAD to older commits:
~HEAD 13:19:04.178 getMediaDebug I get media in search vm 13:19:04.518 getMediaDebug I get media in repeat on resume media view model 13:19:04.529 getMediaDebug I resolving media started at 1698142744529 13:19:04.600 getMediaDebug I resolving media started at 1698142744600 13:19:11.272 getMediaDebug I resolving media started at 1698142751272 took 6 seconds 13:19:11.350 getMediaDebug I resolving media started at 1698142751350 took 6 seconds
commit 75355357 13:40:10.885 getMediaDebug I resolving media started at 1698144010885 13:40:10.890 getMediaDebug I resolving media started at 1698144010890 13:40:10.925 getMediaDebug I get media in search vm 13:40:10.930 getMediaDebug I resolving media started at 1698144010930 13:40:13.672 getMediaDebug I get media in repeat on resume media view model 13:40:13.681 getMediaDebug I resolving media started at 1698144013681 13:40:19.311 getMediaDebug I resolving 3731 media started at 1698144019311 took 8 seconds 13:40:19.538 getMediaDebug I resolving 3731 media started at 1698144019538 took 8 seconds 13:40:19.538 getMediaDebug I resolving 3731 media started at 1698144019538 took 8 seconds 13:40:20.181 getMediaDebug I resolving 3731 media started at 1698144020181 took 6 seconds 13:40:35.620 getMediaDebug I get media in search vm
commit 43e09b10 14:00:05.811 getMediaDebug I resolving media started at 1698145205811 14:00:05.881 getMediaDebug I get media in search vm 14:00:06.188 getMediaDebug I resolving media started at 1698145206188 14:00:09.676 getMediaDebug I resolving 3731 media started at 1698145209676 took 3 seconds 14:00:09.974 getMediaDebug I resolving 3731 media started at 1698145209973 took 3 seconds
I looked through it. Some notes:
- You request glide to make a thumbnail. As pictures nowadays are enormous, you basically ask Glide to resize each picture. That's a lot of CPU work. Instead, thumbnails should be requested from MediaStore - thumbnails there are generated once and stored for each pic. I tried a simple solution and it seems like it works.
- Glide memory caching - this is an error. You can't cache the user's gallery, it just doesn't make sense. Filling up the cache and clearing it frequently - that's what causes GC (maybe). I tried to disable it with .setSkipCache(true).
- I went through Glide's documentation and no, it's not really pagination. Yes, they support it for LazyLists, but for grids - no. For lists they use GlideLazyListPreloader, which knows in what direction the user scrolls and prepares images. In the Gallery scenario, you are using preloadingData to wrap the whole collection (also, lazy initialization from a huge collection is not fast), and then requestBuilder, but it doesn't seem to me like pagination at all... If you could explain to me how it is supposed to work, pls do. But I guess the solution will be to add real pagination, that will preload images in batches according to where the user scrolls
- Long initial loading of gallery is caused by long parsing time of Cursor. Media objects are returned back to repository only when they all are parsed. I suppose this should be done in batches
I've tried disabling the memory cache with skipMemoryCache(true), but as glide's docs, this is not a guarantee the bitmaps won't be stored in memory. You can get blocking GC allocs consistently by moving to trash a large amount of items (10-12+), going to Trash screen, moving them out of the trash and go back to main screen (check logs)
glide's doc is not up to date, their latest impl is no longer using lazylist's state, but their own impl
val preloadingData = rememberGlidePreloadingData(
data = mediaState.media,
preloadImageSize = Size(24f, 24f)
) { media: Media, requestBuilder: RequestBuilder<Drawable> ->
requestBuilder
.signature(MediaKey(media.id, media.timestamp, media.mimeType, media.orientation))
.load(media.uri)
}
if you can do a reliable way to parse them in batches while also keeping the selections as well, go for it, I didn't give a try since the time it takes parsing the data from the cursor is quite small, in comparison with bitmap loading.
About the thumbnails of the mediastore, I've been trying to get the thumbnail to be loaded first, but you should also know that only items from Internal/DCIM and Pictures have thumbnails generated by the MediaStore, everything else is skipped.
Also a personal opinion: I don't think so pagination is required on a local database, would make more sense on a remote (internet) one.
About the last comment: Please link those commits since I can't find those sha's locally. Btw, compose acts the best while compiling in release flavor (staging is better than debug, but slower than release)
Did my own timing (on staging flavor) and got: [1698268130432] Count: 2256. Time: 182ms
100-200ms pretty consistently, also pushed an update to the mediastore observer to fetch new cursor data only when MediaStore version changes
https://github.com/IacobIonut01/Gallery/commit/16cefa02af838574bfdf3f05bdd562135f2382fe This basically fixes the blocking GC Allocs happening after batch operations, I've found out the cursor is triggered way too often because of the uri content observer
What device do you use for testing? It's insane that timings differ so much. I tested on Pixel 6 and I was measuring just Cursor parsing time for all gallery files
What device do you use for testing? It's insane that timings differ so much. I tested on Pixel 6 and I was measuring just Cursor parsing time for all gallery files
Pixel 6 with a gallery size of 2200~
What device do you use for testing? It's insane that timings differ so much. I tested on Pixel 6 and I was measuring just Cursor parsing time for all gallery files
I'm measuring inside getMedia, timestampStart = before starting query, timestampEnd = after final sort of the media (at the return line)
I was measuring with kotlin's mesureTime. Ok let's try simpler approach
Is your feature request related to a problem? Please describe. Media in timeline screen is loading too long. 5-10 seconds in my case (Pixel 6)
Describe the solution you'd like I think that storing Media in database will solve this problem
Additional context Actually, first time I noticed is when you added placeholders to TimelineScreen. After that media loading time increased drastically. Also, mediaState should really be distributed using SharedFlow, because rn every ViewModel is using content resolver to query whole media again.