-
Notifications
You must be signed in to change notification settings - Fork 236
WIP: Experimental message queue #832
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
Conversation
Here is some sample log output: JsonRpcQueue.txt Oh yeah, the PsesLogAnalyzer changes weren't supposed to be part of this commit. I'll continue to work on the module support for analyzing the queue. |
Hmm, need to think about this one a bit:
|
I haven't read through the PR at all but I wanted to drop this as a data point as to another reason for this PR being critical! For the codelens request for references we look at the file system. If we could use a Globber like Glob.cs that does lazy evaluation and cancelation... We can use a cancelationtoken when receiving a cancelRequest or another codelens request. |
Full disclosure here … this still needs work. I'm on the edge (actually over a little) WRT my async/threading chops. I'm using this AsyncQueue but it might not be the best data structure. Also, I'm seeing large delays (6-8 seconds) sometimes with Seems like something is blocking:
One source of extra time is that event messages written from PSES to the client, get posted to the dequeue/dispatch thread to be written to the channel. The intent is that only thread writes to the channel which makes sense. |
668ec1c
to
e31f694
Compare
Here's another message that takes a long time to dispatch/process (which has to be done before we dequeue/dispatch the next message):
Yikes, why so long to get all the document symbols? |
@rkeithhill I take it that delay happens in the extension today for some folks - not introduced by your change. |
I'm pretty sure that is the case. This is the time span between writing the log message inidicating we've pulled the JSON RPC request off the queue and have dispatched it and writing the log message indicating we have written the response for that JSON RPC request. |
73485ff
to
837c6dc
Compare
Rebased from the new master - that was a bit ugly but got through it. |
837c6dc
to
d76ed9b
Compare
Rebased from master. |
Sorry @rkeithhill, would you like us to take a look at this? |
Yes but not so much from a "is this ready to check in" perspective. I'm looking more for a "is this a sane approach" kind of feedback. I have a couple of concerns. One is about using the AsyncQueue that David created quite a while back. I think it is the right approach but not 100%. I'm more comfortable using async/await in GUI's - less so in servers. I also don't like that I'm currently waiting until dispatch of a queued FWIW I don't think this will represent a major leap in perf. We're still processing client messages sequentially but it should reduce the message processing load some by eliminating cancelled messages before we ever start processing them. Cancelling messages currently being processed is a whole other can worms I'm not trying to tackle here. :-) I also need to add some functionality to my PsesLogAnalyzer module to provide a suite of message queue analysis commands. That should help us visualize how the message queue is performing - queue wait times, depth, etc. |
Ok so here are my thoughts:
|
d76ed9b
to
20d1411
Compare
20d1411
to
d5465e9
Compare
Method rename refactoring and work on log messages.
35b0228
to
36eeb2a
Compare
I don't think we need this anymore because of Omnisharp! :D |
Agreed. |
This is still very experimental but the idea is that we spin two threads instead of one for the ProtocolEndpoint. The current impl uses one to read a JSON RPC message, process it and then read the next message. The consequence of this sequential approach is that by the time we process a
$/cancelRequest
we've already processed the target message.This PR adds changes the original thread to just listen and queue JSON RPC messages to an AsyncQueue (I think @daviwil created this type). Cancel message are currently added to a
pending cancel requests
ConcurrentDictionary.Another thread is created to service the Aysnc message queue. Actually, I'm experiementing with two AsyncQueue's one for "low priority" messages like
codeLens
,codeAction
anddocumentSymbol
. Not sure if we really need this - was trying to make sure thattextDocument/completion
requests got serviced more quickly. Not entirely sure I've achieved that just yet. So the dequeue/dispatch thread dequeues a message and first checks to see if there is a pending cancellation request. If there is, we send the appropriate error response for that message indicating it was cancelled. If the message does not have a cancel request pending, then we process the message normally.Here are some things we might want to change.
If the AsyncQueue had a method to remove a message (anywhere in the queue), we could process the $/cancelRequest when it's received (rather than pending it and processing when the target message is dequeued). Seems like this would be friendlier to the LSP client.Actually, we probably want to use the single dequeue/dispatch thread to write all messages to the channel. We still might want to drop the low priority queue - to simplify the implemenation and preserve message order.Also, do we have messages we process on a bg thread? Seems like the code analysis support may happen in the background. If so, we probably want to send the "error - request cancelled" response when message processing completes and is about to send its response, in the scenario where a cancel request comes in after the message is dispatched but before it has returned a response.