question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Architecting for performance

See original GitHub issue

Goal: 10ms blocks

When you are in a browser environment, in order to have a smooth UI, main-thread JS should be kept to 10ms per frame. While the view layer is usually the larger culprit, we saw with minimongo (eg https://github.com/meteor/meteor/issues/6835) that updating the data store can easily exceed that 10ms budget.

Apollo work

Our JS work includes:

  1. performing client-side query
  2. sending query to server (should be quick)
  3. performing client-side simulated mutations
  4. receiving data and updating the store

Which of these might take over 10ms?

Solutions

  1. Code speed improvements
  2. Breaking work into estimated 10ms blocks and calling requestAnimationFrame between blocks. A proper system for this would be client-wide and include the view layer, so the per-frame work can be totaled / shared / turns can be taken. Related: meteor-kernel.
  3. Doing work in a Worker (which does not block UI)

1 and 3 would be best. Workers have separate memory, so if work on an in-memory store were in a Worker, the store would also have to be in the Worker, and you’d need to pass messages between the Worker and the main thread for each query or change notification. Both have access to the same persistent stores (IndexedDB and localStorage), but they don’t support change notifications, which you’d need for reactivity.

cc @mitar

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:4
  • Comments:23 (16 by maintainers)

github_iconTop GitHub Comments

9reactions
kokjinsamcommented, Jun 21, 2017

Hi @helfer , I wrote a slightly longer than expected response. Hope you don’t mind.

I have created a package called workux to facilitate Redux and web worker integration. Check it out here.

Redux & Web Worker Architecture

how redux and web worker work

Similar to createStore in Redux, Workux’s createProxyStore creates a proxy store that exposes same methods like getState, dispatch, etc. but with different underlying logic. This proxy store uses worker messaging protocol aka postMessage and onmessage to dispatch actions and receive Redux store updates respectively. User can also specify enhancers / middlewares that need browser APIs or DOM in createProxyStore. For example, react-router-redux uses history module, which will not be available on the worker thread, in its middleware. To add a note, All of these happen on the main thread.

Workux also provides a method createWorkerStore to attach worker messaging protocol to Redux store. So when Redux store gets updated, worker store will postMessage to proxy store. Similarly, when worker store receives an action from proxy store, it will dispatch the action to Redux store.

Problem with Apollo client

I have to initialize Apollo client on the main thread so that react-apollo can use it. With that being said, XHR requests still happens on the main thread. This kind of defeats the purpose of moving everything to web worker. Preferably, I would like to have web worker handle XHR requests, store updates, etc., leaving just the UI and animations on the main thread. One way to solve this is to create an Apollo proxy just like what I did with Redux. But that would be a lot of work and potentially lots of rough edges.

An Oversimplified Proposal

Instead of having an Apollo Client instance, split it up to smaller modules like createApolloMiddleware, createApolloReducer and createApolloClient. XHR requests will happen in createApolloMiddleware as it is now. createApolloClient will dispatch actions and listen to store updates. That way I can put createApolloReducer and createApolloMiddleware in web worker and createApolloClient on the main thread.

3reactions
lorensrcommented, Nov 22, 2016

Reactive specificity

An important optimization is to avoid recomputing the UI

Oh, I was thinking of that as part of the larger-culprit view layer I mentioned, since in Blaze that’s decided by which reactive deps you use inside helpers. Thanks, wasn’t familiar with how that’s different w/ Redux.

low-hanging things we can do to make sure that we only recompute queries whose dependencies have changed

That would be a bigger deal – matching the reactive specificity of Tracker & Minimongo.

Service workers

I was actually thinking about them when I left the Web out of Workers ☺️ It would be fantastic to not only not need to rehydrate the store on subsequent page loads, but not even need to fetch the changes since last load, because the background service had been receiving them. Ideally we put the store in:

  1. service worker when supported (chrome, FF, android)
  2. web worker when no service workers (IE, safari, iOS)
  3. main thread when no web workers (old IE, old android, or outside browser)

Measuring performance

You could use the Timeline or Profiles tab of Chrome Devtools for one-off. For repeatable tests that you can benchmark on different browsers, you can use the performance api, which is even supported on latest ios safari:

image

And have a test suite that times operations with moderate and large amounts of test data. A good slowest target might be mid-range Android phones.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Performance architecture selection - AWS Documentation
Often, multiple approaches are required to get optimal performance across a workload. Well-architected systems use multiple solutions and enable different ...
Read more >
Architecting for Performance Efficiency on AWS - Pluralsight
In this course, Architecting for Performance Efficiency on AWS, you will gain the ability to make architectural choices to select and implement whichever...
Read more >
Performance Architecture: The Well-Designed Process
To a Performance Architect, design means the solution's look-and-feel, accessibility, adaptability, ease-of-use, alignment with the Worker, ...
Read more >
What Is Performance Architecture? – HPT Treasures
Performance Architects are those that consider the full organization in all its aspects to design and align all the parts to best achieve...
Read more >
Architecting for Performance Clarity in Data Analytics ...
This thesis explores how to architect systems for performance clarity: the ability to understand where bottlenecks lie and the performance implications of ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found