Launch Time Optimization
launch time optimization 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 for more information, see prelaunching applications minimizing home page code stages affected 2 and 5 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 <script src='js/main js' defer></script> <script src='js/scripts js' async></script> 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 for more information, see the html <script> element handling ajax requests 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 sendrequest1 onsuccess sendrequest2 onsuccess sendrequest3 onsuccess sendrequest4 onsuccess sendrequest5 after the first request authorizes the application after receiving the response, the other requests are executed asynchronously sendrequest1 onsuccess sendrequest2 sendrequest3 sendrequest4 sendrequest5 concatenating ajax requests 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 before <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> after <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> 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 before <!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> after<!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> 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 before #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 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 after #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 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 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 ; } enforcing gpu acceleration stage affected 5 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 acceleratedelem { -webkit-transform translatez 0 ; } in general, 3d transformations in css force the browser to use the gpu the following declarations can reduce flickering during css transforms or animations acceleratedelem { -webkit-backface-visibility hidden; -webkit-perspective 1000; } for more information, see an introduction to css 3-d transforms and increase site performance with hardware-accelerated css optimizing javascript code 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 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' ; avoiding slow jquery selectors 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 beforeoptimization afteroptimization 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