csharp-language-server-protocol
csharp-language-server-protocol copied to clipboard
Startup performance issues
The startup of the language server takes on windows >1 sec and on a linux dege device >7 seconds.
We identified the responsible code:
var Input = Console.OpenStandardInput();
var Output = Console.OpenStandardOutput();
//...
var OmniLanguageServer = await OmniSharp.Extensions.LanguageServer.Server.LanguageServer.From(
options =>
options
.WithInput(Input)
.WithOutput(Output)
.ConfigureLogging(x => x
.AddLanguageServer()
.SetMinimumLevel(enableDebug ? LogLevel.Trace : LogLevel.Information))
.OnInitialize((server, request) =>
{
initializeParams = request;
return Task.CompletedTask;
})
).ConfigureAwait(true);
We are currently using version 0.15.0.
Are there any performance improvements in the latest version? Because when we tried to update to the latest version (0.19.0 currently) our software wouldn't compile anymore and then we wouldn't want to spend the effort if no improvements were done.
It's hard to say, depends what code is actually causing the slow down.
User code?
Library Code?
0.15.0 is fairly old, and there have been performance enhancements in that time. 0.19.0 didn't have any specific focus of performance, more specifically on spec correctness.
Do you have any profiles or benchmarks you can share? It's really hard to nail down a performance issue because that code does a whole lot. It builds the DI container, constructs all the provided handlers, and starts the initialize negotiation. I can say I have not seen anything specific in terms of startup performance but without more detail I can't say for sure that there isn't.
Some things have been improved, our parsing code has moved to pipelines and allocates a little less than before, we're still using Newtonsoft.Json so the allocations are not gone by any means, but it's a little better. The DI container internally is using DryIoc now, but that probably doesn't have any meaningful impact one way or another.
LinuxStartup.txt WindowsStartup.txt
Here are some traces that may help you in finding the issue.
As you can see the time is lost here (example from linux file)
[Info - 9:37:27 ] Converting params for Notification initialized to OmniSharp.Extensions.LanguageServer.Protocol.Models.InitializedParams
[Info - 9:37:33 ] Finished: Routing Notification initialized in 5576ms
If we would want to update to the latest version we have compile issues. Are there any release notes we can find to see what has changed and how we have to update our code.
We tried to run the unchanged SampleServer with the version 0.19.0 on the same Linux machine, and got the same performance effect as our own language server. The client is vscode-server. This proved that this performance issue is probably related to the OmniSharp. The following output was generated from the SampleServer:
- 2021-03-30 09:22:11.010 +00:00 [INF] This only goes file...
- 2021-03-30 09:22:18.548 +00:00 [DBG] Finding descriptors for initialize
- 2021-03-30 09:22:20.248 +00:00 [DBG] Queueing "Serial":initialize:0 request for processing
- 2021-03-30 09:22:20.445 +00:00 [DBG] Starting: Processing request initialize 0
- 2021-03-30 09:22:20.537 +00:00 [DBG] Starting: Routing Request (0) initialize
- 2021-03-30 09:22:20.641 +00:00 [VRB] Converting params for Request (0) initialize to OmniSharp.Extensions.LanguageServer.Protocol.Models.InternalInitializeParams
- 2021-03-30 09:22:20.647 +00:00 [VRB] Converting params for Notification initialize to OmniSharp.Extensions.LanguageServer.Protocol.Models.InternalInitializeParams
- 2021-03-30 09:22:23.443 +00:00 [INF] OnInitialize() called
The last message was generated from the OnInitialize() callback in the user code. Between t1 and t2 we measured 7s, t2 to t3 2s, and between t7 and t8 3s. It would be good to know what happened between t1->t2, t2->t3 and t7->t8 and why this communication was so slow on Linux.
On Windows, when running SampleServer together with VSCode, the output is the following:
- 2021-03-30 13:52:11.425 +02:00 [INF] This only goes file...
- 2021-03-30 13:52:12.194 +02:00 [DBG] Finding descriptors for initialize
- 2021-03-30 13:52:12.428 +02:00 [DBG] Queueing "Serial":initialize:0 request for processing
- 2021-03-30 13:52:12.446 +02:00 [DBG] Starting: Processing request initialize 0
- 2021-03-30 13:52:12.451 +02:00 [DBG] Starting: Routing Request (0) initialize
- 2021-03-30 13:52:12.458 +02:00 [VRB] Converting params for Request (0) initialize to OmniSharp.Extensions.LanguageServer.Protocol.Models.InternalInitializeParams
- 2021-03-30 13:52:12.460 +02:00 [VRB] Converting params for Notification initialize to OmniSharp.Extensions.LanguageServer.Protocol.Models.InternalInitializeParams
- 2021-03-30 13:52:12.725 +02:00 [INF] OnInitialize() called
Windows and Linux seem to have the same issue at the same places, but on Windows the duration is not so significant.
This is something I'll see if I can take a look at as to why it's happening.