Taking ReSharper out of process – ReSharper performance series
In the previous post of our ReSharper performance series, we looked at Visual Studio and ReSharper complexity and history, and determined that one of the reasons for degraded performance lies in Visual Studio being a 32-bit process. In this post, we will look at what can be done to overcome that limitation.
In this series:
- Introducing the ReSharper performance series
- Taking ReSharper out of process
- Component composition, just-in-time-compilation, the UI thread
- Performance improvements in ReSharper 2018.1 and 2018.1.1
Let’s dive in!
Roslyn and ReSharper
We’ve looked at the 32-bit process limitations, and figured out there is only so much memory that can be consumed. So one might ask: why is JetBrains still building their own language engine with ReSharper? Why not just use Roslyn so that there is only one engine in memory instead of two? And as a bonus, ReSharper development may go quicker?
There are a number of reasons for not doing this, as explained in our ReSharper and Roslyn Q&A. A better question would be the following: is it worth replacing a well-oiled engine just to work around the limited 32-bit working set? And how long would it be before that replacement also runs against the boundaries? Surely there are better ways…
Microservices! (in the form of child processes)
How can one go beyond this hard limitation in available memory? As with everything, the answer is microservices. Visual Studio is gradually transitioning into a process with many child processes, where every one of those child processes can consume the amount of memory it needs.
This architecture has several advantages: each child process has its own thread pool and can be run on different CPU cores by the operating system. Each child process also has its own memory space and its own garbage collector.
We use the same approach in Rider, our cross-platform .NET IDE, where the IDE is just the UI and a host process, and a lot of the heavy lifting happens in the child processes that are spawned, and this works wonders for performance.
Running multiple processes does present some other challenges. How do you keep them in sync? Do all keystrokes in the editor have to be processed? When we type a class name and then remove it again, does it have to exist in both processes? The reactive distributed communication protocol we use in Rider may be the answer to these questions.
JetBrains is investigating making ReSharper a child process of Visual Studio, instead of being part of the main process.
Async loading of the ReSharper VSPackage
Next to making ReSharper run its own process, we can improve loading the bits that have to remain in the Visual Studio process. We’ll still be able to render menu’s, show refactoring dialogs and keep track of what is happening in the editor.
Visual Studio is really just the Visual Studio Shell, which loads a number of VSPackage instances that contain language features and specific tooling to make it an IDE. Pretty much every checkbox in the Visual Studio installer represents such VSPackage, and ReSharper is another VSPackage instance that can be loaded.
Visual Studio performs delay loading when a package is only needed in certain contexts. Newer versions of Visual Studio allow asynchronous loading of a VSPackage as well, moving the work to a background thread.
JetBrains is investigating loading ReSharper as an asynchronous VSPackage.
In this post, we have looked at one of the ways to make ReSharper performance better: taking it out of process. This brings many benefits: both Visual Studio and ReSharper run in their own process, have their own thread pool, and their own memory space. In addition to that, we are investigating async loading of ReSharper in Visual Studio.
None of these solutions will be the silver bullet by themselves, though. There are other areas that can be improved, and we will look at those in our next blog post!
If you are experiencing performance issues, make sure to check the Performance guide for Visual Studio (ReSharper 2017.3+) as well as our KB article Speeding up ReSharper (and Visual Studio). If you have a specific performance issue you can reproduce, we’d appreciate if you could collect a performance snapshot and send it over.
Subscribe to Blog updates
Thanks, we've got you!
Another Look into the Future with Rider’s Predictive Debugger
In the 2023.2 release cycle, we’ve introduced the Predictive Debugger in ReSharper, which gives you predictions about code paths and variables beyond the current execution pointer. We’ve written extensively about its advantages compared to alternative debugging strategies like thorough thinking, log…
Visualize Entity Framework Relationships and Additional Query Analysis in ReSharper 2023.3
A lot of teams are using Entity Framework or EF Core to work with their database. As an Object-Relational Mapper (ORM), it bridges objects in code to a relational database model, so that as a developer you don’t have to worry too much about the actual database. We all know: that’s not entirely tr…
Automatically Analyze ASP.NET Core Performance With Dynamic Program Analysis
Slow web pages may make your users or customers abandon your web application, even before they’ve had a proper look at it. You’ve likely also been frustrated working with a web application that is slow to load. The good news is that the latest versions of ReSharper and JetBrains Rider’s Dynamic P…
OSS Power-Ups: MassTransit – Webinar Recording
The recording of our webinar, OSS Power-Ups: MassTransit, with Chris Patterson, is available. This was the thirteenth episode of our OSS Power-Ups series, where we put a spotlight on open-source .NET projects. Subscribe to our community newsletter to receive notifications about future webinars.…