This topic presents a case study of improving an application to reduce its launch time. It describes the application launch process, techniques for reducing application loading time, and best practices for writing more efficient JavaScript.
Applications that offer a good user experience (UX) attract more users. Users who have positive impressions of an application return to it and are more likely to recommend it to others. If you monetize the application, this can result in greater profit.
Application launch time is the total time from the moment when the user clicks the application icon until the application is ready to use.
Improving the application launch time improves the user experience. Because application loading is the first experience the user gets of your application, a long loading time can leave them with a negative impression.
Therefore, it is worthwhile to prioritize reducing application launch time.
User satisfaction drastically decreases as the application launch time increases, as shown in the following figure based on a user survey. Using this information, a target launch time of around 5-7 seconds satisfies most users.
Application Launch Process
The application launch process can be divided into 5 stages. Some stages are controlled by the system, but most stages are dependent on application implementation, providing opportunities for performance improvement.
This case study is based on an application running on a 2015 Samsung Smart TV. Video was captured while launching the application on the TV, enabling the duration of each application launch stage to be measured with an accuracy of one video frame.
NoteIf you want to test your application in a similar way, make sure that all tests are performed under the same circumstances, such as using the same device with the same network conditions, to reduce the effects of external factors.
The following figure illustrates the application launch stages, and the time spent at each stage for the case study application.
The following table describes each stage in detail.
Stage
Action
Screen
Time
Description
1
Application icon click
1.086s
Time between clicking the application icon to when the Smart Hub "Apps" panel disappears.
2
Initial loading screen
4.979s
Time between loading the home page ("index.html") and calling the window.onload() method.
3
Black screen
0.837s
Time a transition screen is shown before calling the window.onload() method (for Samsung Legacy Platform applications only).
4
Splash image
0.570s
Time until the splash image appears. The splash image is the first screen shown in the application after calling the window.onload() method. It is usually shown during authentication or while content is loading.
5
Home page
0.348s
Time taken to render the home page, fill it with content, and enable user input.
Table 1. Application launch stages
Optimizing Launch Logic
This section assumes that the case study application utilizes a framework. The framework contains modules responsible for activities, such as sending AJAX requests to the backend server, application authorization in the backend side, and modules responsible for the UI and logic.
The case study application loading process is illustrated in the following figure.
The application logic is dependent on the framework setup. In stages 2 and 3, load and initialize the framework.
After the framework setup is complete, start authorization at the backend server with the application logic.
If authorization succeeds, send AJAX requests to the backend server to fetch application data, such as a list of recommended movies to display on the application home page.
AJAX requests are dependent on the authorization step, because they must contain an authorization token.
Wait for the data needed to render the home page, and render it.
This model is not optimized because the entire framework must be loaded and initialized before the application can start the authorization and content loading processes.
A possible approach to speeding up the launch process is by rebuilding the application in the following way.
Divide the framework setup into 2 phases:
In the first phase, load the modules responsible for application authorization.
In the second phase, initialize the rest of the framework.
Once the first phase is loaded, perform authorization immediately. It is only dependent on the XHR object created in Stage 1 during Web runtime setup. Multiple AJAX requests are merged into 1 request to avoid unnecessary delays. The AJAX request is dependent on the authorization step for the authorization token.
When the framework is fully initialized, begin performing the basic home page setup without waiting for the AJAX request response.
Stage 3 is eliminated completely by migrating the application from Samsung Legacy Platform to Tizen.
Padding time is needed to synchronize the application logic and AJAX requests. The application logic requires AJAX request data to render the home page, but as the requests are asynchronous, implement mechanisms to coordinate the modules, such as events, callbacks, and promises.
Resume the application logic after receiving the response from the server.
Load other parts of application logic, such as required scripts and data, on demand. In this way, they do not delay the launch process.
This flow is more optimized, as many tasks are performed in parallel. Initially, the application loads only the modules which are necessary for authorization and starts authorization immediately along with other operations, such as loading the rest of the framework, the UI, resources, and content. Any tasks not required for displaying the home page are postponed to start after the launch process. Consequently, application launch time is much shorter than before.
Improving Launch Time
The following table lists optimization strategies that can improve application launch time, and the application launch stages they affect.
Optimization
Stage
1
2
3
4
5
Migrating application to Tizen
+
+
Enabling prelaunch
+
+
+
+
Minimizing home page code
+
+
Loading JS files asynchronously
+
+
Sending AJAX requests promptly
+
+
Parallelizing AJAX requests
Concatenating AJAX requests
+
+
+
Delaying platform and Tizen API calls
+
+
Caching API output
+
+
+
Using jQuery 2.x or higher
+
+
+
Loading static resources locally
+
+
Minimizing and concatenating code
+
+
Removing obsolete code
+
+
Using sprites
+
+
+
Using pure CSS
+
+
+
Enforcing GPU acceleration
+
Table 2. Launch stages affected by optimizations
Migrating Application to Tizen
Stages affected: 1 and 3
Tizen is more efficient than Samsung Legacy Platform. Migrating the application from Samsung Legacy Platform to Tizen can improve its performance significantly.
Enabling Prelaunch
Stages affected: 1, 2, 4, and 5
TV Web applications in Tizen support prelaunching. Applications can load in the background when the Samsung TV is switched on. When the user launches the application, it loads more quickly because it has been prelaunched.
Application launch time can be improved by loading and parsing less code at launch. When the application launches, load only the HTML, JS, and CSS code necessary to show the home page. Other code can be loaded on demand using a library, such as require.js, to avoid building and parsing the DOM before it is needed.
Loading JavaScript Files Asynchronously
Stages affected: 2 and 4
When loading external JavaScript files normally, the HTML parser stops while the JavaScript files are downloaded and executed.
To avoid the pause in HTML parsing during download, you can use the defer and async attributes:
Using the defer attribute downloads the JavaScript file in parallel while parsing HTML. The JavaScript code executes only when all HTML parsing is complete. Scripts using the defer attribute are guaranteed to execute in the same order that they appear in the document.
Using the async attribute downloads the JavaScript file in parallel while parsing HTML, but when the download completes, the HTML parser pauses to execute the script.
The defer and async attributes can be used only for scripts implemented with the script element and src attribute.
You can improve launch time by optimizing AJAX request usage:
Sending AJAX requests promptly
Stages affected: 2 and 4
Most applications load their content from remote servers and utilize a framework that helps manage the requests. However, loading and executing the framework code can take a lot of time. To speed up application launch, send the AJAX requests needed to display the home page as soon as possible.
You can send a simple XHR request at the beginning of the "index.html" file, before loading the framework. XHR requests are asynchronous and do not block any other threads. Cache the response in a global object, so the application framework can use the data immediately to display the home page without sending the request again.
Parallelizing AJAX requests
Send AJAX requests in parallel if they are not dependent on responses from prior requests:
Before:
Each request is executed after receiving a response from the previous one:
Stages affected: 2, 4, and 5
Limit the number of AJAX requests by merging several requests, if possible. The fewer requests there are, the less time it takes to process all of them.
For example, consider an application that sends 3 requests to display the home page, such as for application authorization, a list of recommended movies, and a list of the latest movies. Verify whether it is possible to modify the requests and backend in such a way that the response for the authorization request contains the recommended and latest movies as well.
You can also use this strategy throughout the application to reduce the loading time of other scenes.
Delaying Platform and Tizen API Calls
Stages affected: 2 and 4
Many applications make early calls to Tizen and platform APIs for static information, such as the DUID or model code. Because API initialization is "lazy" (the API is initialized only when it is first needed), the first call to each API module takes time. Postpone API calls until the application is fully started and ready to use, if possible.
Caching API Output
Stages affected: 2, 4, and 5
Instead of querying the API each time, cache the static output from Product and Tizen APIs in JavaScript variables.
Consider the following scenarios:
The total duration of video content is constant during video playback. You can retrieve it once and store it in a JavaScript variable instead of querying the API each time it is needed.
TV specification parameters, such as the DUID or model code, never change. You can retrieve the parameters using the API the first time the application is launched and save it in localStorage. Retrieving data from localStorage is quicker than querying the API.
Using jQuery 2.x or Higher
Stages affected: 2, 4, and 5
Newer versions of jQuery are smaller and faster. You can also consider using a custom jQuery build.
Loading Static Resources Locally
Stages affected: 2 and 4
Load static application resources directly from the local file system, by including all application source code, external libraries, and static UI elements, such as CSS and images, within the Tizen package:
This not only decreases loading time, but can also improve application security and eliminate some application errors caused by network issues.
Minimizing and Concatenating Code
Stages affected: 2 and 4
The application loads faster when it makes fewer requests to the file system. If you do not want to use a lazy loading mechanism to load parts of the application on demand, concatenate and minimize your source code, especially JavaScript and CSS files:
In some situations, it can be better to concatenate your code into 2 files instead of 1:
If the code must be executed as soon as possible, put it into a file that is loaded with the async attribute.
If the code requires the DOM to be ready before execution, put it in another file that is loaded with the defer attribute.
Make sure that the code loads in the correct order to satisfy its dependencies.
Removing Obsolete Code
Stages affected: 2 and 4
If the application loads any unused source code, whether it is JavaScript, CSS, or HTML, the browser takes time to parse it, build the DOM, and search the HTML code for matching CSS rules. Keep your code clean and up to date to avoid unnecessary performance issues caused by obsolete or redundant code.
For example, when the window.onload() method is called, calling the unregisterKey() method of the TVInputDevice API is unnecessary because no keys are registered other than the default "Left", "Up", "Right", "Down", "Enter", and "Back" keys.
Using Sprites
Stages affected: 2, 4, and 5
If your application loads many small graphics, such as icons, button elements, and backgrounds, consider using CSS sprites. CSS sprites help images load faster by making fewer requests to the file system, which improves overall application performance.
You can merge all of the icons or background images into 1 large image and use CSS to set the positions for each element. Consider the following mouse hover implementation:
This code is not optimal, as the browser must make 2 requests to the file system instead of 1. Additionally, the first time the user hovers on the button, its background will flicker, as some time is needed to request the new image and show it on the screen.
This code is more optimal because it loads only 1 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 the states.
Using Pure CSS
Stages affected: 2, 4, and 5
Tizen supports CSS3, which allows you to create many graphic effects without using image files. Pure CSS renders faster and takes less time to calculate its properties, which is especially valuable when animating CSS elements.
The following code creates a button using only pure CSS:
Normally, the browser applies GPU acceleration when there is some indication that a DOM element can benefit from it.
CSS3 allows you to force the browser to render elements with GPU acceleration. One of the simplest methods is setting a style indicating 3D transform, even when no real 3D transformation is applied:
Follow a reliable and consistent coding standard and style for JavaScript, as it makes the code easier to write, easier to read, improves its maintainability, and makes it less error-prone.
The following section presents JavaScript best practices that are frequently used in the Web community.
Caching DOM Element References
Searching the DOM tree is a resource-hungry operation. If there are DOM elements on which you perform operations frequently, store them in JavaScript variables to avoid repetitive DOM traversal:
Prefer:
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');
Avoid:
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');
It can be helpful to store references to frequently-used DOM elements in a global object. For example:
jQuery selectors work slower than native ones. If application performance is critical, consider replacing jQuery selectors, for example:
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');
Using Native Methods
Native JavaScript methods are faster than wrappers from different libraries. In some cases, it can 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]);
}
Removing Console Logging
Extensive logging decreases application performance, because each console.log() method call blocks the JavaScript thread in the browser. Other logging methods, such as the console.warn(), console.info(), console.error() methods, behave similarly. To improve application performance, remove log methods in the final build.
You can use a logger utility to easily switch logging on and off. Open source libraries, such as Woodman, are available, or you can write your own logger, such as the following example:
// Global object for storing application configuration
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'); // Outputs 'test' to console
//For production
var applicationConfig = {
debugMode: false
};
var myLog = new Logger(); // Initializes logger
myLog.log('test'); // Does nothing
ImportantNever override console.log() or any other native function.
Overriding native objects is a bad practice in JavaScript, as it can lead to unexpected behavior and introduce defects that are very hard to debug.
Optimization Results
The principles described in this guide were applied to several Samsung TV applications, as listed in the following table.
Optimization
Application
A
B
C
D
E
F
Migrating application to Tizen
+
+
+
+
+
+
Enabling prelaunch
+
+
+
+
+
+
Minimizing home page code
+
+
+
+
+
+
Loading JS files asynchronously
+
+
+
+
+
+
Sending AJAX requests promptly
+
+
+
+
Parallelizing AJAX requests
+
+
+
Concatenating AJAX requests
+
+
Delaying platform and Tizen API calls
+
+
+
+
+
Caching API output
+
+
+
+
Using jQuery 2.x or higher
+
+
+
+
Loading static resources locally
Minimizing and concatenating code
+
+
+
+
+
+
Removing obsolete code
+
+
+
Using sprites
+
+
+
+
+
+
Using pure CSS
+
Enforcing GPU acceleration
+
Caching DOM element references
+
+
+
+
+
+
Avoiding slow jQuery selectors
+
+
+
Using native methods
+
+
Removing console logging
+
+
+
+
+
Table 3. Optimizations applied to Samsung TV applications
The following table lists the launch time optimization results.
Application
Before Optimization
After Optimization
Reduction
Reduction (%)
A
7.234 s
4.422 s
2.812 s
38.87%
B
6.972 s
4.642 s
2.330 s
33.42%
C
4.160 s
3.140 s
1.020 s
24.52%
D
16.512 s
4.011 s
12.501 s
75.71%
E
4.090 s
3.153 s
0.937 s
22.91%
F
17.853 s
7.462 s
10.391 s
58.20%
Average Reduction:
4.999 s
42.27%
Table 4. Results of application launch time optimization
The average reduction in application launch time was almost 5 seconds, a 42% improvement. This result suggests that it is worthwhile to optimize applications, wherever possible.
Manage Your Cookies
We use cookies to improve your experience on our website and to show you relevant
advertising. Manage you settings for our cookies below.
Essential Cookies
These cookies are essential as they enable you to move around the website. This
category cannot be disabled.
Company
Domain
Samsung Electronics
.samsungdeveloperconference.com
Analytical/Performance Cookies
These cookies collect information about how you use our website. for example which
pages you visit most often. All information these cookies collect is used to improve
how the website works.
Company
Domain
LinkedIn
.linkedin.com
Meta (formerly Facebook)
.samsungdeveloperconference.com
Google Inc.
.samsungdeveloperconference.com
Functionality Cookies
These cookies allow our website to remember choices you make (such as your user name, language or the region your are in) and
tailor the website to provide enhanced features and content for you.
Company
Domain
LinkedIn
.ads.linkedin.com, .linkedin.com
Advertising Cookies
These cookies gather information about your browser habits. They remember that
you've visited our website and share this information with other organizations such
as advertisers.
Company
Domain
LinkedIn
.linkedin.com
Meta (formerly Facebook)
.samsungdeveloperconference.com
Google Inc.
.samsungdeveloperconference.com
Preferences Submitted
You have successfully updated your cookie preferences.