Enact Performance Guide
Overview
Section titled “Overview”Performance is a critical portion of any application. With Enact you can use all the same tools as you normally would for React. We recommend reading this first to gain familiarity with performance testing in React.
Some important things to understand are how to use React’s performance timeline, understand how to use shouldComponentUpdate to avoid reconciliation, and learning to not mutate data if possible.
Enact provides some useful tools to help you achieve faster performance.
Managing async calls
Section titled “Managing async calls”Job is a class in our core module. It’s a useful wrapper for async things like setTimeout and requestIdleCallback. We also provide functionality like throttling that we’ll describe below.
In some modern browsers, there is support for requestIdleCallback. In Job we can access this through idle. This calls a function only when the browser is in an idle state. This is great for functions that don’t need to be called immediately and can be called asynchronously without blocking the main thread.
import {Job} from '@enact/core/util';
const importantButNotHighPriority = new Job(doSomething);
this.importantButNotHighPriority.idle();Throttle
Section titled “Throttle”Sometimes a function will execute too often. For instance, let’s take something like an onWheel event. This event may fire too often for out liking, causing reduced performance and ultimately a bad user experience. To throttle it, we can do something like:
import {Job} from '@enact/core/util';
// We can set up Job like so this.// The 2nd argument will set how often the event should fire in millisecondsconst throttleEvent = new Job(doSomething, 100);
// When we run the event we can do this.// This will run the event every 100ms even if we fire it more often.const handleWheel = () => { this.throttleWheelInc.throttle();}
// render method<div onWheel={handleWheel}>Wheel Div</div>Dealing with long lists of data
Section titled “Dealing with long lists of data”React recommends using virtualized lists for rendering long lists of data. This is for a good reason. Virtualized lists drastically reduce the number of repainting and reflowing that normally cause browsers to slow down. Enact includes our own implementation of a VirtualList that makes it easy to achieve this performance boost.
Production Packing
Section titled “Production Packing”Enact’s cli tool provides a way to create, test, and build applications. When packing your application for production, cli makes it very simple.
To build your app in production mode, run the command below. This will minify and “uglify” all of your code and bundle it into a single file.
enact pack --productionIsomorphic
Section titled “Isomorphic”To generate a static version of the first page, you can use our isomorphic flag. This will create an HTML representation of your entry page, allowing users to see the initial content much faster.
enact pack --production --isomorphicUsing timestamps
Section titled “Using timestamps”perfNow is useful for getting higher resolution timestamps to see how long a set of functions take. It’s a nice little wrapper around window.performance.now that will fall back to Date.now.
import {perfNow} from '@enact/core/util';
const firstTime = perfNow();
const secondTime = perfNow();
const difference = secondTime - firstTime;Working with webOS
Section titled “Working with webOS”If you’re developing for webOS, using Enact, we have some specialized tools to help you with that as well.
We can run a log to see how long an application took to launch:
pmctl perflog-reportThis will print out some logs that looks like this:
Type: AppLaunchGroup: com.webos.app.coolappStart time: 2578.59Process MsgID Time(s) +Diff(s) Extrasurface-manager-starfish IM_KEY_INPUT 0.0 +0.0 key_value:0 key_code:272sam APP_LAUNCH 0.021 +0.021 status:start_prelaunchingsam APP_LAUNCH 0.03 +0.009 status:start_memory_checkingsam APP_LAUNCH 0.032 +0.002 status:start_launchingWebAppMgr APPLAUNCH_START 0.033 +0.001 APP_ID:com.webos.app.coolappWebAppMgr APPLOADED 1.665 +1.632 APP_ID:com.webos.app.coolapp URL:file:///usr/webos/applications/com.webos.app.coolapp/index.html PID:24274sam GET_FOREGROUND_APPINFO 1.838 +0.173WebAppMgr WINDOW_FOCUSIN 1.84 +0.002 APP_ID:com.webos.app.coolappElapsed time (s) : 1.840While this is great, we may want to add some custom timestamps to this log. To achieve this we can simply add perfLog from the webos package. It takes three arguments: perfLog(MsgID, Type, Group).
We can use it like this:
import {perfLog} from '@enact/webos/pmloglib'
perfLog('APP_INTERACTIVE', 'AppLaunch', 'com.webos.app.coolapp');The above will now output the same thing we previously had, but with more info.
Process MsgID Time(s) +Diff(s) Extrasurface-manager-starfish IM_KEY_INPUT 0.0 +0.0 key_value:0 key_code:272sam APP_LAUNCH 0.009 +0.009 status:start_prelaunchingsam APP_LAUNCH 0.019 +0.01 status:start_memory_checkingsam APP_LAUNCH 0.021 +0.002 status:start_launchingWebAppMgr APPLAUNCH_START 0.022 +0.001 APP_ID:com.webos.app.coolappWebAppMgr APPLOADED 0.6 +0.578 APP_ID:com.webos.app.coolapp URL:file:///usr/palm/applications/com.webos.app.coolapp/index.html PID:20509sam GET_FOREGROUND_APPINFO 1.188 +0.588WebAppMgr WINDOW_FOCUSIN 1.377 +0.189 APP_ID:com.webos.app.coolappWebAppMgr APP_INTERACTIVE 2.867 +1.49Elapsed time (s) : 2.867