top

Essentials for Performance Improvement

Essentials of improving performance of application for Samsung Smart TV.

Overview

This document is for SW developers who have plans to improve the performance.

This document is clearly dedicated for people with experiences in developing web application.

This document covers detailed technical explanation of application launch process.

On the following chapters, we will propose checklist to minimize application loading time.
Finally, we will provide some JavaScript good practices to improve general performance of application.

Main purpose

  • Improving user experience with application requires smooth transition from “Apps” to application.

  • Applications with good user experience(UX) attract more users. Users who have good impressions return more often and can advertise your application to others.
    With good monetization model this means more profit. Improving the user experience becomes important effort.

  • Application performance is determined by many factors:

    • Launch time
      Launch time is the first impression of application that its users would get. For this reason, it is the most important area of improvement.
      Long loading times may discourage the users so that they would leave even before application is ready to use.

    • Responsiveness and Smoothness of animations
      Responsiveness of the application and operations smoothness (changing scenes, loading content, animations and etc.) are the secondary area.

  • This document presents the case study of improving application to reduce application launch time.
    Main focus is put on TV specific environment but some of the concepts can be also applied to traditional web development.
    Implementation tips provided in the following chapters can also affect performance in all stages of application lifecycle.

Rationale

  • Application launch time is the total time taken from the moment when user clicks on application icon until when the application is ready to use.

  • In order to define a target for loading time optimization, We asked users how much they are willing to wait for application setup.
    Results of the study are presented as below.

    Customer satisfaction from application launch time, source: own research

    Customer satisfaction from application launch time, source: own research

  • Application launch time around 1s would satisfy all users.
    If the launch time exceeds 10 seconds, only 17% of the customers are satisfied.
    Loading time over 15s is not acceptable by almost any users.

Note

We should aim at launch time of around 5-7s to satisfy most of the users.

Terminology

  • Lazy loading
    Design pattern used to delay loading of application files until they are needed.

  • Lazy initialization
    One of the lazy loading implementation methods.

  • Splash image
    Welcome screen of an application which is still loading.

  • Home page
    First page of ready-to-use application.

Application Launch Process

Stages of Application Launch Process

  • The process of application launch can be divided into 5 stages.
    Some stages are controlled by the system, so application developer has no influence on them.
    However, most of them are dependent on application implementation, so those set the space for possible performance improvement.

  • The example below is based on Pooq application.
    We have recorded video while running this application on TV, which allowed us measure the time taken in each stage of the process with an accuracy of one video frame.

  • While testing your own application in similar way, make sure that all tests are performed under the same circumstances (device, network condition and etc.).
    Otherwise the results may vary due to external factors.

  • Below you will find detailed description of each stage.
    It is measured on Samsung TV 2015 model.

    • Stage 1

    Stage 1 -
    Action Clicking icon in Apps
    Time 1.086 s
    Description This stage covers the time period from clicking application icon to the moment when Apps disappears.
    Solution It can be improved by application conversion to Tizen.Refer to Converting Application to Tizen
    • Stage 2

    Stage 2 -
    Action Initial Loading
    Time 4.979 s
    Description From loading the first HTML file such as index.html to calling window.onload.
    Solution Refer to Improving Application Launch Time
    • Stage 3

    Stage 3 -
    Action Black screen
    Time 0.837 s
    Description Transition screen shown only for legacy application before calling window.onload.
    Solution It can be improved by application conversion to Tizen.Refer to Converting Application to Tizen
    • Stage 4

    Stage 4 -
    Action Splash image
    Time 0.57 s
    Description The first screen shown in application after calling window.onload.Usually it is displayed during authentication or loading content, but this may differ depending on application.
    Solution Refer to Improving Application Launch Time
    • Stage 5

    Stage 5 -
    Action Home page
    Time 0.348 s
    Description This stage covers displaying the home page, filling all the content and enabling user user input.
    Solution Refer to Improving Application Launch Time

Optimization of Application Start Logic

  • The following example lets us assume that we are optimizing application based on a kind of framework.
    This framework contains modules responsible for activities such as sending AJAX requests to backend server, application authorization on the backend side and other modules responsible for UI, logic and etc.

  • If we measure the time taken by all application components to load and execute, the detailed loading diagram could look like this:

    • Application’s logic is dependent on the framework setup. The framework is loaded and initialized in stages 2 and 3.

    • After the framework setup is completed, application logic starts authorization at the backend server.

    • If the authorization succeeds, the application sends some AJAX requests to the backend server to fetch application data such as list of recommended movies to be displayed on home page of application.
      AJAX requests must contain authorization token, so they are dependent on authorization step.

    • Application logic waits for the data needed to display in the home page and renders it in Stage 5.

  • This model is far from optimal regarding application launch time.
    It loads and initializes the whole framework before the application can start authorization and loading the content.

  • To speed up the launch process we should aim at rebuilding it in the following way:

    • Framework setup is divided into 2 parts.
      The first part loads the modules responsible for application authorization;
      the second one does initializes the rest of the framework.
      When first part is loaded it can perform authorization immediately – it only depends on XHR object created in web runtime setup at Stage 1. AJAX requests are merged into one to avoid unnecessary delays.
      The request needs to be signed with authorization token, so it depends on the authorization stage.

    • Initial application logic requires that framework is fully set up. However, it can perform the basic home page setup without waiting for the results of AJAX request.

    • Stage 3 does not exist after porting from legacy application to Tizen application.

    • Padding time is the time needed to synchronize application logic and AJAX requests. Application logic needs data from AJAX requests to render the home page, but as the requests are asynchronous there should be some mechanism coordinating those two modules such as events, callbacks, promises.

    • Application logic can resume after receiving response from the server.

    • Other parts of application logic do not delay the launch process (required scripts and data are loaded on-demand).

  • This flow is more optimized as many tasks are performed in parallel.
    Initially the application loads only modules which are crucial to perform authorization and then starts it immediately along with other operations (loading the rest of framework, UI, resources, contents, etc.).
    All things that are not crucial for displaying the home page are postponed to start after the launching process. In result the application launch time is much shorter than before.

Improving Application Launch Time

Converting Application to Tizen

Applies to stages: 1, 3

  • On 2015 models of Samsung TV there are two web runtimes (WRT):

    • Tizen TV
      current WRT, fast and feature rich,

    • Smart TV
      legacy WRT available for backward compatibility.

  • Tizen platform is more efficient than the previous one, so it is worth converting your application to Tizen application.
    You will notice significant improvement in application performance.

  • Please refer to Upgrading Legacy platform to Tizen to learn how to port application.

Enable Prelaunching

Applies to stages: 1, 2, 4, 5

  • If you convert your application to Tizen you can enable prelaunching.
    This feature allows loading recent applications in background when Samsung TV starts.
    When user opens such application, it will display in much shorter time as it is already preloaded on TV.

  • The prelaunching feature should be set it in “config.xml” file:

    <tizen:metadata key='http://samsung.com/tv/metadata/prelaunch.support' value='true' />	
    
Note

  • Only few most recent applications are prelaunched – it depends on the amount of TV resources available.
  • Prelaunching is supported on 9xxx model series such as UN65JS9000, UN78JS9500 and some lower models.

Minimizing the Amount of Code Loaded for the Home Page

Applies to stages: 2, 5

On application start, load only the code (HTML, JS and CSS) which is necessary to show the home page.
Rest of the application can be loaded on demand such as using require.js or similar libraries to avoid building and parsing the DOM before it is needed.
Less code to load and parse will result in shorter start time.

Load JavaScript Files Asynchronously Using Defer or Async Attributes

Applies to stages: 2, 4

  • When loading external JavaScript files, HTML parser stops for the time needed to download and execute the JavaScript.

    Flow of classical JavaScript loading from external files

  • To avoid the pause in HTML parsing, you can use attributes defer or async:

     	<script src='js/main.js' defer></script>
    <script src='js/scripts.js' async></script>	
    
  • The defer option downloads JavaScript file in parallel while parsing HTML. The JavaScript code executes only when all HTML parsing is completed. defer scripts are also guaranteed to execute in the same order that they appear in the document.

    Flow of JavaScript loading from external files using defer attribute

  • The async method downloads JavaScript file while parsing HTML and pauses HTML parser to execute the JavaScript when it is downloaded.

    Flow of JavaScript loading from external files using async attribute

  • The defer and async attributes can be used only for external scripts (script tag with src attribute, not inline scripts embedded in HTML).
    These ways of loading JavaScript are especially useful for initializing the home page of an application.

  • Plese refer to Script()
    (Source: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)

Send AJAX Requests as soon as Possible

Applies to stages: 2, 4

Most applications load their content from remote servers and utilize some kind of framework that helps manage the requests.
However, loading and executing the whole framework code may take a lot of time. In order to speed up the application start, AJAX requests needed to display the home page should be sent as soon as possible.
A good solution could be a simple XHR request at the beginning of index.html, sent before loading the framework.

  • Problem
    Application is based on complex framework which needs some time to load and initialize. After the framework is fully loaded, the application sends a request to remote server (e.g. to get the list of recommended movies to be displayed on home page) using one of its modules. This all takes a lot of time.

  • Solution
    Construct a simple XHR request in index.html and send it as soon as possible. XHR requests are asynchronous so they don’t block any other threads. Cache the response in a global object, so the application framework can use this data immediately to display the home page without sending the request again.

Parallelize AJAX Requests

If consecutive requests don’t depend on previous ones, send them in parallel instead of sending them after previous ones finishes.

  • Good
    First request authorizes the application so it must be executed as the first request.
    When response comes the rest of requests are executed asynchronously which are depending only on request 1 and not on any other, such as getting categories, movies list for home page etc.

    sendRequest1
    	onSuccess: sendRequest2
    			   sendRequest3
    			   sendRequest4
    			   sendRequest5
    
  • Bad
    Each subsequent request is executed after receiving response from previous one:

    sendRequest1
    	onSuccess: sendRequest2
    		onSuccess: sendRequest3
    			onSuccess: sendRequest4
    				onSuccess: sendRequest5
    

Concatenate AJAX Calls

Applies to stages: 2, 4, 5

  • If possible, limit the number of AJAX calls such as by merging several requests into one.
    For example, consider an application that sends 3 requests to display the home page:

    • For application authorization.

    • For a list of recommended movies.

    • For a list of latest movies.

  • In such case, verify if it is possible to modify the requests and backend in such a way, that the response for authorization request contains recommended and latest movies as well.
    The fewer the number of requests, the shorter time it takes to process all of them. Using this technique in all parts of application may also decrease the loading time of other scenes.

Delay Calls to Webapis and Tizen APIs

Applies to stages: 2, 4

Many applications make early calls to Tizen and platform APIs for static information, such as DUID, model code, etc.
The first call to each API module takes long time as the API initialization is done in a lazy way.
If possible, postpone those API calls until the application is fully started and ready to use.

Cache TV APIs Output

Applies to stages: 2, 4, 5

  • Instead of querying the API each time, cache static output from TV APIs (webapis and tizen) in JavaScript variables.
    This applies to values that don’t change frequently, such as the total time of video contents.
    This value is constant for the whole playback time, so it can be retrieved from the API once and stored in a JavaScript variable, without having to query the API each time it is needed.

  • Some of the APIs return constant TV specification parameters that never change, such as DUID or model code.
    To decrease the application launch time it is helpful to save such kind of data in localStorage.
    In effect, the first time the application is run it will query the TV APIs.
    Next time it will read this data from localStorage which works much faster, so the application launch will take less time.

Use at Least v2x of jQuery

Applies to stages: 2, 4, 5

jQuery 2.x is smaller and faster than versions 1.x.
You can also consider using custom builds of jQuery for more details.

Load JavaScript files and Other Resources from Local File System

Applies to stages: 2, 4

We strongly recommend loading all static application resources directly from local file system.
To do this, include all application source code, external libraries and static UI elements (including CSS and images) within your Tizen package.
This will not only decrease loading time, but also improve application security and eliminate some application errors caused by network issues.

  • Good

    <link rel='stylesheet' href='css/bootstrap.min.css'>
    <link rel='stylesheet' href='css/styles.min.css'>
    <script src='js/jquery-2.0.0.min.js'></script>
    <script src='js/bootstrap.min.js'></script>	
    
  • Bad

     	<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css'>
    <link rel='stylesheet' href='https://example.com/myapp/css/styles.min.css'>
    <script src='http://code.jquery.com/jquery-2.0.0.min.js'></script>
    <script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js'></script>
    

Minimize and Concatenate Code

Applies to stages: 2, 4

If you don’t use any lazy loading mechanism that loads parts of your application on demand, concatenate and minimize your source code (JavaScript and CSS). The fewer requests to filesystem, the faster your application will load.

  • Good

     <!DOCTYPE HTML>
    <html lang='en'>
    <head>
     <meta name='viewport' content='width=1280, user-scalable=no'>
     <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
     <title>My application</title>
     <link rel='stylesheet' type='text/css' href='styles/all_styles.css'/>
     <script src='js/all_scripts.js' defer></script>
    </head>
    <body>
      <div id='Menu'></div>
      <div id='mainContainer'>
      <div id='helpbar'></div>
    </body>
    </html>
    
  • Bad

    <!DOCTYPE HTML>
    <html lang='en'>
    <head>
      <meta name='viewport' content='width=1280, user-scalable=no'>
      <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
      <title>My application</title>
      <link rel='stylesheet' type='text/css' href='styles/main.css'>
      <link rel='stylesheet' type='text/css' href='styles/list.css'>
      <link rel='stylesheet' type='text/css' href='styles/player.css'>
      <link rel='stylesheet' type='text/css' href='styles/login.css'>
      <link rel='stylesheet' type='text/css' href='styles/account.css'>
      <script src='js/main.js'></script>
      <script src='js/list.js'></script>
      <script src='js/player.js'></script>
      <script src='js/login.js'></script>
      <script src='js/account.js'></script>
    </head>
    <body>
      <div id='Menu'></div>
      <div id='mainContainer'>
        <div id='helpbar'></div>
    </body>
    </html>
    
  • Sometimes it is better to concatenate your code into two files rather then one, especially when using defer and async attributes.
    For example, you can put the code that should be executed as soon as possible into one file and load it with async attribute.
    Other code that requires DOM to be ready can be put in another file and loaded with defer attribute.

Note

Remember to keep order for code dependency.

Remove Obsolete Code

Applies to stages: 2, 4

If the application loads any unused source code, whether it is JavaScript, CSS or HTML, the browser will take time to parse it, build DOM and search HTML for matching CSS rules.
Keep your code clean and up to date to avoid unnecessary performance issues caused by obsolete code in your package.

For example, when window.onload is called, you don’t have to unregister some keys by callling tizen.tvinputdevice.unregisterKey. It is unnecessary because just only “Left”, “Up”, “Right”, “Down”, “Enter” and “Back(Return)” is basically registered.

Optimize Graphics and Use Sprites

Applies to stages: 2, 4, 5

If your application loads many small graphics such as icons, button elements, backgrounds and etc, consider using CSS sprites.
This technique helps all the images load faster thanks to fewer requests to the file system, which also improves the overall application performance.

  • Good

    #myButton {
    	width: 300px;
    	height: 100px;
    	background: url('img/button-sprite.png') 0px 0px no-repeat;
    }
    
    #myButton:hover {
    	background: url('img/button-sprite.png') 0px -100px no-repeat;
    }
    

    This code is more optimal because it loads only one image (which takes less time to load even though its size is bigger). Mouse hover changes only the background image position, so there is no flickering when switching between those states.

  • Bad

    #myButton {
    	width: 300px;
    	height: 100px;
    	background: url('img/button-normal.png') 0px 0px no-repeat;
    }
    
    #myButton:hover {
    	background: url('img/button-hover.png') 0px 0px no-repeat;
    }
    

    This code is not optimal, as the browser must make 2 requests to the filesystem instead of just one. What is even worse, the first time such button is hovered its background will flicker, as there is some time needed to request for the new background file and update it on the screen.

  • You can merge all of your icons or background images into one big image and use CSS to set proper positions for each element.

Use Pure CSS Instead of Graphics

Applies to stages: 2, 4, 5

Tizen platform supports CSS3 which allows you display many graphic effects without using even a single image.
Pure CSS renders faster and takes less time to recalculate any of its properties, which is especially valuable when animating such elements.

For example, this button was made using only pure CSS:

button {
	width: 180px;
	height: 62px;
	line-height: 62px;
	font-size: 24px;
	color: #fff;
	text-align: center;
	text-shadow: 1px 0 1px rgba(0, 0, 0, .75);
	background: -webkit-linear-gradient(
		top,
		#1e5799 0%,
		#2989d8 50%,
		#207cca 51%,
		#7db9e8 100%
	);
	border: solid 2px #fff;
	border-radius: 12px;
	box-shadow: 0px 0px 15px 5px rgba(255, 255, 190, .75);
}

Enforce GPU Acceleration using CSS

Applies to stages: 5

  • CSS3 allows you enforce the browser to render elements with GPU acceleration.
    The browser applies GPU acceleration when there is some indication that a DOM element will benefit from it.
    Sometimes you may want to cheat the browser to enforce the use of GPU. One of the simplest methods is setting a style indicating 3D transform, even if no real 3D transformation is applied:

    .acceleratedElem {
       -webkit-transform: translateZ(0);
    }
    

    In general, all kinds of 3D transformations used in CSS force the browser to use the GPU.

  • If you notice any flickering when using CSS transforms or animations, the following declarations will help you fix the issue:

    .acceleratedElem {
       -webkit-backface-visibility: hidden;
       -webkit-perspective: 1000;
    }
    
  • Please refer to CSS 3D transformations
    (source: http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css)

General JavaScript Web Applications Improvement Tips

JavaScript is a great language, but it allows writing bad code - not only by means of aesthetics but also performance, maintainability and susceptibility to errors.
It is good to follow a reliable set of coding standards for JavaScript, as it makes the code easier to write, easier to read, improves its maintainability and makes it less error prone.
Here we will point out only the most important tips.
At the end of this chapter there is a list of valuable resources to learn more about good practices in JavaScript development.

Cache References to DOM Elements

Searching the DOM tree is a resource hungry operation.
If there are any DOM elements on which you perform frequent operations, store them in JavaScript variables to avoid repetitive DOM traversal.

  • GOOD

    var elem1 = document.getElementById('elem1');
    elem1.innerHTML = 'Lorem ipsum dolor';
    elem1.classList.remove('class1');
    elem1.classList.add('class2');
    
    var $elem2 = $('#elem2');
    $elem2.html('Lorem ipsum dolor sit amet');
    $elem2.addClass('class3');
    
  • BAD

    document.getElementById('elem1').innerHTML = 'Lorem ipsum dolor';
    document.getElementById('elem1').classList.remove('class1');
    document.getElementById('elem1').classList.add('class2');
    
    $('#elem2').html('Lorem ipsum dolor sit amet');
    $('#elem2').addClass('class3');
    
  • Additionally, it could be helpful to store references to frequently used DOM elements in some global object, such as:

    var domElementsCache = {
    	elDocument: window.document,
    	elHtml: window.document.documentElement,
    	elBody: window.document.body,
    	elHead: window.document.head,
    	elTitle: window.document.getElementById('title')
    };
    
    domElementsCache.elTitle.innerHtml('My title');
    

Avoid Using Slow jQuery Selectors

jQuery selectors work a bit slower than native ones.
If application performance is critical, consider replacing them, e.g.:

  • ID selector

    //jQuery
    var elem = $('#myElem');
    
    //native JS equivalent
    var elem = document.querySelector('#myElem');
    
  • Class selector

    //jQuery
    var elems = $('.class1');
    
    //Native JS equivalent
    var elems = document.querySelectorAll('.class1');
    
  • TagName selector

    //jQuery
    var elems = $('span');
    
    //Native JS equivalent
    var elems = document.querySelectorAll('span');
    
  • $.find()

    //jQuery
    var elems = $el.find('.target1, .target2, .target3');
    
    //Native JS equivalent
    var elems = el.querySelectorAll('.target1, .target2, .target3');
    

Replace jQuery / Underscore Functions with Faster Native Functions

Native JavaScript functions are faster than wrappers from different libraries. In some cases it might be helpful to use them instead of library methods:

var myArray = [1, 2, 3];

//Underscore
_.each(myArray, function(val) {
	console.log(val);
});

//jQuery
$.each(myArray, function(val) {
	console.log(val);
});

//Native JS equivalent
for (var i = 0; i < myArray.length; i++) {
	console.log(myArray[i]);
}

Remove console.log

  • Extensive logging decreases the application performance, because each console.log (console.warn, console.info, console.error too) blocks the JavaScript thread of the browser.
    It is advised to remove any logging in final application.

  • A good idea is to use some kind of a logger utility, so that logs can be easily turned on and off. You can use some kind of open source libraries such as Woodman, or write your own logger, such as this:

    // Global object for storing configuration of application
    	var applicationConfig = {
    	debugMode: true //enables logs in application
    };
    
    // Logger object factory
    var Logger = function() {
    
    	var logger = {};
    
    	if (applicationConfig.debugMode === true) {
    		logger = {
    			log: function() {
    				var args = Array.prototype.slice.call(arguments, 0);
    				console.log(args);
    			},
    
    			info: function() {
    				var args = Array.prototype.slice.call(arguments, 0);
    				console.info(args);
    			},
    
    			warn: function() {
    				var args = Array.prototype.slice.call(arguments, 0);
    				console.warn(args);
    			},
    
    			error: function() {
    				var args = Array.prototype.slice.call(arguments, 0);
    				console.error(args);
    			}
    		};
    
    	} else {
    		logger = {
    			log: function() {},
    			info: function() {},
    			warn: function() {},
    			error: function() {}
    		};
    	}
    
    	return logger;
    };
    
    // USAGE:
    // For development and debugging.
    
    var applicationConfig = {
    	debugMode: true
    };
    
    var myLog = new Logger(); // Initializes logger.
    myLog.log('test'); // Will output 'test' to console.
    
    
    //For production.
    var applicationConfig = {
    	debugMode: false
    };
    
    var myLog = new Logger(); // Initializes logger.
    myLog.log('test'); // Will do nothing.
    
Important

Never override console.log or any other native function.
Overriding the native objects is considered a bad practice in JavaScript as it may lead to unexpected behavior and introduce defects that are very hard to debug.

Other Resources

Useful Tools

  • Maintaining the code of your application, keeping it clean and doing repetitive and tedious tasks during the development can be a real pain. All jobs like:

    • optimizing graphics,

    • building sprites,

    • concatenating and minifying the code,

    • building CSS from LESS, Sass or other,

    • lining the code,

    • parsing CoffeScript

  • and many more can be automated and done fast by the computer. There come some useful tools to help that and save your time.
    Here we will mention two most popular complex solutions. They are easy to use for JavaScript developers (all configuration is done using JavaScript), come with a handful of ready to use plugins and are easy to extend with your own functionalities.

  • Other useful tools, less complex, but still worth to learn are:

    • Compass CSS Authoring Framework – open source toolchain enabling easier creation of CSS files, together with concatenation (7.11). Also optimizes images and generates sprites (7.13). Can work together with Grunt and Gulp.

    • ESLint and JSHint – tools for enforcing a defined style of JavaScript code. Both can be configured to work with Grunt and Gulp.

    • YUI Compressor – JavaScript minified by Yahoo. Claims to yield a higher compression ratio than most other tools.

Summary

  • We have applied the principles described in this document to several applications available on Samsung TV. Results of the optimization are available in the table below.

    - Before improvement Post improvement Gain Gain (%)
    Application A 7.234 s 4.422 s 2.812 s 38.87%
    Application B 6.972 s 4.642 s 2.330 s 33.42%
    Application C 4.160 s 3.140 s 1.020 s 24.52%
    Application D 16.512 s 4.011 s 12.501 s 75.71%
    Application E 4.090 s 3.153 s 0.937 s 22.91%
    Application F 17.853 s 7.462 10.391 s 58.20%
    Average gain: 4.999 s 42.27%

    The average gain in application launch time is almost 5 seconds, which gives 42% improvement compared with the previous results. Our experiment proves it is worth to take an effort to optimize the application.

  • Here is what we did with each application:

    Application A B C D E F
    Convert your application to Tizen + + + + + +
    Enable prelaunching + + + + + +
    Minimize the amount of code loaded for the home page + + + + + +
    Load JS files asynchronously using defer or async attributes + + + + + +
    Send AJAX requests as soon as possible + + + +
    Parallelize AJAX requests + + +
    Concatenate AJAX calls + +
    Delay calls to webapis and tizen APIs + + + + +
    Cache TV APIs output + + + +
    Use at least v2.x of jQuery + + + +
    Load JavaScript files and other resources from local file system
    Minimize and concatenate code + + + + + +
    Remove obsolete code + + +
    Optimize graphics, use sprites + + + + + +
    Use pure CSS instead of graphics +
    Enforce GPU acceleration using CSS +
    Cache references to DOM elements + + + + + +
    Avoid using slow jQuery selectors + + +
    Replace jQuery/Underscore functions with faster native functions + +
    Remove console.logs + + + + +