question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Dropped frames while scrolling in list with multiple spans

See original GitHub issue

I’m observing some pretty hefty main thread blockage using the latest Coil version (0.11.0) and older ones too. I just migrated from Glide on this app (I’ve used Coil before in other projects but never in a RV adapter) and everything was smooth until I tried scrolling on the RV. Anyway, tested with both ixel 3 and OnePlus 7T Pro so clearly not an hardware bottleneck.

My setup is a 5 span GridLayoutManager vertical scrolling. One device has +300 pictures, the other has ~50, so doesn’t seem related to the amount of pictures. What I observe is when I start scrolling when Coil is decoding the URIs and starting to display the thumbnails something seems to block the main thread and the whole thing gets blocked and it seems to suspend the entire operation. Sometimes I have to wait 3-4 seconds for it to finish whatever it seems to be doing and it then resumes.

In the screenrecord I’m attatching you can see a bit of the jank after I open the app fresh. I made each thumb 8px/8px because it’s my personal pictures library, but you get the picture. It obviously has worse jank with their actual decoded size (which should be device width / spancount) (5 in this case). The jank is halved if I decrease the span count to 3 or 4. Here’s the very simple code I’m using:

LoadRequest request = LoadRequest.builder(((ViewHolder) holder).b.picture.getContext())
                    .key(item.getUri().toString())
                    .data(item.getUri())
                    .crossfade(false)
                    .target(((ViewHolder) holder).b.picture)
                    .build();
            Coil.execute(request);

Logcat is filled with these GC related operations when doing the scrolling:

2020-05-19 20:36:44.160 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 11330(820KB) AllocSpace objects, 48(1172KB) LOS objects, 0% free, 8438KB/8438KB, paused 124us total 157.193ms
2020-05-19 20:36:44.455 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 22434(2113KB) AllocSpace objects, 127(3216KB) LOS objects, 49% free, 7161KB/13MB, paused 438us total 288.432ms
2020-05-19 20:36:45.609 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 28249(2948KB) AllocSpace objects, 190(4884KB) LOS objects, 0% free, 13MB/13MB, paused 590us total 693.969ms
2020-05-19 20:36:45.772 12402-12437/com.franco.graphice I/franco.graphic: Waiting for a blocking GC ProfileSaver
2020-05-19 20:36:46.126 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 46990(4091KB) AllocSpace objects, 222(5452KB) LOS objects, 49% free, 10MB/20MB, paused 1.728ms total 515.818ms
2020-05-19 20:36:46.126 12402-12437/com.franco.graphice I/franco.graphic: WaitForGcToComplete blocked ProfileSaver on ClassLinker for 354.762ms
2020-05-19 20:36:48.146 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 111714(5587KB) AllocSpace objects, 253(6552KB) LOS objects, 0% free, 22MB/22MB, paused 300us total 851.007ms
2020-05-19 20:36:48.421 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 125680(7618KB) AllocSpace objects, 372(9332KB) LOS objects, 49% free, 8377KB/16MB, paused 654us total 258.322ms
2020-05-19 20:36:50.169 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 122438(7099KB) AllocSpace objects, 230(5824KB) LOS objects, 49% free, 5686KB/11MB, paused 48us total 438.112ms

Also it’s a bit better when using BitmapConfig RGB_565, but just a tiny bit. With the default BitmapConfig I see tons of these logcat messages:

2020-05-19 20:38:15.978 12923-12923/com.franco.graphice I/Choreographer: Skipped 40 frames!  The application may be doing too much work on its main thread.
2020-05-19 20:38:16.211 12923-12965/com.franco.graphice I/OpenGLRenderer: Davey! duration=914ms; Flags=0, IntendedVsync=5662959106048, Vsync=5663625772688, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=5663641456128, AnimationStart=5663641473576, PerformTraversalsStart=5663642302847, DrawStart=5663719940563, SyncQueued=5663865801775, SyncStart=5663866294692, IssueDrawCommandsStart=5663867129952, SwapBuffers=5663869075161, FrameCompleted=5663874209172, DequeueBufferDuration=187000, QueueBufferDuration=1022000, 
2020-05-19 20:38:16.321 12923-12936/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 108152(11MB) AllocSpace objects, 478(11MB) LOS objects, 50% free, 17MB/34MB, paused 201us total 1.090s

Any clues or question that I can answer to help you narrow it down somehow?

Thanks I hope this was clear enough.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:7
  • Comments:42 (19 by maintainers)

github_iconTop GitHub Comments

3reactions
colinrtwhitecommented, Oct 11, 2021

I’ve just published 2.0.0-alpha01 which should completely fix any performance issues related to scrolling. I’ve set the sample app to run with 5 columns and it doesn’t drop any frames.

Among other performance improvements, 2.x throttles the output of BitmapFactoryDecoder. The number of parallel BitmapFactory decodes defaults to 4, but can be adjusted using ImageLoader.Builder.bitmapFactoryMaxParallelism. Increasing the number allows more parallel decodes, but may (slightly) reduce scrolling FPS. I felt 4 was a good default, but depending on how much work your app does on the main thread, your app may be able to handle more.

3reactions
colinrtwhitecommented, Jul 23, 2021

@leondeklerk Unfortunately, there isn’t a great solution for this at the moment aside from setting ImageLoader.Builder.dispatcher(Dispatchers.Default). That said, this bug should be completely fixed in 2.0. I’m able to run 5 columns in the sample app no problem. The alpha will be out soon.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Interpreting Dropped Frame In Chrome Dev Tools
I'm having similar issues, where renders dependent on scroll events, while scrolling on a mac trackpad, can delay the next frame indefinitely ( ......
Read more >
The 4 Types of Creative Website Scrolling Patterns - UXPin
Considering that our attention span on the web has dropped to about 8 ... layers of a two-dimensional image moving at different speeds...
Read more >
Maintaining Scroll Offsets When Adding Content Above The ...
Ben Nadel demonstrates how to maintain scroll offsets when new content is added above the user's viewport in Angular 9.0.0-rc.2.
Read more >
Web Animation Performance Fundamentals – How to Make ...
animation-scroll-2 Generated frames during a few seconds of scrolling ... An animation with frame drops and delays.
Read more >
Debouncing and Throttling Explained Through Examples
Debounce and throttle are two similar (but different!) techniques to control ... When scrolling using a trackpad, scroll wheel, or just by ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found