perf: 90ms improvement: Defer more code in renderer, load state earlier
By deferring more code in the renderer and loading state earlier, we improve startup time by another 90ms! Before: 507 unique requires (1270-1280ms) After: 506 unique requires (1180-1190ms)
This commit is contained in:
@@ -45,18 +45,26 @@ function init (state, options) {
|
|||||||
y: initialBounds.y
|
y: initialBounds.y
|
||||||
})
|
})
|
||||||
|
|
||||||
win.once('ready-to-show', function () {
|
win.loadURL(config.WINDOW_MAIN)
|
||||||
|
|
||||||
|
win.once('ready-to-show', () => {
|
||||||
if (!options.hidden) win.show()
|
if (!options.hidden) win.show()
|
||||||
})
|
})
|
||||||
|
|
||||||
win.loadURL(config.WINDOW_MAIN)
|
if (win.setSheetOffset) {
|
||||||
|
win.setSheetOffset(config.UI_HEADER_HEIGHT)
|
||||||
if (win.setSheetOffset) win.setSheetOffset(config.UI_HEADER_HEIGHT)
|
}
|
||||||
|
|
||||||
win.webContents.on('dom-ready', function () {
|
win.webContents.on('dom-ready', function () {
|
||||||
menu.onToggleFullScreen(main.win.isFullScreen())
|
menu.onToggleFullScreen(main.win.isFullScreen())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
win.webContents.on('will-navigate', (e, url) => {
|
||||||
|
// Prevent drag-and-drop from navigating the Electron window, which can happen
|
||||||
|
// before our drag-and-drop handlers have been initialized.
|
||||||
|
e.preventDefault()
|
||||||
|
})
|
||||||
|
|
||||||
win.on('blur', onWindowBlur)
|
win.on('blur', onWindowBlur)
|
||||||
win.on('focus', onWindowFocus)
|
win.on('focus', onWindowFocus)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ const config = require('../../config')
|
|||||||
|
|
||||||
const SAVE_DEBOUNCE_INTERVAL = 1000
|
const SAVE_DEBOUNCE_INTERVAL = 1000
|
||||||
|
|
||||||
|
appConfig.filePath = path.join(config.CONFIG_PATH, 'config.json')
|
||||||
|
|
||||||
const State = module.exports = Object.assign(new EventEmitter(), {
|
const State = module.exports = Object.assign(new EventEmitter(), {
|
||||||
getDefaultPlayState,
|
getDefaultPlayState,
|
||||||
load,
|
load,
|
||||||
@@ -16,13 +18,11 @@ const State = module.exports = Object.assign(new EventEmitter(), {
|
|||||||
// After first State.save() invokation, future calls go straight to the
|
// After first State.save() invokation, future calls go straight to the
|
||||||
// debounced function
|
// debounced function
|
||||||
State.save = debounce(saveImmediate, SAVE_DEBOUNCE_INTERVAL)
|
State.save = debounce(saveImmediate, SAVE_DEBOUNCE_INTERVAL)
|
||||||
State.save()
|
State.save(...arguments)
|
||||||
},
|
},
|
||||||
saveImmediate
|
saveImmediate
|
||||||
})
|
})
|
||||||
|
|
||||||
appConfig.filePath = path.join(config.CONFIG_PATH, 'config.json')
|
|
||||||
|
|
||||||
function getDefaultState () {
|
function getDefaultState () {
|
||||||
const LocationHistory = require('location-history')
|
const LocationHistory = require('location-history')
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Reports back so that we can improve WebTorrent Desktop
|
// Reports back so that we can improve WebTorrent Desktop
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init,
|
init,
|
||||||
|
send,
|
||||||
logUncaughtError,
|
logUncaughtError,
|
||||||
logPlayAttempt
|
logPlayAttempt
|
||||||
}
|
}
|
||||||
@@ -22,7 +23,9 @@ function init (state) {
|
|||||||
telemetry = state.saved.telemetry = createSummary()
|
telemetry = state.saved.telemetry = createSummary()
|
||||||
reset()
|
reset()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function send (state) {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
telemetry.version = config.APP_VERSION
|
telemetry.version = config.APP_VERSION
|
||||||
telemetry.timestamp = now.toISOString()
|
telemetry.timestamp = now.toISOString()
|
||||||
@@ -223,7 +226,7 @@ function getElemString (elem) {
|
|||||||
let ret = elem.tagName
|
let ret = elem.tagName
|
||||||
try {
|
try {
|
||||||
ret += '.' + Array.from(elem.classList).join('.')
|
ret += '.' + Array.from(elem.classList).join('.')
|
||||||
} catch (e) {}
|
} catch (err) {}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ console.time('init')
|
|||||||
const crashReporter = require('../crash-reporter')
|
const crashReporter = require('../crash-reporter')
|
||||||
crashReporter.init()
|
crashReporter.init()
|
||||||
|
|
||||||
|
// Perf optimization: Start asynchronously read on config file before all the
|
||||||
|
// blocking require() calls below.
|
||||||
|
|
||||||
|
const State = require('./lib/state')
|
||||||
|
State.load(onState)
|
||||||
|
|
||||||
const dragDrop = require('drag-drop')
|
const dragDrop = require('drag-drop')
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
@@ -12,7 +18,6 @@ const ReactDOM = require('react-dom')
|
|||||||
const config = require('../config')
|
const config = require('../config')
|
||||||
const telemetry = require('./lib/telemetry')
|
const telemetry = require('./lib/telemetry')
|
||||||
const sound = require('./lib/sound')
|
const sound = require('./lib/sound')
|
||||||
const State = require('./lib/state')
|
|
||||||
const TorrentPlayer = require('./lib/torrent-player')
|
const TorrentPlayer = require('./lib/torrent-player')
|
||||||
|
|
||||||
// Required by Material UI -- adds `onTouchTap` event
|
// Required by Material UI -- adds `onTouchTap` event
|
||||||
@@ -50,22 +55,22 @@ let state
|
|||||||
// Root React component
|
// Root React component
|
||||||
let app
|
let app
|
||||||
|
|
||||||
State.load(onState)
|
|
||||||
|
|
||||||
// Called once when the application loads. (Not once per window.)
|
// Called once when the application loads. (Not once per window.)
|
||||||
// Connects to the torrent networks, sets up the UI and OS integrations like
|
// Connects to the torrent networks, sets up the UI and OS integrations like
|
||||||
// the dock icon and drag+drop.
|
// the dock icon and drag+drop.
|
||||||
function onState (err, _state) {
|
function onState (err, _state) {
|
||||||
if (err) return onError(err)
|
if (err) return onError(err)
|
||||||
state = window.state = _state // Make available for easier debugging
|
|
||||||
|
// Make available for easier debugging
|
||||||
|
state = window.state = _state
|
||||||
window.dispatch = dispatch
|
window.dispatch = dispatch
|
||||||
|
|
||||||
telemetry.init(state)
|
telemetry.init(state)
|
||||||
|
|
||||||
// Log uncaught JS errors
|
// Log uncaught JS errors
|
||||||
window.addEventListener('error',
|
window.addEventListener(
|
||||||
(e) => telemetry.logUncaughtError('window', e),
|
'error', (e) => telemetry.logUncaughtError('window', e), true /* capture */
|
||||||
true /* capture */)
|
)
|
||||||
|
|
||||||
// Create controllers
|
// Create controllers
|
||||||
controllers = {
|
controllers = {
|
||||||
@@ -90,23 +95,18 @@ function onState (err, _state) {
|
|||||||
// Restart everything we were torrenting last time the app ran
|
// Restart everything we were torrenting last time the app ran
|
||||||
resumeTorrents()
|
resumeTorrents()
|
||||||
|
|
||||||
|
// Initialize ReactDOM
|
||||||
|
app = ReactDOM.render(<App state={state} />, document.querySelector('#body'))
|
||||||
|
|
||||||
// Calling update() updates the UI given the current state
|
// Calling update() updates the UI given the current state
|
||||||
// Do this at least once a second to give every file in every torrentSummary
|
// Do this at least once a second to give every file in every torrentSummary
|
||||||
// a progress bar and to keep the cursor in sync when playing a video
|
// a progress bar and to keep the cursor in sync when playing a video
|
||||||
setInterval(update, 1000)
|
setInterval(update, 1000)
|
||||||
app = ReactDOM.render(<App state={state} />, document.querySelector('#body'))
|
|
||||||
|
|
||||||
// Lazy-load other stuff, like the AppleTV module, later to keep startup fast
|
|
||||||
window.setTimeout(delayedInit, config.DELAYED_INIT)
|
|
||||||
|
|
||||||
// Listen for messages from the main process
|
// Listen for messages from the main process
|
||||||
setupIpc()
|
setupIpc()
|
||||||
|
|
||||||
// Warn if the download dir is gone, eg b/c an external drive is unplugged
|
// Drag and drop files/text to start torrenting or seeding
|
||||||
checkDownloadPath()
|
|
||||||
|
|
||||||
// OS integrations:
|
|
||||||
// ...drag and drop files/text to start torrenting or seeding
|
|
||||||
dragDrop('body', {
|
dragDrop('body', {
|
||||||
onDrop: onOpen,
|
onDrop: onOpen,
|
||||||
onDropText: onOpen
|
onDropText: onOpen
|
||||||
@@ -119,18 +119,28 @@ function onState (err, _state) {
|
|||||||
window.addEventListener('focus', onFocus)
|
window.addEventListener('focus', onFocus)
|
||||||
window.addEventListener('blur', onBlur)
|
window.addEventListener('blur', onBlur)
|
||||||
|
|
||||||
// ...window visibility state.
|
|
||||||
document.addEventListener('webkitvisibilitychange', onVisibilityChange)
|
|
||||||
|
|
||||||
// Done! Ideally we want to get here < 500ms after the user clicks the app
|
|
||||||
if (electron.remote.getCurrentWindow().isVisible()) {
|
if (electron.remote.getCurrentWindow().isVisible()) {
|
||||||
sound.play('STARTUP')
|
sound.play('STARTUP')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To keep app startup fast, some code is delayed.
|
||||||
|
window.setTimeout(delayedInit, config.DELAYED_INIT)
|
||||||
|
|
||||||
|
// Done! Ideally we want to get here < 500ms after the user clicks the app
|
||||||
console.timeEnd('init')
|
console.timeEnd('init')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs a few seconds after the app loads, to avoid slowing down startup time
|
// Runs a few seconds after the app loads, to avoid slowing down startup time
|
||||||
function delayedInit () {
|
function delayedInit () {
|
||||||
|
telemetry.send(state)
|
||||||
|
|
||||||
|
// Warn if the download dir is gone, eg b/c an external drive is unplugged
|
||||||
|
checkDownloadPath()
|
||||||
|
|
||||||
|
// ...window visibility state.
|
||||||
|
document.addEventListener('webkitvisibilitychange', onVisibilityChange)
|
||||||
|
onVisibilityChange()
|
||||||
|
|
||||||
lazyLoadCast()
|
lazyLoadCast()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user