Skip to content
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

Riot sometimes slowly leaks heap (was 'reliably hangs after 24h') #2951

Closed
ara4n opened this issue Jan 14, 2017 · 16 comments
Closed

Riot sometimes slowly leaks heap (was 'reliably hangs after 24h') #2951

ara4n opened this issue Jan 14, 2017 · 16 comments
Assignees
Labels
A-Performance P2 S-Major Severely degrades major functionality or product features, with no satisfactory workaround T-Defect

Comments

@ara4n
Copy link
Member

ara4n commented Jan 14, 2017

Pretty much every time i unsleep my laptop in the morning, riot-web on electron has wedged, chewing 100% CPU and being entirely unresponsive - not redrawing the window, and not letting me switch to developer tools (even if i left them open). Menus work and there's no beachball of doom however.

This time I'd left dev tools open: the last logs from the app were at 16:05 (laptop spontaneously waking up, probably) and then:

MatrixChat.js:630 MatrixClient sync state => SYNCING
2017-01-14 20:00:03.389 index.js:390 got keys for @lb:ldbco.de: Object {BXGWFQILLR: Object, VPOTDJPZDN: Object, XuU7luMVtZs6@517: Object, &FInPK^.T#+iO~+7: Object, VZYLRCWTNS: Object…}
2017-01-14 20:00:08.103 index.js:390 got keys for @lb:ldbco.de: Object {BXGWFQILLR: Object, VPOTDJPZDN: Object, XuU7luMVtZs6@517: Object, &FInPK^.T#+iO~+7: Object, VZYLRCWTNS: Object…}
2017-01-14 20:00:19.546 olm.js:256 Decrypted Olm message from omArxuuEPFOc0B/6wKePdGxyYyI3ZDRSnHgOIBp4ACw with session JRAKMjop8meUeeh0JAwZSd0ChFxJtKtdCTEZ+yq5oXE
2017-01-14 20:00:19.549 olm.js:256 Decrypted Olm message from P6ggBCKY5qrdKOLYwyaAdJlaQbPqgmHpCXjXaX0htCE with session +doDUo7oui1X3GgFgzfSfvUtC3ncg/Bh4l41W9dQ8nw
2017-01-14 20:00:19.553 olm.js:256 Decrypted Olm message from bcvm7dC0xk0qUx7TSc9da6QrmxbSQxdPZf8L35yy/0k with session 9EZVZypxUPlDeyTw89CYbH911EOcYfpESH4kqrNHopE
2017-01-14 20:00:21.687 olm.js:311 created new inbound Olm session ID 2G7pJobigUbiNIVoQlD52MxbIcYq7YAv95AFiTVfffg with WYYBqYwp6PAIG9V1PsxfvTNfHAZEIOkLs8fkIB6lT0k
2017-01-14 20:00:21.688 megolm.js:548 Adding key from  e.e…s.MatrixEvent {event: Object, sender: null, target: null, status: null, forwardLooking: true…}
2017-01-14 20:00:21.706 megolm.js:548 Adding key from  e.e…s.MatrixEvent {event: Object, sender: null, target: null, status: null, forwardLooking: true…}
2017-01-14 20:00:21.721 megolm.js:548 Adding key from  e.e…s.MatrixEvent {event: Object, sender: null, target: null, status: null, forwardLooking: true…}
2017-01-14 20:00:21.741 megolm.js:548 Adding key from  e.e…s.MatrixEvent {event: Object, sender: null, target: null, status: null, forwardLooking: true…}
2017-01-14 20:00:21.758 index.js:1117 m.new_device event from @ylecollen:matrix.org:XRNOEFNJTU for rooms !UCnwUWwIKhcpaPTHtR:sw1v.org,!pLAcOvLjsxbcgitday:matrix.org
2017-01-14 20:00:21.763 index.js:356 Starting key download for @ylecollen:matrix.org

...and then wedge solid. Inspector itself is responsive, however, and let me pause the VM in the debugger (but not query the DOM). The debugger gave a stacktrace of:

i (traverseAllChildren.js:90)
o (traverseAllChildren.js:172)
i (flattenChildren.js:70)
_reconcilerUpdateChildren (ReactMultiChild.js:212)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:213)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:936)
updateComponent (ReactDOMComponent.js:754)
receiveComponent (ReactDOMComponent.js:716)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
performUpdateIfNecessary (ReactCompositeComponent.js:561)
performUpdateIfNecessary (ReactReconciler.js:157)
s (ReactUpdates.js:150)
perform (Transaction.js:140)
perform (Transaction.js:140)
perform (ReactUpdates.js:89)
w (ReactUpdates.js:172)
closeAll (Transaction.js:206)
perform (Transaction.js:153)
batchedUpdates (ReactDefaultBat…Strategy.js:62)
l (ReactUpdates.js:200)
r (ReactUpdateQueue.js:24)
enqueueSetState (ReactUpdateQueue.js:209)
r.setState (ReactComponent.js:63)
refreshRoomList (RoomList.js:203)
e.exports.d.createClass._delayedRefreshRoomList (RoomList.js:189)
r (ratelimitedfunc.js:37)
onRoomTimeline (RoomList.js:155)
n.emit (events.js:96)
(anonymous function) (sync.js:1132)
n.emit (events.js:89)
(anonymous function) (room.js:1250)
n.emit (events.js:89)
r.addEventToTimeline (event-timeline-set.js:482)
r.addLiveEvent (event-timeline-set.js:457)
i._addLiveEvent (room.js:563)
i.addLiveEvents (room.js:841)
o._processRoomEvents (sync.js:1066)
(anonymous function) (sync.js:789)
o._processSyncResponse (sync.js:709)
(anonymous function) (sync.js:522)
r (q.js:834)
s.promiseDispatch.c (q.js:863)
r.promiseDispatch (q.js:796)
(anonymous function) (q.js:604)
r (q.js:137)
e (q.js:125)
runCallback (timers.js:574)
tryOnImmediate (timers.js:554)
processImmediate (timers.js:533)

...i.e. tightlooping drawing the UI whilst adding events to timeline; this feels very similar to the deadlocks seen in the past in #2020.

The event it's trying to add to the room is:

screen shot 2017-01-14 at 20 11 10

(can't dump it from the debugger console itself for some reason).

Trying to profile then crashed the debugger entirely.

@ara4n
Copy link
Member Author

ara4n commented Jan 24, 2017

I switched back from Electron for my main account in order to work around #2737, and was vaguely interested that the behaviour there is to 'Aw snap' when trying to catch up overnight. I've never seen an 'Aw snap' in Electron, so I suspect this another way this problem manifests.

@ara4n
Copy link
Member Author

ara4n commented Jan 27, 2017

Saw this again, now on normal vector-web. On unsleeping Chrome had become spectacularly unresponsive, as if swapping - taking ~5s to respond on the JS console. Trying to do a heap dump caused it to 'Aw snap' at 17%. The stacktrace, fwiw, was:

mapSingleChildIntoContext (ReactChildren.js:100)
traverseAllChildrenImpl (traverseAllChildren.js:77)
traverseAllChildrenImpl (traverseAllChildren.js:93)
traverseAllChildrenImpl (traverseAllChildren.js:93)
traverseAllChildren (traverseAllChildren.js:172)
mapIntoWithKeyPrefixInternal (ReactChildren.js:127)
toArray (ReactChildren.js:178)
TruncatedList_render (TruncatedList.js:45)
(anonymous) (ReactCompositeComponent.js:796)
measureLifeCyclePerf (ReactCompositeComponent.js:75)
_renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795)
_renderValidatedComponent (ReactCompositeComponent.js:822)
_updateRenderedComponent (ReactCompositeComponent.js:746)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:208)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:930)
updateComponent (ReactDOMComponent.js:748)
receiveComponent (ReactDOMComponent.js:710)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:208)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:930)
updateComponent (ReactDOMComponent.js:748)
receiveComponent (ReactDOMComponent.js:710)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:208)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:930)
updateComponent (ReactDOMComponent.js:748)
receiveComponent (ReactDOMComponent.js:710)
receiveComponent (ReactReconciler.js:125)
updateChildren (ReactChildReconciler.js:109)
_reconcilerUpdateChildren (ReactMultiChild.js:208)
_updateChildren (ReactMultiChild.js:312)
updateChildren (ReactMultiChild.js:299)
_updateDOMChildren (ReactDOMComponent.js:930)
updateComponent (ReactDOMComponent.js:748)
receiveComponent (ReactDOMComponent.js:710)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
receiveComponent (ReactCompositeComponent.js:547)
receiveComponent (ReactReconciler.js:125)
_updateRenderedComponent (ReactCompositeComponent.js:754)
_performComponentUpdate (ReactCompositeComponent.js:724)
updateComponent (ReactCompositeComponent.js:645)
performUpdateIfNecessary (ReactCompositeComponent.js:561)
performUpdateIfNecessary (ReactReconciler.js:157)
runBatchedUpdates (ReactUpdates.js:150)
perform (Transaction.js:140)
perform (Transaction.js:140)
perform (ReactUpdates.js:89)
flushBatchedUpdates (ReactUpdates.js:172)
closeAll (Transaction.js:206)
perform (Transaction.js:153)
batchedUpdates (ReactDefaultBat…Strategy.js:62)
enqueueUpdate (ReactUpdates.js:200)
enqueueUpdate (ReactUpdateQueue.js:24)
enqueueSetState (ReactUpdateQueue.js:209)
ReactComponent.setState (ReactComponent.js:63)
refreshRoomList (RoomList.js:203)
module.exports.React.createClass._delayedRefreshRoomList (RoomList.js:189)
wrapper (ratelimitedfunc.js:37)
onRoomTimeline (RoomList.js:155)
EventEmitter.emit (events.js:99)
(anonymous) (sync.js:1148)
EventEmitter.emit (events.js:88)
(anonymous) (room.js:1265)
EventEmitter.emit (events.js:88)
EventTimelineSet.addEventToTimeline (event-timeline-set.js:486)
EventTimelineSet.addLiveEvent (event-timeline-set.js:461)
Room._addLiveEvent (room.js:584)
Room.addLiveEvents (room.js:861)
SyncApi._processRoomEvents (sync.js:1082)
(anonymous) (sync.js:791)
SyncApi._processSyncResponse (sync.js:712)
(anonymous) (sync.js:525)
_fulfilled (q.js:834)
self.promiseDispatch.done (q.js:863)
Promise.promise.promiseDispatch (q.js:796)
(anonymous) (q.js:604)
runSingle (q.js:137)
flush (q.js:125)
onNextTick (main.js:64)
Item.run (browser.js:133)
drainQueue (browser.js:103)
setTimeout (async)
runTimeout ()
process.nextTick ()
exports.setImmediate ()
nextTick ()
(anonymous) ()
(anonymous) ()
become ()
deferred.resolve ()
(anonymous) ()
(anonymous) ()
on_end ()
on_state_change ()
XMLHttpRequest.send (async)
run_xhr ()
request ()
_request ()
requestOtherUrl ()
request ()
authedRequest ()
SyncApi._sync ()
(anonymous) ()
_fulfilled ()
self.promiseDispatch.done ()
Promise.promise.promiseDispatch ()
(anonymous) ()
runSingle ()
flush ()
onNextTick ()
Item.run ()
drainQueue ()
setTimeout (async)
runTimeout ()
process.nextTick ()
exports.setImmediate ()
nextTick ()
(anonymous) ()
(anonymous) ()
become ()
deferred.resolve ()
(anonymous) ()
(anonymous) ()
on_end ()
on_state_change ()
XMLHttpRequest.send (async)
run_xhr ()
request ()
_request ()
requestOtherUrl ()
request ()
authedRequest ()
SyncApi._sync ()
(anonymous) ()
_fulfilled ()
self.promiseDispatch.done ()
Promise.promise.promiseDispatch ()
(anonymous) ()
runSingle ()
flush ()
onNextTick ()
Item.run ()
drainQueue ()

@ara4n ara4n changed the title riot/macos reliably hangs after about 24h of use Riot reliably hangs after about 24h of use (both electron & web) Jan 27, 2017
@ara4n
Copy link
Member Author

ara4n commented Jan 27, 2017

before it crashed i got some more datapoints: it was trying to insert a timeline event for linux masterrace; the room had 11 timelines with 20 to 700 events each. the room list looked normal. my guess is that the heap was huge (proc was 1.7GB rsz) and chrome had hit some nasty v8 failure mode or deliberate throttling.

@kegsay: is there any chance of pruning old events from ram whilst you are doing the indexeddb stuff?

@kegsay
Copy link
Contributor

kegsay commented Jan 27, 2017

@ara4n : I can look at it afterwards if you would like, but this isn't a "kill 2 birds with one stone" scenario: the indexeddb stuff is far removed from pruning events from the timeline.

@ara4n
Copy link
Member Author

ara4n commented Feb 9, 2017

this is really looking like the heap is exploding - i finally caught it almost-dead-but-not-quite and got a heapdump out of it (took about 20 mins to generate):

-rw-r--r-- 1 matthew staff 1.5G 9 Feb 10:40 Heap-20170209T103848.heapsnapshot

and also 93% of time in GC:

screen shot 2017-02-09 at 09 48 40

Prior to this, the stack traces were showing 80% of time going into 'program', with the remainder going into browser-request callbacks, whilst doing E2E device syncing voodoo - possibly related to: #3127 and #3158.

It seems fairly clear the problem here is the size of the heap though, and the fact that v8 becomes unstable somehow and spends its life GCing.

@ara4n
Copy link
Member Author

ara4n commented Feb 9, 2017

next step is for me to dig into that heap dump.

@kegsay
Copy link
Contributor

kegsay commented Feb 9, 2017

It seems fairly clear the problem here is the size of the heap though, and the fact that v8 becomes unstable somehow and spends its life GCing.

I think this is correct, but not obviously so. I regularly have large heaps (>4GB) on the IRC bridge which is using V8 under the hood, so the raw size of the heap is not the problem.

I have seen many occasions where the V8 GC goes berserk and basically consumes all CPU preventing any JS from running, but this only happens when it approaches the limit of its heap size (which by default is ~1.5GB).

I suspect you're hitting this failure mode (which is the exact same failure mode we hit on Freenode when we reach our limit). I theorise that this is the GC desperately trying not to OOM and is aggressively trying to clear objects, so much so that it makes the program unusable.

Either way, the solution is the same: don't have such a big heap.

@ara4n
Copy link
Member Author

ara4n commented Feb 9, 2017

rather splendidly the heapdump is too big to load into chrome to analyse :|

@ara4n ara4n added P1 A-Performance T-Defect S-Major Severely degrades major functionality or product features, with no satisfactory workaround labels Feb 10, 2017
@ara4n
Copy link
Member Author

ara4n commented Feb 10, 2017

so the heap dump has 500K events in it. from random sampling, they seem to be both presence events associated with users, as well as timeline events. it's very hard to tell if there's actually a leak here (beyond not pruning history) or if this just how busy my account really is. i can't find a programmatic way to analyse the heap like you can with objgraph in python, other than the useless https://www.npmjs.com/package/heapsnapshot-parser which barfs on a 1.5G heapdump. i'm kinda inclined to suggest pruning old history and see if it magically fixes itself.

@pik
Copy link

pik commented Mar 8, 2017

Is there a reason to keep presence events rather than just to compute current state from it?

@lampholder lampholder modified the milestones: RW002 - candidates, RW003 - candidates Apr 3, 2017
@lampholder lampholder modified the milestones: RW004 - candidates, RW003 - candidates Apr 24, 2017
@ara4n
Copy link
Member Author

ara4n commented Apr 24, 2017

Something seems to have happened to have improved things a bunch. I just measured my Riot.app (0.9.8) after precisely 24h of use, and it "only" had 517MB of heap in use:

screen shot 2017-04-25 at 00 26 28

...and so I then restarted the app and did another capture, which yielded 591MB of heap(!):

screen shot 2017-04-25 at 00 30 57

So I think that the problem has somehow gone away during kegan's indexeddb work, but I'm not entirely sure how or where.

@kegsay: did you do something deliberate to fix the leak? @richvdh, did you spot anything when investigating earlier?

I'm deprioritising in the meanwhile...

@ara4n
Copy link
Member Author

ara4n commented Apr 24, 2017

given our event count on restart dropped from 278,672 to 274,553 (so 6MB retained size) it does look like there may still be a slow leak, but at 6MB per day that's not the end of the world. I'll monitor it.

@ara4n ara4n added P2 and removed P1 labels Apr 24, 2017
@ara4n ara4n changed the title Riot reliably hangs after about 24h of use (both electron & web) Riot sometimes slowly leaks heap (was 'reliably crashes after 24h') Apr 24, 2017
@ara4n ara4n changed the title Riot sometimes slowly leaks heap (was 'reliably crashes after 24h') Riot sometimes slowly leaks heap (was 'reliably hangs after 24h') Apr 24, 2017
@ara4n ara4n removed this from the RW004 - candidates milestone Apr 24, 2017
@richvdh
Copy link
Member

richvdh commented Apr 25, 2017

@richvdh, did you spot anything when investigating earlier?

Yes, matrix-org/matrix-js-sdk#395, which drops old timelines when we get a limited sync (typically after suspending).

@kegsay
Copy link
Contributor

kegsay commented May 2, 2017

@kegsay: did you do something deliberate to fix the leak?

I did stuff a while back like matrix-org/matrix-js-sdk#395 which will help for any long sleep periods which I guess you were hitting if:

after precisely 24h of use

is anything to go by.

@ara4n ara4n mentioned this issue May 15, 2017
@lampholder
Copy link
Member

My Riot is starting to hang again, on my dev machine, after a day or two? I'll try and keep a closer eye on it...

I restarted it at 9.45 this morning.

@richvdh
Copy link
Member

richvdh commented Oct 31, 2017

matrix-org/matrix-js-sdk#395 fixed the worst of this, though we still have other problems as per #3307.

@richvdh richvdh closed this as completed Oct 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Performance P2 S-Major Severely degrades major functionality or product features, with no satisfactory workaround T-Defect
Projects
None yet
Development

No branches or pull requests

6 participants