[HN Gopher] BrainFlood: Runtime code generation via reflection i...
___________________________________________________________________
BrainFlood: Runtime code generation via reflection in .NET
Author : thunderbong
Score : 69 points
Date : 2025-01-26 08:05 UTC (2 days ago)
(HTM) web link (sbox.game)
(TXT) w3m dump (sbox.game)
| antithesis-nl wrote:
| Ah, yes, this is delightfully useless! Well, maybe good for
| stress-testing language tooling (that single huge type expressing
| the Mandelbrot generator is... something to behold), but mostly
| just cool-that-this-can-be-done.
|
| Another cool thing that I learned about via this post (as I was
| wondering about the .scene files in the GitHub repo) is this
| whole ecosystem:
|
| > S&box is coded in C#. Under the hood, it uses the Source 2
| engine (CS2, HL:Alyx, DOTA2) and some of its systems: rendering,
| resources, physics, and audio
|
| And people say there is no more Good Stuff on the Internet...
| pjc50 wrote:
| This is quite something. I suspect this person has a C++
| background, because the thing where they're abusing the generic
| type system to do arithmetic is very much more like C++ template
| libraries than something you normally see in C#. The advantage
| seems to be that you can use MakeGenericType() in situations
| where the normal bytecode Emit() isn't available?
| kittoes wrote:
| I wouldn't exactly call it "normal", but that's partially
| because a lot of C# developers still don't know about the
| relatively new generic maths feature. Those who are familiar
| regularly "abuse" the system in a similar way because that's
| one of the major benefits of it. We don't necessarily
| reimplement basic arithmetic using the type system, but we
| regularly hoist generic constants into static properties in
| order to convince the compiler to behave the way we expect. For
| example: _T.PopCount(value: T.AllBitsSet)_ is a safe and
| generic way to express the size of a binary integer as a
| constant.
| neonsunset wrote:
| > For example: T.PopCount(value: T.AllBitsSet) is a safe and
| generic way to express the size of a binary integer as a
| constant.
|
| Despite the name, 'Unsafe.SizeOf<T>()` is the safe and
| preferred way to do this - it is guaranteed to be a compiler
| constant (in the past you'd say "JIT constant" but you can no
| longer assume that with the advent of NativeAOT).
|
| It's a bit unfortunate because much like with MemoryMarshal,
| not all methods are equally unsafe. Some are benign or safe
| like this one, same are Unsafe.As or, worse,
| Unsafe.AsPointer.
| tialaramex wrote:
| > Despite the name
|
| Why even _have_ something labelled "Unsafe" which is in
| fact safe ? Genuine question. What lead to this choice?
| kittoes wrote:
| The reasoning is generally that using SizeOf implies one
| is doing unsafe things. Why do you need the size of
| something in managed code? What would you do with that
| information?
|
| Not that I necessarily agree with the decision myself,
| but that's the argument made by others.
| Timwi wrote:
| Sounds like an awesome article, but it's unreadable on mobile
| (cut off on both sides) so I'll have to wait to read it until I
| get to a PC. Might be worth fixing
| nguyenkien wrote:
| Your mobile browser doesn't have reader view?
| gwbas1c wrote:
| You shouldn't have to jump through hoops to read an article
| on a phone. It's 2025; mobile browsers have been mainstream
| since 2007.
| maushu wrote:
| Desktop mode in mobile seems to work fine.
| recursive wrote:
| The point is that normal mode doesn't.
| gpvos wrote:
| Looks fine to me (Fennec 134 on Android).
| saurik wrote:
| Maybe it has been fixed, but the article currently looks fine
| for me on an iPhone.
| souenzzo wrote:
| Feels like a brainfuck interpreter version of magic(1), a
| clojureCLR JIT compiler implemented via macro.
|
| 1 https://github.com/nasser/magic
| neonsunset wrote:
| > Practical .NET Optimization Abuse
|
| This is not abuse, it's intended behavior, standard library
| itself likes to use it a lot internally. That's also how generics
| work in Rust!
|
| This can be pushed further by passing data by ref's. You can also
| easily allocate structs in unmanaged heap (aka malloc and free)
| and then pass them by `ref` without using unsafe (save for
| construction and alloc/free). Just don't do it for structs which
| contain gcrefs. C# can lean very heavily into systems programming
| :)
|
| There have also been a large amount of struct optimizations
| across the last few versions. So it is not a coincidence that
| RyuJIT/ILC can trade blows with LLVM (not always but still!).
|
| Edit: Oh god, I saw what this refers to. I take it back. There is
| likely a better, idiomatic and compiler-friendly way haha.
| MrLeap wrote:
| This is fascinating! Code generation is a thing that's solved a
| couple problems for me recently. The way I do it never feels
| great. Whenever I want to cache a big dictionary literal, I tend
| to generate the code as a string and write it to a file. I've yet
| to find a compelling upgrade that checks all the boxes. (The
| generated side has run in the kneecapped .net for unity, although
| the generator doesn't necessarily.)
|
| I'm going to dig into your implementation.
| kkukshtel wrote:
| You could source generate this directly into your code instead
| of dealing with file IO. Newer versions of Unity support source
| generators:
|
| https://docs.unity3d.com/6000.0/Documentation/Manual/create-...
| whizzter wrote:
| This is quite cursed, but does show that the .NET runtime system
| and JIT seems fairly robust even in the presence of this
| stupidity.
| MarkSweep wrote:
| This is great and despite what the article says, an actually
| useful technique. The reason this performs well is the .NET
| runtime does monomorphization when the generic type parameters
| are value types (primitive types like int or user-defined
| structs). In modern .NET you would use static abstract methods
| interface methods to implement this feature. But if you have to
| run on the old Windows-only .NET Framework, you need to use the
| approach used in BrainFlood. See this article [1] for more
| details. An example of an official .NET library that uses this
| technique on .NET Framework is TensorPrimitives. See this file
| [2], the structs are defined at the bottom.
|
| [1]: https://blog.stephencleary.com/2022/10/modern-csharp-
| techniq...
|
| [2]:
| https://github.com/dotnet/runtime/blob/main/src/libraries/Sy...
___________________________________________________________________
(page generated 2025-01-28 23:01 UTC)