JavaScript on the Desktop
Fast and Slow
CGI
Battlefield 1
Nvidia GeForce Experience
Adobe
Creative Suite
All the Electron Apps
Let's Talk Performance
🚀
💾
Memory
⏱
Speed
🔋
Energy
const isReachable = require('is-reachable')
async function isDotReachable() {
const dotReachable = await isReachable('dotjs.io')
console.log(dotReachable)
}
1️⃣ Modules
94000
Lines of JSON
const isReachable = require('is-reachable')
async function isDotReachable() {
const dotReachable = await isReachable('dotjs.io')
console.log(dotReachable)
}
Modules
// Don't require the module until you need it
// require() caches results
async function isDotReachable() {
const isReachable = require('is-reachable')
const dotReachable = await isReachable('dotjs.io')
console.log(dotReachable)
}
// Do you even need a module?
function isDotReachable() {
return new Promise((resolve, reject) => {
const http = require('http')
http.get('http://dotjs.io', () => {
resolve()
}).on('error', (e) => {
reject(e)
})
})
}
#!/usr/bin/env node
'use strict';
[...]
try {
require(__dirname + '/../lib/v8-compile-cache.js');
} catch (err) {
}
[...]
V8 Code Caching
require('v8-compile-cache')
async function isDotReachable() {
// The "compiled" blobs are now cached
// Have V8 parse the module only once
const isReachable = require('is-reachable')
const dotReachable = await isReachable('dotjs.io')
console.log(dotReachable)
}
Careful, Cowboy
might cost you
npm install
Turning your code
into pixels
Make it easy
2️⃣
// Option 1
const divs = document.querySelectorAll('.test-class')
// Option 2
const divs = document.getElementsByClassName('test-class')
// 🤔 Which one is faster? And by how much? Let's find out:
// https://jsperf.com/dotjs-perf-example
3️⃣ Not all code is equal
document.querySelectorAll('.test-class')
375,363 ops/sec
±5.27%, 99% slower
document.getElementsByClassName('test-class')
29,318,183 ops/sec
±0.55%
#include <nan.h>
NAN_METHOD(IsPrime) {
if (!info[0]->IsNumber()) {
Nan::ThrowTypeError("Argument must be a number!");
return;
}
int number = (int) info[0]->NumberValue();
if (number < 2) {
info.GetReturnValue().Set(Nan::False());
return;
}
for (int i = 2; i < number; i++) {
if (number % i == 0) {
info.GetReturnValue().Set(Nan::False());
return;
}
}
info.GetReturnValue().Set(Nan::True());
}
NAN_MODULE_INIT(Initialize) {
NAN_EXPORT(target, IsPrime);
}
NODE_MODULE(addon, Initialize);
Go Native
// Brought to you by Parcel:
// Import a wasm file like it's no big deal
const { add } = await import('./add.wasm')
const result = add(2, 3)
// 🙀 Same trick, but with Rust
const { add } = await import('./add.rs')
const result = add(2, 3)
// Rust, a true teamplayer
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
return a + b
}
Application
Lifecycle
Respect it
4️⃣
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
// Suspend all expensive operations
// 🔪 setInterval()
// 🔪 Animations
// 🔪 Not-urgent network requests
} else {
// Continue!
}
})
Background
@felixrieseberg
JavaScript on the Desktop, Fast and Slow
By Felix Rieseberg
JavaScript on the Desktop, Fast and Slow
- 1,800