ShareChat
Moj

Deep dive into Animation Hitches and RenderLoop

Amirthy Tejeshwar

Amirthy Tejeshwar 31 Aug, 2022

Follow us on FacebookFollow us on TwitterFollow us on InstagramFollow us on Linkedin
Deep dive into Animation Hitches and RenderLoop

Today we are going to learn about how a frame is displayed and general issues with smooth scrolling, transitions, or animations in iOS.

While developing a user-facing application, any developer aims to provide the smoothest possible experience. But when there are many flows in the application, even a small miss on any screen can cause the app to misbehave and deviate from expectations. Users can observe the slow responses to their interactions, jerks, or jumps in the animation while scrolling through the content.

For a social media application like ShareChat, we needed to benchmark the smoothness and continuously work on reaching the desired experience throughout the application.

Introduction - RenderLoop, Animation Hitches

Let’s consider a device with a 60 Hz refresh rate. Each frame is displayed on the screen every 16.67 ms (1 second/60 Hz), and by the end of this window, we need the next frame to be ready.

The device hardware emits an event at the beginning of a frame called VSYNC i.e., after the time interval for the current frame, a VSYNC is released to mark the beginning of the next frame.

RenderLoop

In iOS, the whole life cycle of rendering a frame, from interaction by the user stage to displaying visible changes in the UI stage is called a Render loop. This happens over a set of VSYNC.

Animation Hitches

Animation hitches can cause jumps in animations and break the fluid user experience. A hitch occurs when a new frame appears on screen later than expected. So it basically occurs when the Render loop fails to render the next frame by the start of a new VSYNC.

There can be two types of hitches possible. More on this later.

Render loop in detail

Overall there are five phases in three stages of the RenderLoop that are segregated based on the different processes involved as shown in the above image.

Stages

  1. The first stage happens in the application, it handles the user events and submits changes to the render server (Event and Commit phase)
  2. The second stage happens in the Render server and it is responsible for the UI rendering (Render prepare and Render execute phase)
  3. The third and final stage is where the frame is displayed on the screen (Display)

Each stage is critical for a smooth user experience and should be completed within a single VSYNC.

An important point to note here, a frame is processed two frames before display, so that the next frame is ready by the end of the current frame, this is called double buffering and it helps in improving the performance a lot. There is also a triple buffering mode which is a fallback mode to avoid hitches where the render server is given one extra VSYNC to complete the rendering of the frame.

Phases in detail

Event

  • This stage handles touch events, interactions from the user and decides if there’s a need to update UI
  • System combines all the layout update requests to avoid duplicate work being performed in the commit phase

Commit

  • In this phase, the system takes all the layers that need updating layout and lay them parent to child, sibling to sibling.
  • App updates the UI and submits that to Render server which is a different process

Render prepare

  • Render server takes the submission and prepares GPU for the render phase
  • Processes the layers, effects and animations to create a pipeline that GPU can execute

Render execute

  • Render server draws the UI into a final image in this stage
  • Draws layers and effects using GPU, some layers take longer to execute

Display

  • Display the created frame to the user

Animation Hitches in detail

This video gives a good idea on the occurrence of a hitch(the jump in animation) and is caused by a frame staying on display for more time than expected while scrolling.

It is important to consider hitches in an application and how they hamper the user experience. They can even cause freezing of the application if ignored.

As explained above, delayed frame rendering, jumps or jerks in scrolling, transitions or any animations are the example occurrences of Animation Hitches

There are two types of hitches:

Commit hitches

  • Happens within app process.
  • App takes too long to commit or handle events.
  • The commit phase misses the deadline, and the render server has to wait for the next VSYNC to begin rendering.

Render hitches:

  • Happens in the render server.
  • Rendering doesn’t complete in the given time.
  • Render server is unable to prepare or execute the layer tree within the allotted VSYNC and hence causing a hitch.

Each VSYNC miss will add about 16.67 ms of hitch time in 60 Hz refresh rate devices.

Hitch Time Ratio:

Measuring hitches individually is not a good idea. It varies from devices to tests. So we make the measurement using the Hitch Time Ratio (HTR).

This normalizes total time in different intervals and helps to measure the outcome. It’s measured in hitch millisecond per second which is basically the duration of hitches in milliseconds within a second. Apple recommends to keep HTR < 5 as a good measure of scrolling performance in applications.

Commit phase hitches

For the scope of this article, let’s consider discussing only the commit phase animation hitches.

During a commit transaction the views that need a display or a layout will be updated accordingly by calling draw(rect:) or layoutSubViews. Also any image decoding or format conversion if required are a part of the commit phase itself and can take up a large amount of time.

Instruments template - Animation hitches

To profile hitches we are going to use the Instruments template - Animation hitches from Xcode(12+)

Some important details that will help us understand the template better

  1. Hitches track shows the hitches and their durations.
  2. User events track shows the user interactions
  3. Commits track shows the commit phases and the processes that committed during this phase
  4. Renders and GPU tracks show the rendering processes and are used to examine Render phase hitches
  5. Frame lifetimes track shows the entire lifetime of any frame
  6. Built in display track shows all the frames appeared on display
  7. Acceptable latency - Expected interval for the frame to be ready to display
  8. Hitch duration - The extra frame lifetime after the acceptable latency

We can also get the Hitch Type information if a hitch is a part of the commit or render phase. Time profiler is also included in this Animation hitches template which helps in finding the part of code taking too long in the commit phase.

ShareChat case study

The below is a normal UICollectionView with grid layout and you can watch the video to see the jump in the animation while scrolling through the content. This example is from a section in ShareChat iOS application.

We used the Animation hitches template for profiling this issue and found out that there were some blocks of code that delayed the commit phase to finish. Example: Text was being scaled every time we scroll around these items

Many other minor issues united to trigger expensive commit transactions which in turn delayed the next frames to display causing the jumps in the animation.

After getting to know the root causes for these bottlenecks, we updated the code blocks with performant and optimised code resulting in a not at all surprising, smooth scrolling experience like below.

Our exercise for profiling and improving the performance worked wonders and resulted in an improvement of 17% in HTR(Hitch Time Ratio) of the app directly and 35% reduction in frozen frames on average for this particular section of the application.

There is still a long way to go as this example is only scratching the surface of the limitless benefits of profiling the application. It is a great and important learning to put a good user experience above everything.

Recommendations:

1) Profile the application using instruments periodically

2) Keep your views light weight:

  • As custom drawing requires visual updates, avoid overriding draw(rect:) method if possible.
  • Use CALayer properties over custom draw(rect:) code
  • Reuse views instead of adding or removing views
  • Utilise hidden property of UIView to show or hide the view.

3) Avoid expensive view hierarchy operations if possible

  • Layout is a common performance bottleneck
  • Use setNeedsLayout as layoutIfNeeded will expend the current commit transaction and can cause hitches.
  • Use minimum number of constraints to reduce the complexity

4) Avoid heavy lifting on main thread:

  • Carry out only UI work on the main thread
  • Delegate any other processing to asynchronous blocks based on priority

Summary

We have discussed RenderLoop in detail, different types of animation hitches and Hitch Time Ratio for measuring them. Also explored Instruments template for finding hitches and applied it on our ShareChat case study.

We are hiring!

At ShareChat, we believe in keeping our Bharat users entertained in their language of preference. We are revolutionizing how India consumes content and the best in class Engineering technology is at the forefront of this transformation. In addition, you'll also get the opportunity to work on some of the most complex problems at scale while creating an impact on the broader content creation ecosystem.

Exciting? You can check out various open roles here!






Other Suggested Blog

Are you in search of a job profile that fits your skill set perfectly?

Congratulations! You’ve reached the right place!

We are enroute to building a team of humble, yet ambitious folks. Grow professionally in your career with us, as we offer tremendous room for growth in unique career fields. Do not miss out on this unique opportunity. Send us your resume today!