Open ara4n opened 7 years ago
(random additional datapoint: FF 55 takes 1,200ms to render the same frame on dev - which is https://github.com/vector-im/riot-web/issues/2499)
Updated for perf improvements I've ben doing, notably avoiding the whole timeline panel re-render on room switch and removing the slow HTML manipulation on addCodeCopyButton.
@dbkr's work has improved things considerably for accounts with few rooms: for the test case I used in the original analysis here we are now at 196ms for first frame (158ms in onClick, and 38+46ms over the next two frames). (In prod build, it's 149ms for first frame (113ms in onClick) and 25+43ms over the next two frames).
refreshRoomList
takes about 160ms on my actual account currently, and we look to be calling it when we switch room (are we getting the js-sdk to emit new events when we change room?)This is what I was originally trying to fix in https://github.com/matrix-org/matrix-react-sdk/pull/807. @dbkr, was your stuff meant to avoid this?
...and now Firefox Quantum (57.0b3) is now very similar perf to Chrome. The test case on current develop gives 185ms to render the frame (compared with 158ms on Chrome). So, yay!
Current behaviour i'm seeing on today's develop on my main account when switching between #matrix and #matrix-dev is ~1s to update middlepanel & rightpanel, and then ~500ms afterwards to update leftpanel (triggered by sending a RR):
It's currently (on a much newer laptop) taking ~300ms in Electron to switch room to somewhere like Matrix HQ, which is just about doable but could still be much better.
171.3ms of that for instance is in _showMembersAccordingToMembershipWithLL
doing a membership sort, for instance...
in the new room list the actual room switch operation takes less than 50ms, though the rest of the UI trying to render is getting into the 700ms range.
A Pull Request to improve switch room rendering has landed. It is no where close to the 50ms that are originally mentioned but here is a list of things that have been tackled
_showMembersAccordingToMembershipWithLL
was very slow due to its usage of String.prototype.localeCompare
(view matrix-org/matrix-react-sdk#6130) setState
calls together and leveraging cached values to avoid a two step render where possible (matrix-org/matrix-react-sdk#6079)The combination of all of these has definitely improve the room switching timing.
What I haven't tackled... (TimelinePanel
, MessagePanel
, ScrollPanel
)
forceUpdate()
, difficult to optimise in their current stateSolutions involving IntersectionObserver
could be explored but this has not been done so far due to the footprint that those changes would have on the most important set of components in the platform
If one has Element Web open for like weeks and is subscribed to 100's of rooms, it can get worse, requiring seconds to switch between rooms, sometimes stalling and thinking some more.
Disabling showing of images in the web browser helps somewhat, but as Element Web is not accessible without images, this is not a good workaround.
One of the best things about @dbkr's original matrix-react-sdk example app (which turned into Vector/Riot) is that it was ludicrously fast at switching rooms.
So I checked out some older versions of the app to see where it all went wrong. All tests were done against the same HS (my local dev synapse) on a modest account with 30 rooms, switching between the same pair of rooms (from a single-user room with lots of history to a 14-person room with lots of history), using the same size of screen, using the same type of build (dev) and trying to keep all other things equal (e.g. Left and RightPanel expanded). Performance was measured as time taken to render the first frame whilst changing rooms (i.e. the big green splodge along the top of the Chrome Dev Tools timeline). Old copies of the app were built after manually pinning all the deps in their package.json (and one also has to manually delete the copy of react in the matrix-react-sdk instance that the app pulls in, otherwise you end up with two copies and it breaks with addComponentToRefs warnings).
Checking out "protovector" as of 9aa9a603: 50ms in total to render the frame (of which 36ms is actually handling the click, and 7ms in total is rendering). It looks like this:
50ms.json.txt
It's important to note that the vertical white stripes in the flamegraph do not show consecutive calls to the same stack, but are a bug in the stack unwinding in v8: https://stackoverflow.com/questions/46008547/how-to-interpret-gaps-in-chrome-flame-charts
Moving on to vector 0.1.0 (with matrix-js-sdk 0.2.0): 68ms in total, of which 46ms is handling the click, and rendering has actually gotten faster to 6.3ms (probably because the very low-density layout means there's less content to render). There's a bug here that hashChange triggered a setState which wastes 14ms (subsequently fixed years ago), which means in practice it's actually more like 54ms in total: things are still fast! At least at this point I hadn't broken everything with horribly clunky flexbox & CSS! It looks like this:
68ms.json.txt
Skipping forwards to current riot-web dev (~0.12.3): 416ms for the first frame (and then another 135ms spread over two more frames) to switch room. Of which 370ms is handling the click, and rendering is 65ms. So, we've got around an order of magnitude slower. It looks like this:
417ms.json.txt
...and trying it again, this time with
?react_perf
turned on (i.e. a URL like https://riot.im/develop/?react_perf/#/room/##testing:sierra): it shows:484ms-react-perf.json.txt
I also compared against riot 0.10.2 prod release, which took 276ms to handle the click (so fairly similar to 0.12.3 when considering it's prod); so good news that Bluebird doesn't seem to have slowed things down much).
I also compared against vector 0.8.4 prod release, which took 173ms to handle the click, which is interesting as it's cosmetically almost identical to what we have today. Might be worth digging further to see what has changed between 0.8.4 and now.
I've dug around a bit in this trace to see obvious things which are slower than they used to be. My list is:
s/GeminiScrollbar/div/g
) but it didn't make much difference, as it seemed to then just make the .scroll methods in ScrollPanel itself take more time.So, TL;DR: I think we should:
For the layout stuff, I suggest we profile with Advanced Layout in chrome dev tools, which should show a pretty 3D video of what's going on, although I haven't got that far yet.