New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 599514 link

Starred by 5 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

Jank displaying big looping animated gif with many frames

Project Member Reported by wangxianzhu@chromium.org, Mar 31 2016

Issue description

b/26173128

Sample gif: http://www.wired.com/wp-content/uploads/2015/12/StarWarsPoster.gif

Sample trace attached.

The CompositorTileWorker thread is very busy. About 1/3 to 1/2 time of each frame is for decoding the image frame, the other 1/2 to 2/3 time is for rasterization to tiles.

There might be two problems:

1. We decode a frame each time we display it. The caching mechanism doesn't work for the case because of memory limit: We cache several recent frames, but evict old frames from memory. Have no idea how to fix this except to increase memory limit for cached images.

2. Slowness of rasterization. TileTaskWorkerPool::PlaybackToMemory of each tile takes about 3ms.

bsalomon@ can you look at the rasterization slowness or reassign? Thanks.

 
trace_gif.json
5.1 MB View Download
Components: Internals>GPU>Rasterization
Labels: -Pri-3 OS-Android Pri-2

Comment 2 by aelias@chromium.org, Mar 31 2016

Cc: cblume@chromium.org vmp...@chromium.org bsalomon@chromium.org ericrk@chromium.org
Owner: ----
Adding folks working on the image pipeline.  (Probably, the issue is not contained entirely within Skia so bsalomon@ isn't the best owner.)
Components: Internals>GPU>Image
Owner: cblume@chromium.org
Chris, I'm guessing this can be duped to some existing gif work?
Status: Assigned (was: Available)
This may be a dupe of an existing issue. I'll check on that later, once I know what the root cause is and how to resolve it.

But first, what is TileTaskWorkerPool::PlaybackToMemory? I'm looking in Code Search and not really finding it.

I see that name in tests but not in the normal code. I also see TileTask and TileTaskManager. And I see TaskGraphRunner and TaskGraphWorkQueue. I assume TileTaskWorkerPool is another name for tile tasks in the TaskGraphWorkQueue.


I see the slow decodes in the trace. That is what I will focus on in my investigation. But like #1 said, a decode is followed by several calls to TileTaskWorkerPool::PlaybackToMemory. Those calls aren't THAT slow. But there are many of them. So the collection of them is slow.

Even if I fix the decode time, I will need to know what that does. It is just as important. It's just as slow.
re TileTaskWorkerPool::PlaybackToMemory, this was probably renamed to RasterBufferProvider::PlaybackToMemory. In other words, that's "raster", so whatever the slice for that is called :)
Issue 651817 has been merged into this issue.
Re #6 So when I see multiple TileTaskWorkerPool::PlaybackToMemory for each pending tree (and after a decode) I can read that as the tiles being rastered with that animation frame?

In the trace it looks like a lot of tiles that take quite a long time to raster. Longer than I would have expected.
I wouldn't worry too much about the existing trace - from looking at things, this was before the ImageDecodeController went in. It'd probably be more interesting to take a new trace and see if we still see issues.
Yeah, when I tested on my MacBook Pro last night it was silky smooth. I'm building now to test Linux ToT and get a new trace.
While trying to setup the trace (got the wrong categories at first) I noticed one run-through that was VERY janky and another run-through that was very smooth.

Attached is a trace of the smooth run-through. You'll notice the decode is only ~8-10 ms. This can probably be improved later but for now that is great. Another thing that might be improved is SoftwareImageDecodeController::DecodeImage() sometimes spends up to ~5 ms before getting to DecodingImageGenerator::getPixels().

But all of that is fine for now. None of it is what is causing the jank.


I have a theory. I think once a little jank starts we get stuck in catch-up. We are behind on presenting the current frame, and we have to decode several frames to catch up. Decoding several frames takes a long time, which causes us to once again be several frames behind. This continues on and on.

If we have all of the decoded frames cached then this will fix once we loop. But if we purge the decoded frames, we continue.

We exit this catch-up burden by decoding faster than a presentation requires. However, if the gif has a 10 ms delay between frames and we are taking ~10 ms to decode, we won't escape.


I'll try to get a trace which shows this theory.
trace_smooth_gif.json.gz
3.3 MB Download
I was able to get a janky animation from the original page:
https://www.wired.com/2015/12/star-wars-force-awakens-animation/

The original, source cause of the jank isn't the image decoder. Our catch-up behavior is the symptom that perpetuates the jank.

The original jank is from JavaScript running, which blocked our animation and took too long. Once that JavaScript finished, we attempted to catch up.


At 71.9 s into the attached trace you will see a decode which took 236 ms. It was decoding frame 25. Because it took so long, it then caused us to miss the next few frames.

The animation looped around to the beginning and we next requested frame 11. This still required decoding 11 frames so we spent 110 ms, and missed the next frame.

The next frame requested was 18, which took 56 ms to produce.

As you can see, once JavaScript introduces jank we have to spend a while catching up. During our cascading catch-up we continue to jank.

The jank gets less and less bad until it disappears.




I really, really want to get rid of this catch-up behavior. Safari mobile and Edge desktop (I didn't test Edge mobile) don't do it. And without it, we wouldn't have this eventually-stop-janking behavior.
trace_janky_gif.json.gz
3.4 MB Download
Labels: Hotlist-ImageWG
Components: -Internals>GPU>Rasterization

Sign in to add a comment