Part 1 of this series talked about the startup problems we face. In Part 2, I want to talk about the editor.
Many people have reported that editing with the new editor is slower. I’ve experienced the same thing myself so I certainly do not want to accuse people of hallucinating but I thought it might be interesting to understand why that might happen, especially since this new editor is supposed to be better than the old.
Why is this editor better and how is it better?
I’m glad you asked
It’s actually better in pretty much every editing way. The data structures associated with this new editor do not require complex locking algorithms for access, it delivers logical “micro-snapshots” of the editor buffer which do not change – it is a copy of the buffer at an instant in time. This is a fantastic situation if you are, for instance, a background compiler. Previously to get consistent snapshots the entire buffer had to be copied, potentially on every keystroke!
And if that’s not enough, there’s a lot more. Another big tax on the editor is region management. Regions are used to track everything from bookmarks to breakpoints – and more. Those squiggles you see, those are all regions and there can be thousands of them. That is far beyond what the original editor design intended and those algorithms were starting to degenerate to quadratic behavior. You can see that yourself by noting that simply scrolling around at the end of large files in the old editor tended to get slower.
Those are just two areas, but generally where the old editor had quadratic performance we were able to improve things to linear and in some places we were able to do even less work by being more careful about processing only visible segments of the text buffer. All goodness.
So why is the thing slower if it’s so much better?
Well let me elaborate a little more, but before I answer that directly, first let me tell you what things are almost certainly not the problem.
Not the problem #1: WPF
With the exception of some cases where we found that remoting WPF primitives over terminal server connections was slow, generally the WPF system is more than capable of keeping up with the editor. If you are seeing sluggish typing WPF is almost certainly not to blame.
Not the problem #2: Editor Primitive Operations.
The basic insert primitives are blazing fast, as low as a few microseconds even in very large files. If you’re seeing a problem, the chances that the text buffer is letting you down are slim to none.
Ok, so, if it’s not those things, what is it? There’s two good bets.
The new editor is managed, and it has its own brand new managed interface. You can call it directly. However, there is lots of existing code that knows how to talk to the OLD editor and the old editor had a COM interface with its own particular API. We didn’t want to port all of the editor related code to the new editor’s managed interfaces – for several reasons but perhaps the most important is that there’s just so much of it. So we created a compatibility layer – shims – that allow old callers to use the new editor. That’s also important for our partners out there. That’s all fine and well but of course that means you’re going to be forced to use COM-interop where there was none before and of course those shims have to emulate the old editors behavior even when that wasn’t exactly the fastest choice in the west.
So sometimes improving editor responsiveness has meant converting more code to the direct interface and thereby avoiding the shims. The trick here is to make sure you convert the code that needs converting rather than going crazy trying to convert all of it in one go.
OK but who are all these users? What are we talking about here?
That brings us to the second point.
Another reason why the editor can get bogged down is that various clients can register for notifications of interesting events. This is actually very popular (understatement) and important things like the language’s intellisense services want to be notified of various things going on in the buffer. Now it turns out that the actual editing primitives are so fast that the bulk of the cost of doing edits is actually in these various event processors. Sometimes because they are using shims, sometimes just because they are being over-aggressive in subscribing to things. Sometimes because they have their own personal problems that are only incidentally related to editing.
One way that you can see the difference in the root cause of editing yourself is to try your editing operations in a file named ‘foo.txt’ rather than ‘foo.cs’ or ‘foo.vb’ or whatever the case may be. This will disable many of the event listeners and give you a truer feel for what the editor itself is doing. Even that isn’t perfect because of course there are still listeners for bookmarks, and other kinds of things that are applicable to even plain text files.
What are we doing about it?
Well I think I’ve already alluded to it. Make better use of the underlying editor primitives. Move more things off the shims where the cost is high. Reduce the cost and number of listeners generally. And of course make sure that our text and region management primitives stay nice and fast.
What can you do?
If you see the editor behaving dumbly, enter bugs. They really help!