allennlp-demo
allennlp-demo copied to clipboard
Some HeatMaps perform sluggishly
The current HeatMap structure is heavy with lots of nested DOM nodes and applied styles. Thus pages with very large tables and/or pages with many heatmap tables are starting to perform sluggishly.
Things that may improve this:
-
Drawer System - Replace nested Accordion UX with Drawer system (#89) is likely to help, as only the relevant tables need to be rendered at a given time. With current Collapsible accordion, all tables on a page are being rendered simultaneously.
-
Optimizing HTML and CSS - Some of this complexity can't be avoided, but It may be possible to reduce some of the markup by switching from a
<table>
structure to using<div>
s. It may also be possible to make the CSS a bit faster by simplifying selectors and consolidating some of the nested structures into fewer elements. -
Rearchitect Crosshairs - Look at alternative architectures for how crosshairs and active cells are being rendered
-
Rearchitect Tooltip - See https://github.com/allenai/allennlp-demo/issues/106#issuecomment-428722407
See related conversion on the Crosshairs/Tooltip PR that was merged into master on 10/10/2018.
Just a note: see this comment for a bit more detail. In my experiments, it wasn't the size of the table that caused sluggishness, it was the number of rendered components on the page. Particularly, the slowness was due to the browser spending a whole lot of time in "update layer tree", figuring out the right way to layout all of the nested components after a javascript update. The way we're showing the semantic parsing internals means that we're currently rendering a ton of stuff up front, and hiding it. This is the problem. We need to just render the heatmaps that we need on the fly, instead of keep them around.
Thanks Matt. When I was testing this last night, I was noticing that the single MC tables with many rows performed worse than the tables on the WikiTables page even though that page had more tables.
Whether it's more an issue of how many tables per page or how many rows per table, my assumption was that the underlying issue stemmed from too much markup on the page at a given time.
Or do you think this is more about React working overtime to figure out a complex virtual DOM and less about what actually gets rendered in the browser?
@matt-gardner you weren't kidding. As-is, the HeatMaps on http://staging.allennlp.org/atis-parser/NDAwMjUz are unusable. :( Would be interesting to test how the page performs if you disable the Predicted Actions section and render with just the Entity linking scores.
And by the same token, try the reverse: disable the linking scores and see how the actions tables perform.
This may help us determine if the culprit has more to do with number of heatmaps or number of rows. If the latter then Drawer won't help as much and we'll have to revisit how this thing is built.
Another note: these heatmaps are performing WAY better on staging than on my local machine. My guess is that Docker was hogging almost all of my machine resources, not leaving very much left for Chrome.
Here are some performance screenshots:
First, BiDAF, with a large table:
This was indeed quite a bit slower for me when I made the question very long. This is mostly due to re-rendering the whole table on each move, as you can see when you click on a mouse event:
If you dig into the particular functions being called, the time is being spent inside HeatMap.render()
. This isn't too surprising - the table is large. It might be possible to optimize this a bit, but I'm not really sure how.
Second, the ATIS parser, on a relatively small table, but where there are a lot of actions:

Here you notice that in addition to the javascript slowness (the yellow/orange blocks in the "main" piece), you also have the purple layout slowness, and the top place where "self time" is spent is on "Update Layer Tree".
If we look at what's taking up the javascript time, when it's being slow, you see that it's on "addEventListener" and such, which turns out is in the ReactTooltip
code - I think it's adding all of the listeners to a big list, for all of the tables, and so when there are a lot of them, it takes a significant amount of javascript time just to mutate that list at every mouse event (you can see that I clicked on one of the yellow/orange boxes on the far right):
If you remove the tooltip on ATIS, you get rid of most of the javascript slowness, but you still get a very slow UI, and you can see that it's almost entirely due to layout issues:

So, there are two issues here. The first is that large tables take a long time to re-render, and optimizing the html/css/react code could help here. But I'd also guess that for the majority of cases, this isn't a huge problem.
The second, and in my opinion more pressing, issue, is that when there is a lot of stuff rendered on the page, things get slow, both in the ReactTooltip
component, and just in recomputing the page layout. Only rendering heat maps and other things on-the-fly in a drawer should solve this issue completely.
That’s super helpful. Thanks for doing that analysis!
You’ve convinced me that rendering just-in-time tables will move the needle the most, but if we are looking for every opportunity to optimize, I wonder if an alternative tooltip solution may also help. I started out with a homegrown solution, but it was broken in that it wasn’t smart enough to detect container and window boundaries, so it was getting cut off at the edges. The library I ended up using solved that immediate problem, but may prove to be too clunky when used at scale...
I wondered the same thing at first, which is why I dug into stuff like I did. After looking at this, I'm quite sure that a different tooltip solution won't really solve anything. It's not a significant source of slowness if there aren't a whole lot of things rendered on the page, and if you remove it, things are still slow if you have a lot of things on the page. So I wouldn't spend time trying to solve the tooltip issue.