-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Architecting for performance #128
Comments
What about using service workers? So that client-side database could really be a service running in the background? |
(This can then be nicely turned into offline use as well.) |
@lorensr is there some way to run perf tests on this library without trying to guess at which parts are slow? |
An important optimization is to avoid recomputing the UI (virtual DOM or other) when the state hasn’t changed, which is a problem a state management library like MobX is good at solving (see Dan Abramov tweet on that and related detailed explanations). For its internal state management, the Apollo client uses Redux which isn’t as efficient by default but has other advantages (good community support, replayable state transitions, dev tools, etc). The good news is that the Redux community is aware of MobX-like dependency management and is working on the abstractions that would bring that to Redux as well (cf. Reselect selectors). I’m confident that fined-grained dependency tracking, including a notion of a “derived value” and memoization, will be standardized and recommended in the future Redux. If not, a possibility we also have is to swap the internal Apollo-client store as we discussed a bit in #63 but I would prefer to see some convergence between Redux and MobX than having to build a store abstraction that would support multiple backends under the hood as proposed in #92. |
There are some very low-hanging things we can do to make sure that we only recompute queries whose dependencies have changed, I think - that's why I want to have real profiling rather than guessing at what will make things faster, because I think we can get very far without even thinking about any of the stuff mentioned above. |
Reactive specificity
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.
That would be a bigger deal – matching the reactive specificity of Tracker & Minimongo. Service workersI was actually thinking about them when I left the Web out of Workers
Measuring performanceYou 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: 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. |
One optimization people are doing here is that they make sure that they can use referential equality to know when a change in state happened. The idea is that you have immutable state objects and if state changes, you provide a new object with a new reference. Then a very fast comparing objects with Maybe this is something Meteor can embrace. |
We're hoping to do that for Minimongo eventually, and I think it would make sense to go in that direction from the start with Apollo. |
Related info from JS community: Google decided to support putting your Angular 2 app inside a Web Worker: (thanks @Urigo for pointing that out)
Facebook doesn't want to put React inside a Worker (instead waiting for Compositor Workers to come out), but they're "actively exploring" putting Relay in a Worker: Also in Meteor: |
Very interesting! Actually I wonder if there is just a way to run all Redux reducers in a worker, that would help a lot. Then it's just about getting the query results to the UI. |
These are good notes, but I want to make sure we don't assume that these optimizations are necessary or appropriate for Apollo until we have some way to make those decisions in a data-driven way. |
Yeah, it was great how they were able to try immutablejs and just measure :) |
Slides about Relay 2, which includes a few performance things. Starting here: https://speakerdeck.com/wincent/relay-2-simpler-faster-more-predictable?slide=29
"Big bets":
optimizations: Improving time-to-interaction |
How is Apollo performance now? immutability and shouldcomponentupdate etc |
@scf4 we haven't gotten around to doing any profiling yet. If you'd like to help out and set up a benchmark or something, that would be great! |
This would be a cool thing to take on for the contributer week this week. I am too inexperienced, otherwise I'd jump on it. I know the topic of a performant architecture is going to be a major USP for Apollo at some point, if it isn't already. Scott |
I think a really cool way to work on this if anyone in the thread is still interested is to see if we can modify |
Closing up old issues. Let's track this under #1409 |
Hi @sammkj we haven't thought too much about it yet, but we'd definitely like to support that use-case. Can you tell us how you would envision using Apollo with a web worker? |
Hi @helfer , I wrote a slightly longer than expected response. Hope you don't mind. I have created a package called Redux & Web Worker ArchitectureSimilar to Workux also provides a method Problem with Apollo clientI have to initialize Apollo client on the main thread so that An Oversimplified ProposalInstead of having an Apollo Client instance, split it up to smaller modules like |
Since this is basically a perf optimization I wonder if there is a way to architect apollo to allow people to use https://github.com/developit/workerize-loader for xhr. This way if you don't provide an implementation via the loader then the default on main thread implementation would be used. |
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 meteor/meteor#6835) that updating the data store can easily exceed that 10ms budget.
Apollo work
Our JS work includes:
Which of these might take over 10ms?
Solutions
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.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
The text was updated successfully, but these errors were encountered: