Getting into programming the .NET runtime
I've recently made my first contributions to the .NET runtime. Open source development isn't new for me, but contributing to a project of this size and with such an active community certainly was. .NET is the main platform I use, but I never looked further than the projects I build on top of it. Time to dive into the experience that is contributing to .NET!
Every year I've been to Techorama (an IT/.NET conference in the Netherlands, previously Microsoft TechDays), I've gone to sessions by Bart De Smet about new language features and the internals of .NET, just to be blown away by the Just-In-Time (JIT) compiler, intermediate language (IL), memory operations, and the like. After one of those sessions I even attempted to implement a C# language feature myself, only to fail spectacularly.
It did however pique my interest in the underlaying layers of .NET, on which I program daily (mostly on older versions, because industry likes old and stable...). Quite a few years back, Microsoft decided to open source .NET (including the runtime), providing the possibility to take a look at the code, but also to contribute to it: create issues, take part in discussions, and make code contributions.
My first contribution: make a non-nullable property nullable
My first contribution in itself was no big deal (not even a little deal): making a non-nullable string property (that could be null anyway) nullable. It did require going through the process of getting the source code, finding the correct solution to open, build the Common Language Runtime (CLR) and the libraries, make commits and opening a pull request.
After overcoming the first shock of having the build fail when finding out it's certainly not your code that made it fail, it's time to wait for feedback and the changes to be merged. As mentioned: the change was no big deal, so there was no feedback to be implemented. It's only after the changes were merged that my tiny change turned out to be a breaking one...
Turns out that making a non-nullable public property nullable would break existing code when it doesn't expect it to be nullable (causing a warning) and it gets build with warnings-as-errors enabled (please don't have me enable that in projects... ??). Something I wouldn't have thought of myself and luckily for me the friendly folks at Microsoft are handling the documentation process on that one.
StringBuilder.Replace and ReadOnlySpan<char>, who doesn't use them every day..?
Just like my first contribution, allowing StringBuilder.Replace to be used with ReadOnlySpan<char> arguments is not something I'd use in my daily work. I just picked an issue from the list that looked doable, waited for the proposed API to be reviewed during a livestreamed session by Microsoft developers/architects and went to work.
领英推荐
There was already an existing implementation of StringBuilder.Replace which accepted strings as arguments. As strings are easily convertable to ReadOnlySpan<char>, my implementation changed the existing string argument methods and the underlaying code to take the read-only spans instead of the strings and re-created the string argument methods to call them using .AsSpan() on the strings.
As more code was changed this time around, it attracted more attention and reviews. We use code reviews in my daily work, but they're not quite as meticulous as those from the likes of Stephen Toub (if you have hours to spend, read his famous performance improvements blog ??) and Adam Sitnik . Though while rigorous, they're easy and nice to interact with and very helpful in getting the code to be of the best possible quality.
As the technical implementation of an existing method changed and the signature of those string argument methods remained the same, I thought it'd be an interesting situation to use benchmarking: the same piece of code (the benchmark) can be run against the .NET 8 runtime and against my build containing my implementation of the methods. Sounds simple enough, but I must admit: I haven't used benchmarking much before and applying it to the .NET runtime took some trial-and-error. Luckily with some instructions from Adam, I made it work.
My basic benchmark indicated the new implementation might be slightly slower than the existing implementation. Not unlogical, as the string has to be converted to a read-only span (or for other reasons, I'm not sure). The issue for which the PR was created wanted the implementation for a different reason, which sadly wasn't easy to benchmark (a "PITA" - technical term ??).
Adam was nice enough to kindly indicate that the one benchmark wasn't really representative for all use cases and gave some good pointers as to which scenarios to try and which benchmarking settings to use. My more extensive benchmarking results cover those scenarios and paint a more mixed picture as to whether the new implementation is faster than the existing one: in some scenarios it seems to be, in some it doesn't. I'll let the experts working for Microsoft decide whether it's fine to accept the implementation like this, the code itself has already been "LGTM'ed" ("looks good to me").
Starting with the small issues
Small issues. They're worthy of getting worked on too, aren't they? And it's an easy way to get (somewhat) familiar with a codebase you don't know. Not for a moment will I pretend that making one constructor public, fixing the nullability of one property, or implementing two small methods will make a huge difference to the overall experience people will have with .NET. However, it might for the people who created the issues, and it certainly does when it comes to my knowledge of the .NET runtime.
I wasn't sure what to expect when making my first contribution to something as large as the .NET runtime. Would it be a good way to spend my time? What would it bring me as software developer? Were they even going to accept my contributions?
With the few contributions I've made so far, I've noticed it improving my collaboration skills, providing me the satisfaction of getting my code into a big project, and finding out more about concepts like benchmarking. The (Microsoft) people I've come across while collaborating have been friendly, very helpful, and accepting of the contributions I'm making.
Contributing to an active open source project (could be .NET, but could be something else entirely) is something I'd recommend to anyone looking to discover other sides of software development.
Senior Solution Architect for Production at Lilium specializing in Production Automation
1 年Max (a.k.a. TheMaximum) is a very skilled professional and I am proud he's part of our team! Great work Max! And fun to read as well.... :)