Matt Warren

mattwarren.org · Personal blog · on HN since 2014

Matt Warren, a .NET developer, writes about CLR internals, runtime design, performance and the history of .NET.

What HN saysCommenters call it an incredible resource for CLR internals and value its write-ups on generics, CoreRT and .NET talks.
49HN people shared it
24linked it in comments
175stories submitted
5.5Kstory points
3 years agolast shared
2014people per year2026

Most-shared posts

  1. 1
    How generics were added to .NET
    7 people · 244 points · first shared 2018 · 124 comments on HN
  2. 2
    CoreRT – A .NET Runtime for AOT
    5 people · 179 points · first shared 2018 · 75 comments on HN
  3. 3
    Is C# a low-level language?
    4 people · 169 points · first shared 2019 · 71 comments on HN
  4. 4
  5. 5
    Monitoring and Observability in the .NET Runtime
    4 people · 119 points · first shared 2018 · 5 comments on HN
  6. 6
    Exceptions should be Exceptional (2016)
    4 people · 82 points · first shared 2016 · 74 comments on HN
  7. 7
    Research papers in the .NET source
    3 people · 190 points · first shared 2016 · 29 comments on HN
  8. 8
    Open Source .NET – 2 years later
    3 people · 165 points · first shared 2016 · 46 comments on HN
  9. 9
    Visualising the .NET Garbage Collector
    3 people · 149 points · first shared 2016 · 24 comments on HN
  10. 10
  11. 11
  12. 12
    Open Source .NET – 4 years later
    3 people · 23 points · first shared 2018 · discussion on HN
  13. 13
    Fast wildcard searches with trigrams
    3 people · 23 points · first shared 2015 · 8 comments on HN
  14. 14
    Stop the .NET GC Running with TryStartNoGCRegion()
    3 people · 7 points · first shared 2016 · 4 comments on HN
  15. 15
    Optimising LINQ-to-Objects
    3 people · 7 points · first shared 2016 · discussion on HN

What HN people wrote when they linked it

hdhzy · 2017-05-21
Excellent post. The blog [0] is an incredible boon for anyone interested in CLR internals. I wonder if the author considered writing a book, kind of modern Shared Source CLI Essentials (that I read years ago and hold in high regard)? [0]: http://mattwarren.org/
atombender · 2018-12-19
So where should I look? It doesn't seem to be a particularly popular or well-documented topic. The best I've found is this [1]. [1] https://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AOT/
matthewwarren · 2018-12-14
> I also love that people are doing write ups about the source of .NET Core and it's internals. Me too! BTW, if you want more on the same topic check out http://mattwarren.org/2018/07/12/Presentations-and-Talks-covering-.NET… and http://mattwarren.org/2018/01/22/Resources-for-Learning-about-.NET-Int…
Skinney · 2018-08-31
> Bytecode or ‘Intermediate Language’ (IL) changes. The main > place that the implementation of generics in the CLR differs > from the JVM is that they are ‘fully reified’ instead of > using ‘type erasure’, this was possible because the CLR > designers were willing to break backwards compatibility, > whereas the JVM had been around longer so I assume that this > was a much less appealing option. For more discussion on >this issue see Erasure vs reification and Reified Generics > for Java. Update: this HackerNews discussion is also worth a read. http://mattwarren.org/2018/03/02/How-generics-were-added-to-.NET/
shakna · 2017-07-11
The CLR is quite terrible at small programs, as you're seeing. That being said, the huge "Image" section doesn't have to be as big as you're seeing. If you look at the breakdown [0], then you can see some debugging, in the form of "TraceDLL". He also mentions that the four biggest memory eaters: System.Private.CoreLib.dll, coreclr.dll, clrjit.dll and CoreRun.exe are probably bigger than normal, because he's using a debug version of the CLR. Outside those five, every other piece of memory is shared, which changes how you see its allocation. I'd expect it'd change a measurable amount, but as before... The CLR is best when handling bigger programs, where JITing can actually make sense. [0] http://mattwarren.org/images/2017/07/Image%20Memory%20Usage.png
csharptwdec19 · 2021-03-18
There's a few challenges with doing something like this. - arrays (which most collections use under the covers) will need to allocate `elements*size_of_struct`. Unless the structs are the same size, you'd have to do some level of thunking/offsetting. - Even if they are the same size, when you're iterating the list, how would the runtime know whether it's `A`, `B`, or `C`? Structs don't have header information that can be used to infer the type, it's only whatever fields you've defined (with padding potentially). Part of 'boxing' is essentially thunking the struct by wrapping a methodtable for the struct into the object [0]. If you need something like polymorphism with structs, your best bet is to make the struct itself quasi-polymorphic (i.e. with enums) and/or start abusing generics in some fashion I haven't yet figured out. [0] - https://mattwarren.org/2017/08/02/A-look-at-the-internals-of-boxing-in…
bad_user · 2018-01-17
On .NET Core's focus, that's not actually true: http://mattwarren.org/2017/12/15/How-does-.NET-JIT-a-method-and-Tiered… Android optimizes for battery life, but it's also worth noting that Dalvik was a really rudimentary JIT, having no benefits from JIT compilation, only drawbacks, the ART with AOT being a good upgrade. But tiered compilation is in a different league, being about speculating what's going to happen depending on what the process has witnessed thus far. The point of tiered compilation is to profile/guard stuff at runtime and recompile pieces of code based on changing conditions, which is how you can optimize virtual call sites or other dynamic pieces, which you can't do ahead of time because the missing part is the decompiler which can revert optimizations based on invalidated conditions. It's really interesting actually, because you can profile a C++ app and use that to optimize your AOT compilation, but the compiler is still limited by the things it can prove ahead of time, or otherwise it would be memory unsafe.
samsquire · 2023-05-29
Thank you for your reply. I prefer reading documentation or technical deep dives - such as this one https://mattwarren.org/2017/02/07/The-68-things-the-CLR-does-before-ex… Is code more dense than English? Why do I understand more overall from this blog post than I would if I studied the codebase of the CLR for hours and hours. I think it's to do with mental models. If developers were on all the same page of understanding the underlying mental models, we could all understand eachother's code because we all understood the same underlying things.
NovaX · 2023-03-14
You might enjoy the alternative approach taken by .NET's threadpool which uses hill climbing to dynamically adjust the number of threads. See this articles [1] and its references to Microsoft's papers on their design. Semi-relatedly, I used hill climbing to adjust the eviction policy in Caffeine (Java cache) to favor recency/frequency. While it seemed simple and naive, it worked surprisingly well and robustly. [1] https://mattwarren.org/2017/04/13/The-CLR-Thread-Pool-Thread-Injection…
sremani · 2022-03-12
C# is not faster than Rust - but you can get near Rust performance with all the safety and memory management goodness. On benchmark C# is giving go run for its money! But again, it is easy to get carried away by benchmarks. Go-routines are a killer feature, .Net async/await come with gotchas. The weird space of .Net/.net is because the first 15 or so years - it was hostage to Windows. There by tainting its mind-share and engineering culture. Links (a bit old ones about C# low level chops) https://mattwarren.org/2019/03/01/Is-CSharp-a-low-level-language/ https://www.youtube.com/watch?v=mLX1sYVf-Xg
pjmlp · 2021-11-09
The actual history goes a bit differently, they already had generics working, however they weren't stable and management didn't want to delay the initial release. https://mattwarren.org/2018/03/02/How-generics-were-added-to-.NET/
lukevp · 2020-07-24
Why the hate on C#? Are you perhaps thinking of languages like Ruby and Python and grouping them into the same bucket as C#? This[0] shows an example of C# vs C++ having a 10% performance gap on ray tracing. There is also no reason that extremely performance sensitive parts couldn’t be rewritten in Rust or C or C++ and called from C# over a FFI. [0]: https://mattwarren.org/2019/03/01/Is-CSharp-a-low-level-language/
throwlaplace · 2019-12-26
>Does F# offers native builds ? I thought it was CLR only. i would guess that it will eventually support aot: https://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AOT/
MarkSweep · 2019-10-14
It looks like the number of threads in the threadpool is fixed. If have 1 one thread in the thread pool, is it possible to dead lock it by queuing a Task A the blocks waiting for Task B to do something, where A starts executing before B? Do you think it would make sense to dynamically adjust the number of threads in the pool? An example of a thread pool that dynamically adjusts the number of threads is .NET. The algorithm is described by Matt Warren[1] and a paper[2]. In addition to the C++ version Matt links to, there is a C#[3] implementation. [1]: https://mattwarren.org/2017/04/13/The-CLR-Thread-Pool-Thread-Injection… [2]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.487.7627&… [3]: https://github.com/dotnet/corert/blob/master/src/System.Private.CoreLi…
acqq · 2019-03-25
If I understand correctly, that uses this: https://github.com/dotnet/corert Written about here: https://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AOT/ "One of the first things people asked about CoreRT is “what is the size of a ‘Hello World’ app” and the answer is ~3.93 MB (if you compile in Release mode), but there is work being done to reduce this." .. "So Test.CoreLib really is a minimal runtime!! But the difference in size is dramatic, it shrinks down to 0.49 MB compared to 3.93 MB for the fully-featured runtime!"
tigershark · 2019-03-17
C# compiler can generate a huge amount of code from simple and small programs: https://mattwarren.org/2017/11/08/A-DoS-Attack-against-the-C-Compiler/ But you can very easily get the AST. Obviously it may happen that you have to wait until the hell is frozen to get a result, but generally it doesn’t happen in code that you see day to day..
benaadams · 2019-01-27
Any obvious reasons currently; or just historic ones? i.e. its been fully open source for 4 years https://mattwarren.org/2018/12/04/Open-Source-.Net-4-years-later and is under the .NET Foundation rather than Microsoft https://dotnetfoundation.org/
cmiles74 · 2018-07-19
I agree that generics should probably be a strong consideration right from the beginning. I disagree that this would mean that it would necessarily be done correctly or that it's impossible to add it later. That was the case with .Net and C#, it wasn't until the 2.0 release that generics were added. [0] [0]: http://mattwarren.org/2018/03/02/How-generics-were-added-to-.NET/
tjalfi · 2017-05-11
TypeMock Isolator[0] and JustMock[1] can mock nonvirtual methods and static methods. Fody Ionad[2] is a free tool that can replace static methods. The reason that most mocking framework don't support this is that the implementation is complex[3]. [0] https://www.typemock.com/isolator [1] http://www.telerik.com/products/mocking.aspx [2] https://github.com/Fody/Ionad [3] http://mattwarren.org/2014/08/14/how-to-mock-sealed-classes-and-static…
flukus · 2017-05-01
.Net now has a non-hierarchical version of this: http://mattwarren.org/2016/08/16/Preventing-dotNET-Garbage-Collections…
SloopJon · 2016-05-09
This post suggests that Stack Overflow has about 30,000 distinct tags, which seems like a good fit for a bitmap index: https://mattwarren.org/2015/08/19/the-stack-overflow-tag-engine-part-2… Not that that's the whole solution, but certainly something I'd look into before digging into CUDA.
skybrian · 2021-11-09
Java did this in a very complicated but backwards-compatible way. (Including bytecode level compatibility.) Here is a detailed FAQ [1] devoted to the intricacies of Java generics, covering erasure, bounded and unbounded wildcards, special cases for raw types and arrays, workarounds for primitive types, interaction with inheritance, etc. It was a big achievement, but also something to learn from. It’s reasonable that other language designers would want to do better. The C# designers tried to improve on what Java did, reconsidering many of their design decisions [2]. Apparently it was a five year effort, including inventing novel runtime mechanisms. They had different goals, particularly supporting multiple languages and cross-language compatibility. Go’s generics support is another years-long effort. They reconsidered everything again in a new context, because the Go language doesn’t have the same features or design constraints. That’s also a big achievement. This only looks like the “exact same thing” if you ignore all the history. Language design is all about the details. Every language feature interacts with every other language feature. The “peanut gallery” is a lot of random people, some of whom don’t know anything about designing or maintaining a production language. If you really want to know about this stuff, I suggest reading the papers by people who actually did it. [1] http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html [2]…

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close