This diff makes the run log viewer faster.
It turns out there were several problems that had built up in here. We've been mostly implementing the "streaming GraphQL subscription which appends to an array" ourselves, but on each inbound update we update the data and commit it to Apollo's normalized store. We have no interest in a normalized store for log entries and Alex noted earlier today it's almost shockingly slow. We then turn around and pull the data right back out for display, and it seems to re-pluck each requested key-value pair. Oof.
This diff merges the RunSubscriptionProvider and LogFilterProvider into a single LogProvider that opens a websocket, sends the GraphQL request, and then accumulates the logs into our own array which is vended to it's children. The logs are not requested through Apollo at all. It turns out it's faster to retrieve the "initial" / old logs through the socket too by using a cursor of 0. (That way we don't have to insert / retrieve the older logs from Apollo either.)
This diff also avoids throwing away the virtualized grid's cell offset + height cache every time new logs arrive. We were doing this because the search / filters in the view hide items and invalidate the row offsets. Now we generate a key from the filters - as long as the filters remain the same, we know the logs are append-only and it's safe to keep using the cached row offsets. This eliminates one heavy double-render caused by the height calculations.
Because we know we're receiving the logs in order, I also made the LogProvider attach a clientsideKey to each message. Having a unique key for each item in the array allows us to keep the cell height cache even when you're filtering the array and the items change array indexes. (So we invalidate the row offsets as you filter, but not the row sizes).
It turns out we were also spending a good deal of time just rendering the actual cells. Because each cell is rendered and then re-rendered with it's fixed size, memoizing the cells /inside/ of the main row container is effective but memoizing them at the top level doesn't work because the style prop is changing.
Anyway. Here we go - this is just a log_spew run with the Debug message filter toggled on: