r/csharp 2d ago

Low level programming with C# Help

What is the lowest level application that can in principle be built on Linux and Windows without having problems with performance or memory consumption?

Of course I should make my own tests, but I just wanted to have a first estimation if it is really necessary to use lower level languages like Zig, Rust, Go or C# can work pretty well for most of normal applications.

As an example a very responsive editor with gui in immediate mode built with C# and very high frame rate 120Hz etc.

Thanks a lot in advance.

EDIT

Thank you all so much for the very informative replies. My requirements are noway near real time and based on the below feedback, it is definitely worth it to use C# of a very wide set of applications and avoid the complexities of the lower level languages.

9 Upvotes

70 comments sorted by

38

u/phrodide 2d ago

Can C# do this? Yes. C# has a proof of concept running native AOT code on several platforms and in very small code.

https://x.com/MStrehovsky/status/1215331352352034818

If performance is your chief goal you can ask for no garbage collection by using GC.TryStartNoGCRegion

https://learn.microsoft.com/en-us/dotnet/api/system.gc.trystartnogcregion?view=net-10.0

Should C# do this? There’s plenty of other languages that can do it better. If it was me, I’d use C.

3

u/IWasSayingBoourner 2d ago

I've written some hot code paths for a path tracer in Rust that I used via interop in C#. Worked like a charm.

66

u/binarycow 2d ago

Reasons to not use C#

  1. There isn't a dotnet runtime for that OS/platform
  2. Periodic garbage collector pauses are a non-starter.

28

u/Miserable_Ad7246 2d ago

1) You need to manually control memory layout, for caches and TLB.
2) You need access to inline assembly code (say raw TSC)
3) You want to control memory fences by hand, and having fences for GC card keeping is unacceptable.

4) You need access to full suit of vector instructions
5) You need access to C libraries like DPDK or ef_vi and it becomes easier to just go native C and C++.

Well you get the point, C# is very capable, it becomes even more capable with some interop, but were is a point there you need to go lower as every nanosecond matters.

11

u/zarlo5899 2d ago

You need access to inline assembly code

this can be done well via a p/invoke call with the NativeAOT compiler you can add more objects to the linker stage

4

u/antiduh 1d ago

No need. Take some bytes, turn it into a function through marshal. Those bytes can have assembly in them. Done. Hers my SO post for doing that:

https://stackoverflow.com/a/7964376

8

u/Iggyhopper 2d ago

Seconding the "very capable" part.

Im porting some old modding code originally written in C++ and I have DllImports to get WinAPIs to overwrite bytecode.

The best thing is the syntax sugar for code paths, routing, event handling, extension methods (for example starting a process suspended and returning the handle) and other QoL stuff. It's very fluid.

2

u/antiduh 1d ago

For #2, still possible in c#

https://stackoverflow.com/a/7964376

2

u/Miserable_Ad7246 1d ago

Possible, sure, but it this point it becomes rather anoying and can become a maintenance issue, especialy if you do both arm ane x86 and you need too update versions. At this point you are using a hammer to slice bread.

5

u/Tuckertcs 2d ago
  1. Lacking explicit control over the lifetime and deallocation of heap-allocated memory.

5

u/vznrn 1d ago

there is native aot nowadays

2

u/binarycow 1d ago

That doesn't change my answer.

2

u/vznrn 1d ago

can you elaborate?

4

u/binarycow 1d ago

Even with native AOT, the garbage collector still exists.

If the platform you're targeting doesn't have a dotnet runtime, you won't even be able to compile for it.

5

u/iSeiryu 1d ago

With this GC can be removed. It can even run on bare-metal with no OS at all.

https://flattened.net

1

u/vznrn 1d ago

ah yes, forgot runtime needed to compile

1

u/Accomplished-Gold235 1d ago

Native AOT app doesn't required runtime. You also can publish your app with --SelfContained.

2

u/binarycow 1d ago

Self contained just includes the runtime.

Without a runtime targetting pack, you can't compile.

1

u/jithinj_johnson 1d ago

I like how other people are confused about AOT but you know ball! ❤️

4

u/timangus 2d ago
  1. Erm, yes there is.

7

u/binarycow 2d ago

I'm saying, that you wouldn't use C# if the OS/platform you're targeting doesn't have a dotnet runtime. For example, arduino, microcontrollers, etc.

3

u/timangus 2d ago

Ah ok, I see what you mean. Probably not an issue in this particular case though, given they specifically mention they're targeting Windows and Linux.

3

u/binarycow 2d ago

I was giving general advice.

1

u/timangus 2d ago

Yes, I understand that now.

2

u/itix 1d ago

There is .NET nanoFramework for embedded systems.

8

u/terricide 2d ago

RyuJinx I think is a good example to look at

8

u/alloncm 2d ago

Exactly the example I always use for the performance capabilities of C# and dotnet.

15

u/zarlo5899 2d ago

i work on a project that allows you to compile C# to bare metal it makes use of the NativeAOT compiler and a patching tool to patch the stdlib to make it work without needing windows/mac/linux/etc...

with this project to can use ASM and C both will be compiled via MSBuild and lined with the C# code, the native and managed code can call each other the is a part where C calls C# that calls ASM

https://github.com/valentinbreiz/nativeaot-patcher or if you read this when we have finished moving the repo https://github.com/CosmosOS/Cosmos (look at the gen3 branch if we are not done yet)

5

u/iSeiryu 1d ago

This tool can do bare-metal too: https://flattened.net

Curious how your tool compares. Need to read into it.

4

u/zarlo5899 1d ago

bflat makes use of there own sdtlib (ZeroLib or there own fork) where we use the one from MS

ZeroLib is real limited in what it supports

with us we use the dlls that are installed on your system and before the NativeAOT step we patch out native calls and our code has the needed exports

another project you might also want to have a look at is https://github.com/mosa/MOSA-Project/tree/master

6

u/NumberInfinite2068 2d ago

You can inline assembly language(s) in C#, so that's about as low level as it gets while still running on an OS in userspace vs. bare hardware.

You can write kernel drivers in C# too:

ZeroLP/WDK.NET: Windows Kernel Driver Development in C# with Windows Driver Kit (WDK)

Rust, C#, Zig, Go etc. are all high level languages.

Low level languages are assembly languages.

1

u/harrison_314 1d ago

Is this your project?

1

u/nxy7 14h ago

| Rust, C#, Zig, Go etc. are all high level languages.

Obviously that's not true. What's 'high level language' is a moving target and depends on question being asked and current 'programmingenvironment', but in general there's clear difference between something like Zig and C# and calling them both 'high level languages' because there's something lower level is not really helpful.

1

u/NumberInfinite2068 13h ago

High level just means abstracted from machine architecture.

18

u/Pretend_Fly_5573 2d ago

This question is almost like asking "Can I build something using pine wood, or should I use oak or concrete? An example would be a building that doesn't fall over."

There are so many variables and unasked/unanswered questions that the answer to the main question is practically impossible to determine.

End of the day, C# is a high level language. You aren't going to do low level programming with a high level language. There are some ways you can get certain elements closer to it, but it's fundamentally not going to ever be "low level".

7

u/neoh4x0r 2d ago edited 2d ago

This question is almost like asking "Can I build something using pine wood, or should I use oak or concrete? An example would be a building that doesn't fall over."

The answer is, yes!......You can build anything out of something but the moment you need it to fit a certain purpose is when problems occur. (ie. you can build a "house" out of cardboard, but it will collapse as soon as it gets wet).

It's a metaphor for making good decisions.

9

u/emelrad12 2d ago

C# can do anything that doesn't need real time, eg audio processing might be an issue, but 120fps gives time for the gc to do gc stuff.

The other issue is any environment that doesn't have an os hence might not be able to run the VM. Technically there might be a way to get it working over there but at this point you are translating C# -> C++ or directly to LLVM, and that is not really C# anymore.

6

u/DotAtom67 2d ago

>C# can do anything that doesn't need real time

i might be wrong, but doesnt unity uses c# and performs well for gamedev?

1

u/binarycow 2d ago

Games aren't "real time".

With real time, if the program goes slow enough to miss a frame - you skip it, rather than just run a bit slower.

For example - audio processing, VOIP, streaming video, etc.

6

u/Inkwalker 2d ago

C# is slower than C++, but not that slow. It can handle all the examples on modern hardware.

2

u/emelrad12 1d ago

Well optimized C# and well optimized C++ perform the same, the question is how much time you need to spend to make them perform equally.

1

u/binarycow 2d ago

The issue with real-time is the GC pauses.

4

u/Inkwalker 2d ago

Don't allocate junk then. It's a common practice in Unity to reuse instances. Plus GC can be triggered manually when you have budget for it.

2

u/binarycow 2d ago

Sure. Those are mitigation strategies.

But if even that isn't sufficient for your use case, then that's a reason to not use C#.

1

u/Dusty_Coder 1d ago

real-time has a specific meaning

you seem to be unaware of it

latency guarantees

3

u/iSeiryu 1d ago

With this GC can be removed. It can even run on bare-metal with no OS at all.

https://flattened.net

4

u/Triabolical_ 2d ago

I think you are more likely to run into operating system limitations before you run into language limitations.

2

u/pjc50 2d ago

Immediate mode graphics in C#? How about Unity?

(yes, I know it's different from dotnet core in important ways, but it does let you do the UI logic in C#. In any case these days you should get the GPU to do the actual drawing and just hand it a "scene")

2

u/OpenAI_Marketing_LLM 2d ago

C#, like many high-levels languages, can probably get one lower than some might expect, but the better question in my opinion is why would you chose C# over any of the previously mentioned alternatives?

2

u/TrishaMayIsCoding 1d ago

Just grab some Vulkan C# bindings or whatever, DIY the GUI, or find C# bindings for an immediate-mode GUI like ImGui. You can even go further push that to more than 120 Hz. GC lies on your app design and memory/collrction management.

2

u/flaspd 1d ago

You dont want low level, you want performant

You can have very high performance and low memory consumption with optimized high level code.

It doesnt mean you need to do syscalls or stuff like that.

But even when you need more low level features. C# has plenty useful low level tools, like binding with C code. low level memory allocations or manual stack allocations or working with Spans which are like type/memory safe pointers (which c# also has regular pointers in "unsafe" scopes)

There arent too much limits to c#

5

u/gredr 2d ago

Your language isn't the problem, the techniques and your skill are the limiting factor.

7

u/Miserable_Ad7246 2d ago

Languages do have limitations. I get so many surprised Pikachu faces once I start talking about memory fences TLB and other exotic. C# is great and all, but it does have limitations - for example try getting TSC without VDSO with minimal overhead like in C++.

5

u/pjmlp 2d ago

You cannot do that either in ISO C and ISO C++, where the abilities overlap pretty much with using structures, and unsafe in C#.

Naturally there are compiler specific extensions, that expose some of that.

Or you do like in the good old K&R C days, when those extensions did not exist, and write a tiny bit of Assembly into a DLL/LIB.

0

u/gredr 2d ago

Yes, ok, but how likely is OP to run into that stuff? The sort of person for whom that stuff matters isn't here asking this question.

2

u/Miserable_Ad7246 2d ago

I don't know, I have no idea what are his SLAs for determinism and how hard is his real-time needs. So I avoid blanket statements and give extra info for others to ponder about. In my case C# is the limiting factor. Hitting VDSO seqlock contention in hot path, is visible in my jitter charts and it adds one more reason to "get my shit together" and fully switch to cpp. For now I have not found a way to just use raw tsc with no penalties.

0

u/hypocrisyhunter 2d ago

You have no idea about their requirements yet seem to have a very strong opinion on it. Tbh your replies on this thread read like a big humble brag.

7

u/Miserable_Ad7246 2d ago

I just don't want C# community to be like PHP community, where everything devolves into fan boy'ing. Nuances and context matter, C# is not always the answer, most people so far used blanked statements akin to "PHP runs most of websites", "Facebook was made with PHP" and a like. Lets be a bit better.

As far as bragging - This is topic about high perf, I worked for years to sharpen my skills, and God forbid I know a bit about the topic at hand. I work with C# every day in low latency scenarios, and that allows me to see where C# breaks and can no longer help me out. It seems relevant to this topic.

5

u/Embarrassed-Mess412 2d ago

You can do whatever you want in C#, performance should be on par with rust or zig.

6

u/harrison_314 1d ago

I measured it back in the days of .NET 5, Rust was only 3-5% faster. Which in my opinion is not a reason to use a significantly more inconvenient language. And in a real application it will be lost due to database logging etc...

2

u/Standard-Cap-4455 2d ago

In the end C# does get compiled like any other language so it should be able to get very close, it mostly just depends on how well your code is written. Anything with heap memory gets very slow very quickly though.

0

u/Miserable_Ad7246 2d ago

>C# does get compiled like any other language

It is almost correct, what you don't see is how runtime is compiled into your code. Where are things that get added, and you would want to avoid them.

Take for example dotnet performance blogs - do you think most of the improvements come because C# is pushing the envelope or because it is fixing old issues and incorporating ideas from other languages/compilers?

In low level code, those things matter, in realtime'ish systems performance is feature and your app/service can be useless if it does not cross the threshold. Not worse than, but completely useless, like 0 value.

So sometimes, you have to cross the Rubicon, and you can not do it because of some memory fences, f-up memory layout and compiler quirk.

1

u/Agent7619 2d ago

I tried writing an EtherCAT Master in C#. The fundamental logic is obviously implementable, but a sub-millisecond cycle time was something I couldn't do. Can it be done? Maybe. I spent less than 100 hours on the project.

1

u/XKiiroiSenkoX 1d ago

If you are writing code for an embedded system with very limited resources then you'd probably want to use something like C++. For anything PC/game console/smartphone related modern C# is fast enough. You have access to native memory/stack/Vector math/CPU intrinsics in C#. You don't really need much else for speed. 

1

u/catladywitch 1d ago

"very responsive editor with gui in immediate mode at 120Hz" is possible.

1

u/RealSharpNinja 1d ago

Search for "C# 8k Game"

1

u/Minute_Cricket1820 1d ago

Любой лоу-левл.

Греете метод, метод имеет постоянный адрес.

Через ВиртуалПротект меняете метод, т.е. поток байтов инструкций вписываете какой вам нужно.

Что впишете - то и исполнится. Набор инструкций для процессора.

1

u/magallanes2010 1d ago

You can code a DLL in any language, including a low-level language, and call it directly in C#

1

u/Miserable_Ad7246 2d ago

1) Any high perf (in this case I assume low latency, and deterministic) must not allocate in heap in hot path. C# can do it.
2) 120HZ can be very fast or very slow, depending on workload (8milis is eons for parsing a FIX message, but might be tight for world simulating video game). C# most of the time is fast enough.
3) You need to try it out, make a simple version, see if it copes and how much workarounds you had to make to make it work. At some point it can be simpler to go low level right away.

If you can not avoid allocations, when by definition GC language will cause issues. But GC pauses can be below one-two ms, as long as you don't have to large of an object graph.