David Cordero

Bumping the performance of TVML with Prototypes and Data Binding… or not

Published on 25 Nov 2017

The low performance of TVMLKit has been one of its biggest bottle necks since tvOS was launched. Not only when performing heavy computing task, which could be after all derived to Swift, but also when dealing with a lot of UI elements.

You only have to load a screen with several items and layers and you will start noticing delays and glitches when loading your views.

tvos loading screen

Fortunately, last June at WWDC 2017, with the presentation of tvOS 11, Apple introduced a solution for the low performance offered by TVML when loading really big documents. This is what they called Prototypes and Data Binding.

Prototypes and Data Binding

The idea is simple, when using Collections Lists (Grids, Shelfs or Carousels) it is quite common to end up with a lot of duplicated text in our TVML documents, because most of the items will contain almost the same information repeated along the collection.

<grid>
    <section>
        <lockup>
            <img src="./movie0.png" width="300" height="200">
            <title>Movie 0</title>
        </lockup>
        <lockup>
            <img src="./movie1.png" width="300" height="200">
            <title>Movie 1</title>
        </lockup>

        [...]

        <lockup>
            <img src="./movie999.png" width="300" height="200">
            <title>Movie 999</title>
        </lockup>
    </section>
</grid>

Using the new concept of Prototypes in tvOS 11 it is possible to merge all those duplicated lines of code in a single item definition.

<grid>
    <section binding="items: {movies}">
        <prototypes>
            <lockup prototype="Movie">
                <img binding="@src: {image};" width="300" height="200">
                <title binding="textContent: {title};"></title>
            </lockup>
        </prototypes>
    </section>
</grid>

And once the document is loaded, much faster because of its smaller size, the collection can be populated making use of Data Binding.

// Create Data Items

let dataItems = [];
for(let i = 0; i < 999; ++i) {
    let movie = listOfMovies[i];

    let dataItem = new DataItem("Movie", movie.id);
    dataItem.image = movie.image;
    dataItem.title = movie.title;
    dataItems.push(dataItem);
}

// Append Data Items to the Grid Section

const section = document.getElementsByTagName('section').item(0);
let sectionDataItem = new DataItem();
sectionDataItem.movies = [];
section.dataItem = sectionDataItem;

Array.prototype.push.apply(section.dataItem.movies, dataItems);
section.dataItem.touchPropertyPath("movies");

That is all that we need to get a bump in the performance of TVMLKit in our documents.

A closer look to loading times

When Apple presented this new feature at WWDC, they showed up this graph to describe the problem when loading TVML documents in tvOS 10.

scalability issues graph

This graph shows a clear exponential tendency in the time spent to load the document when adding more and more items. But the fact is that the graph does not have any number at all, which makes it quite hard to say how horrible the thing is, right? So, lets puts some numbers…

I have the strong opinion that there is no better way to make performance tests than using cats, so lets put some cats on the screen to check how much time they need to load… how many cats? A LOT, up to 45k basically because there are never enough cats in the Internet 🙀

I prepared this simple project which presents a grid of cats using three different methods. With and without Prototypes and Data Binding, and just for fun an additional one directly using UIKit. And here you have the results:

loading times comparison

First thing that we can notice is the incredible low performance of TVML, regardless of the chosen method, in comparison to directly using UIKit. Trust me, UIKit is there but it is that fast in comparison to TVML that its values do not sum up enough for drawing one single pixel in the graph.

Moving the focus to the TVML results, we can clearly see that the benefit in loading times is huge when using Prototypes and Data Binding, specially when dealing with really big documents. More than 35 seconds in the worse analyzed case with 45k cats.

But if we zoom up a little bit to take a closer look to the loading times when having fewer items, we will see that the loading times are not that different…

low data comparison

So, Prototypes and Data Binding are definitely a great improvement when woking with really big documents, but probably not noticeable at all for most of the cases. Because lucky us, Tv Apps do not have to usually deal with thousand of items, basically because they would be very hard to manage and navigate making use of Siri Remote.

Caviats…

In terms of performance, apart from loading times, the behavior of our views in runtime is also very important. So, lets put also some numbers to the runtime performance, measuring the frames per second when scrolling our huge list of 45k cats using each of the three different methods.

Frames per second directly using UIKit

Frames per second NOT using Prototypes and Data Binding

Frames per second using Prototypes and Data Binding

Once again we can see that directly using UIKit offers a much better performance in terms of fps.

In the results of TVML, we can also see that the benefit in loading times that we can get using Prototypes and Data Binding, is not free. It has a high cost in runtime performance with a scrolling animation dropping down from 43 to 27 frames per second (fps).

It looks like the definition of the collection with a single prototype item, apart from offering better loading times, does also require extra computing effort to build each single item. This ends up with an important impact in the fps of our views.

Conclusion

Prototypes and Data Binding are really cool. They do improve a lot the loading times, specially when dealing with huge documents.

But, as we have seen in numbers, the benefit on loading times is not really noticeable for collections with “just a few” items, and it has a quite high cost in terms of runtime performance.

As a result of that, Prototypes and Data Binding should not be seen as a replacement to traditional TVML collections loading techniques, but as a new alternative. Their use should be analyzed, taking into account the characteristics of each specific case.

Feel free to follow me on github, twitter or dcordero.me if you have any further question.