GapLo.Tech
Virual DOM Reconciliation
Rendering
Painting
System
0ms
5ms
10ms
15ms
20ms
Why 99% of the Browsers’ UI threads are overworked?
State Management
Virual DOM Reconciliation
Rendering
Painting
System
Why 99% of the Browsers’ UI threads are overworked?
State Management
Remote API Response Massage
0ms
5ms
10ms
15ms
20ms
Virual DOM Reconciliation
Rendering
Painting
System
Why 99% of the Browsers’ UI threads are overworked?
State Management
Remote API Response Massage
0ms
5ms
10ms
15ms
20ms
Tracking Analytic Event
Virual DOM Reconciliation
Rendering
Painting
System
Why 99% of the Browsers’ UI threads are overworked?
State Management
Remote API Response Massage
0ms
5ms
10ms
15ms
20ms
Tracking Analytic Event
Persisting Data and Creating in-Memory Store
Why 99% of the Browsers’ UI threads are overworked?
0ms
5ms
10ms
15ms
20ms
Drop frame
Why 99% of the Browsers’ UI threads are overworked?
0ms
5ms
10ms
15ms
20ms
Drop frame
Why 99% of the Browsers’ UI threads are overworked?
104ms
Drop frame
Judged by Comparing
other platform's UI Development
let nameLabel = UILabel()
DispatchQueue.global(qos: .background).async {
getRemoteUser(id: 1) { data in
DispatchQueue.main.async {
nameLabel.text = data.username
}
}
}
Why the UI thread is underpaid?
val nameText = TextView()
GlobalScope.launch(Dispatchers.IO) {
val data = getRemoteUser(id = 1) // suspend function
GlobalScope.launch(Dispatchers.Main) {
nameText.text = data.username
}
}
Why the UI thread is underpaid?
const nameElem = document.getElementById('name')
// wait and process on main(UI) thread
const data = await getRemoteUser(1)
nameElem.innerHTML = data.username
Why the UI thread is underpaid?
Why the UI Thread is underpaid?
0ms
5ms
10ms
15ms
20ms
Drop frame
Why the UI Thread is underpaid?
0ms
5ms
10ms
15ms
20ms
Drop frame
Nokia 3.4, Released on September 2020
SnapDragon 460
- Equiv. to iPhone 5s
(7 year ago)
- Equiv. to Nexus 5X
(5 year ago)
Single Core Performance of 2020 Budget Phone
View
Action
Store
Dispatchers
Action
Main Thread
View
Action
Store
Dispatchers
Action
Web Worker
Main Thread
Worker Thread
View
Action
Store
Dispatchers
Action
Web Worker
Main Thread
Worker Thread
// app.js
const nameElem = document.getElementById('name')
// wait and process on main(UI) thread
const data = await getRemoteUser(1)
nameElem.innerHTML = data.username
// app.js
const nameElem = document.getElementById('name')
const worker = new Worker('./worker.js')
worker.postMessage({ topic: 'getRemoteUser', data: { id: 1 }})
worker.addEventListener('message', event => {
nameElem.innerHTML = event.data.username
})
// worker.js
async function getRemoteUser(id) {
return fetch(..)
}
addEventListener('message', async event => {
switch(event.data.topic) {
case 'getRemoteUser':
const data = await getRemoteUser(event.data)
postMessage(data)
default:
throw new Error('not supported message')
}
})
Turning Message-driven to RPC
import { getRemoteUser } from './userApi.worker.singleton.js'
const nameElem = document.getElementById('name')
// now process on worker thread!
const data = await getRemoteUser(1)
nameElem.innerHTML = data.username
// userApi.worker.singleton.js
export async function getRemoteUser(id) {
return fetch(..)
}