(Also adds an <Import />, not shown here)
I have heard the phrase “premature optimization is the root of all evil” many times but have never had a chance to consciously put it to the test before. Meta# has a few critical execution paths where performance is a very big concern and has a large impact on how performant the overall process of parsing goes.
I intentionally ignored all performance concerns up till this point however, choosing to trust in the wisdom that says to avoid premature optimization. I finally got to a point where most of the main features I wanted were in place and I have some very good test coverage (turns out I had 91% test coverage the first time I ran the code coverage tool). So I decided to embark upon a journey of performance optimization.
Tests: 662, Failures: 0, Skipped: 1, Time: 32.402 seconds
Tests: 665, Failures: 0, Skipped: 0, Time: 16.977 seconds
I’d say that it was a huge success! The three new tests are actually parsing all of the .g files in meta# again and tracking their performance. Which means that the slowest tests are now run twice and the whole run is taking about half time time it was before.
I can tell you when I first went to look into where to do optimizations I almost panicked. I thought my code was perfect and that the performance flaw was in the design itself, I had a moment of crisis. But there were tons of low hanging fruit ready for optimization.
So I’m officially a believer in avoiding premature optimization at this point. I would include that I relied heavily on an excellent unit test base to prove that my changes still worked and that is a crucial piece to being able to make these types of systemic changes.
Also, I used the excellent TestDriven.NET performance tools to do give me my data. I highly recommend it. You just right click a test and select Run Test -> Performance. It gives you a very detailed report and the ability to find out your slowest calls very quickly. Optimize and try again! A very clean cycle.
Last time I tried this I had to use the old Managed Package Framework (MPF) APIs in vs2008 and it was so incredibly painful that I gave up and I have been scared to try again ever since. Well I tried again for vs2010 finally and managed to get it working in a single night! The new MEF based APIs are a real breeze comparatively speaking.
After an initial stumbling around period digging through tons of seemingly useless documentation I finally found an example of a language extension called Ook! And it was exactly what I needed. It also turns out that the API for doing highlighting in VS is setup exactly perfectly for the way I am providing highlighting metadata in MetaSharp. What a happy coincidence! This isn’t committed yet but it’s a very encouraging start.
The culmination of many features has finally arrived: syntax highlighting grammars based on metadata!
This is a screenshot of my prototype language workbench for meta#. In the grammar section you write rules that get combined together into an implicit grammar which is used to parse each of the code blocks below. On the right is the AST of whatever block you have currently selected. This is a basic “hello world” grammar.
Notice the syntax highlighting! Keywords are yellow, identifiers are gray, character and string literals are green and everything else is white.
The thing that’s cool about this is that the editor for each of those blocks actually does not know anything about the grammar of the code it is highlighting. The highlighting information is coming from the metadata of the grammar itself. In fact you can add that same metadata to the grammar you are authoring in order to get highlighting in the code blocks as well.
Here you can see that I have added the [Keyword] attribute onto the ident rule, this attribute is aggregated as metadata and can be harvested by the code editor. It uses that metadata to get information about the original code and add appropriate colors. The code editor is a custom control I am working on that inherits from RichTextEditor in wpf.
This language workbench is still just a prototype but it’s still kind of cool. I have some ideas on how to evolve it that I need to solidify still but it provides a nice playground for me to experiment with features like this.