Ask HN: What less-popular systems programming language are you using?
465 comments
·March 1, 2025yellowapple
I've pretty much settled on Zig at this point, if only for how dead-simple it is to cross-compile for other hardware platforms. The process of compiling working code for oddball platforms (in my case the Nintendo 64) was way easier than I expected it to be.
The only downside is the stdlib being as fast-moving of a target as it is. Right now I've had to put a pin on getting panic stack traces to work on my N64 code because apparently the upcoming release changes a bunch of stuff around panic/stacktrace handling (and it's already changed quite a bit over the years even before these new changes).
archargelod
> how dead-simple it is to cross-compile for other hardware platforms
The fact that zig can compile C code makes it useful for other languages too. I recently started using `zig cc` to cross-compile Nim for lots of different platforms within the same environment.
It takes no time to setup and, honestly, works like magic.
Galanwe
> The fact that zig can compile C code makes it useful for other languages too
Agree, C interop is IMHO the big feature of Zig. There are plenty of systems programming languages in 2025, but where Zig shines is its pragmatism: a single standalone binary containing compiler, libc, build system, code formatter and test runner for C and Zig.
As of late though, I've been concerned with some "holy wars"/"ideological postures" that the dev team started which IMHO departs from the original "let's be pragmatic" mantra.
- There's a bunch of places where the stdlib just crashes on unreachable assertions, and that won't be fixed "because the kernel should have better error reporting".
- There are a bunch of kernel syscalls which are just not possible to call "because C enums should not allow aliases"
- etc
I hope this trend fades away and it gets back on a more pragmatic stance on these issues, nobody wants a systems programming language that plays the programming police.
Otherwise, C3 looks promising as well (though not as nice than Zig IMHO), but currently it's a bit too barebone to my taste. There no stable LSP, no nvim plug-in, etc.
csdvrx
I like Perl mostly because it's poetic (the code is super nice to read, with variable types standing out thanks to sigils), but another core strength is how very fast and light it is.
Instead of "cross-compiling" or just running a native perl interpreter (there's one for about every platform!), I prefer how Actually Portable Executables make Perl multiplatform with just 1 binary asset running everywhere!
I wanted to write a webserver processing CGI to learn more about the "old school web", so I wrote https://github.com/csdvrx/PerlPleBean and the simplicity of just downloading and running the .com on anything is very nice
I'm now trying to do the same in Python3, but it's not as fun - and I'm not yet to the part where I will try to safely run python code within the python webserver, either through restrictedpython or ast.parse(), ast.walk(), eval(compile()) ...
dwedge
I also choose Perl most of the time, but I think this is the first time I've ever heard anyone call it super nice to read
yellowapple
Perl was my first "real" language, i.e. the first one that actually "clicked" for me. Still holds a soft spot in my heart, even though I don't use it much these days. It's one of the few languages (along with Ruby, Erlang, and Zig) that I feel have made me a better programmer by learning them.
ajsnigrutin
I like perl, because the code i wrote 20 years ago still works without issues.
phatskat
Just wanted to say that I really dig your enthusiasm! I read most of PerlPleBean’s README and was smiling the whole time - APE was so exciting to read about when it came out, and your project may just inspire me to look more into what it can do!
kamma4434
Importing stuff fron CPAN used to be a nighthmare but I admit I have a sweet spot in my heart for Perl.
Galanwe
> The only downside is the stdlib being as fast-moving of a target as it is.
Ah that's an interesting take, my opinion is that the stdlib doesn't move fast enough.
In its current state it's pretty broken, most of the "process", "os" and "posix" modules are either straight up raising unreachable in normal scenarios, or simply badly designed. I would like the stdlib to be much more fast moving and fix all these issues, but I had the impression most work on it is frozen until 0.15 or 0.16, after incremental compilation is done.
brodo
You are right, the stdlib is not the highest priority right now. There are major improvements coming in 0.14 though. The new default allocator for example. I think the problem you describe can be solved by having more contributors focussing on the standard library. With the compiler, there are bottlenecks which make onboarding new people hard. This is a smaller problem in stdlib.
Galanwe
> I think the problem you describe can be solved by having more contributors focussing on the standard library.
I don't think so, my impression is that stdlib improvements are volontarily frozen for now, not because of a lack of contributors but because of a lack of clear plan as to what the stdlib should look like. There are a number of issues and PR of people willing to contribute to stdlib that are stalled.
That's not to say that's its bad per se, "we don't have a plan for now and don't want people to commit time for an unclear target" is a perfectly OK answer.
epolanski
I'm picking up zig as my first system programming language myself and I love it.
Sadly the job market looks dead
azthecx
It's such a new language, not even in 1.0.0 You won't really find companies willing to bet their livelihoods at such an early stage.
You can make your own though :)
nyjah
What N64 code are you working on? I am intrigued.
yellowapple
Current progress is here: https://fsl.yellowapple.us/zig64/dir?ci=trunk
Right now it's just a bunch of WIP Zig interfaces for the N64's hardware, but the end-goal is to get it developed enough for homebrew gamedev.
nyjah
Wow - will follow. Awesome!
dvdbloc
What’re you doing with Zig and N64? Sounds awesome.
yellowapple
Eventually, I hope to use Zig for N64 homebrew.
To get there, though, I need to implement Zig-ish interfaces to the N64's hardware, which is slowly-but-surely happening at https://fsl.yellowapple.us/zig64/dir?ci=trunk
creakingstairs
I've been using Odin [1] for my hobby game development and I've been liking it a lot. Feels like a more ergonomic C.
Things I like:
- Vendor libraries like Raylib and MicroUI make it easy to get started
- I can pass around memory allocators and loggers implicitly using context, or explicitly if I need to.
- natively supports vector math and swizzling
- error handling with `or_else` and `or_return`
Things I don't like:
- Name spacing is a bit annoying. The convention is to prefix the procedures but I don't like how they look. It really isn't a big issue.
Have a quick read of the overview and if you are still interested, I highly recommand 'Understanding the Odin Programming Language' book by Karl Zylinski [2]
johnisgood
I like Odin, but the creator is not too motivational (or rather, actively un-motivational)[1]. I still use it nonetheless for some of my own stuff, for now.
Regardless, I do recommend people to try it out. I use Linux and OpenBSD, too, despite Linus and Theo. :)
[1] The reason for why I think this can be found in their pull requests, but it's been some time I think.
amjoshuamichael
What do you mean by "motivational?" Are you talking about how the creator is against adding new features to the language? I actually think that's perfectly fine. One of my favorite things about Odin is the simplicity; the entire language and all of its rules can be understood by reading the Odin overview document. I'm actually thrilled to have a creator that doesn't want to bloat the language.
johnisgood
No, suppose you make a contribution to a project and its creator belittles you instead of providing constructive criticism, for example. This contribution is not a new feature to the language, however, perhaps a 3rd-party library.
It has nothing to do with adding new features. I agree with you, I do not want the language to be bloated, nor do I want new features blindly added. I prefer simplicity, too.
FWIW you can see him losing his "cool" on Discord, too, at times.
xxami
I remember being turned off from it for the same reasons, in particular there were some fairly harsh comments directed to V's developer which felt a bit dog piley to me. Drama's long dead now.. It is a great language though. Closest to the language that would kill C for me so far, but not quite =D
johnisgood
I missed out on this! I remember something, had no idea Odin was involved.
chris_armstrong
OCaml
The compiler is very fast, even over large codebases.
Mostly trying to bring AWS tooling to the platform[1], or experimenting with cross-compilation[2] using another less well known systems language, zig.
[1] https://github.com/chris-armstrong/smaws/ [2] https://github.com/chris-armstrong/opam-cross-lambda
mbac32768
I've used a lot of programming languages and the kind of groove you can get into with OCaml is hard to match. You can just dive into an enormous, unfamiliar codebase and make changes to it with so much more confidence. But while it's reasonably fast, it's also higher level than Rust so you don't have to struggle quite so much with forms like `Arc<Mutex<HashMap<String, Box<dyn Processor + Send + Sync>>>>` everywhere.
Re: AWS tooling, have you seen https://github.com/solvuu/awsm ?
It generates code for all 300+ AWS services and produces both Async and Lwt forms. Should be fairly extensible to Eio.
I worked on this. Let me know if you want to tag team.
IshKebab
I want to like OCaml but OPAM is just so bad... and tooling is super important (it's one of the reasons Go is popular at all). Windows support is also an afterthought. There's no native debugger as far as I can tell. This is before you even get to the language which definitely has its own big flaws (e.g. the lack of native 64-bit integers that MrMacCall mentioned.
The syntax is also not very friendly IMO. It's a shame because it has a lot of great ideas and a nice type system without getting all monad in your face. I think with better tooling and friendlier syntax it could have been a lot more popular. Too late for that though; it's going to stay consigned to Jane Street and maybe some compilers. Everyone else will use Rust and deal with the much worse compile time.
Taikonerd
> The syntax is also not very friendly IMO.
Very true. There's an alternate syntax for OCaml called "ReasonML" that looks much more, uh, reasonable: https://reasonml.github.io/
Bilirubino
The OCaml syntax was discussed a long time ago between the developers and the whole community and the agreement was that the community is happy with the current/original syntax. ReasonML was created for those developers more familiar with Javascript, but it was not very successful in attracting new developers as they usually look more at the semantics of the language along with the syntax (and that is where OCaml's type system shines). Strictly speaking, there is a long list of ML family languages that share many properties of OCaml's syntax. However, what is a ‘reasonable’ syntax is open to debate. Javascript and Python were not mainstream languages when Ocaml was developed and it made much more sense to create a syntax in line with the ML family of powerful languages available at the time. Once you program a bit in OCaml syntax is not a problem, learning to program in a functional paradigm and getting the most out of it is the real challenge.
mbac32768
> (e.g. the lack of native 64-bit integers that MrMacCall mentioned.
They exist, I think you just mean `int` is 63-bit and you need to use operators specialized `Int64.t` for the full precision.
MrMcCall
How can you access the full 64 bits if "one bit is reserved for the OCaml runtime"? (the link is in the my original post's thread)
dgan
Why opam is bad? Compared to what? Could you elaborate
IshKebab
1. I've found it to be extremely buggy, often in confusing ways. E.g. there was a bug where it couldn't find `curl` if you were in more than 32 Linux groups.
2. It has some kind of pinning system that is completely incomprehensible. For example you can do `opam install .`, which works fine, and then `git switch some_other_branch; opam install .` and it will actually still install the old branch?? Honestly I've never figured out what on earth it's trying to do but me and my colleagues have had constant issues with it.
> Compared to what?
Compared to good tooling like Cargo and Go and NPM and uv (if you give it some slack for having to deal with Python).
It's better than Pip, but that doesn't take much.
fuzztester
>The syntax is also not very friendly IMO.
Why do you think that the syntax is not very friendly?
Not saying you are wrong, just interested to know.
satvikpendem
Have you tried esy?
fuzztester
I've read some part of the book Real World OCaml, by Yaron Minsky and Anil Madhavapeddy.
https://dev.realworldocaml.org/
I also saw this book OCaml from the Very Beginning by John Whitington.
I have not read that one yet. But I know about the author, from having come across his PDF tools written in OCaml, called CamlPDF, earlier.
https://github.com/johnwhitington/camlpdf
>CamlPDF is an OCaml library for reading, writing and modifying PDF files. It is the basis of the "CPDF" command line tool and C/C++/Java/Python/.NET/JavaScript API, which is available at http://www.coherentpdf.com/.
davidwritesbugs
My problem with OCaml is just that there is no stepping debugger for VScode. I'd use it except for that.
worik
Yes
Symbolic debugger seem to be going out of fashion
MrMcCall
It's my understanding that OCaml does not allow its programs to specify the size and signedness of its ints, so no 16-bit unsigned, 32-bit signed, etc...
Being a huge fan of F# v2 who has ditched all MS products, I didn't think OCaml was able to be systems-level because its integer vars can't be precisely specified.
I'd love to know if I'm wrong about this. Anyone?
cmrx64
You’re wrong, not sure where you got that conception but the int32/64 distinction is in the core language, with numerous libraries (eg stdint, integers) providing the full spectrum.
MrMcCall
Thanks. They're not in the basic-data-types, but you are correct, they are available in the stdint module, which has a pub date from Oct 19, 2022. It can be found here:
> https://opam.ocaml.org/packages/stdint/
It's been a while since I investigated OCaml, so I guess this is a recent addition and is obviously not a part of the standard integer data types (and, therefore, the standard language), that not only have no signedness, and only have Int32 and Int64, but have "one bit is reserved for OCaml's runtime operation".
The stdint package also depends on Jane Street's "Dune", which they call a "Fast, portable, and opinionated build system". I don't need or want or need any of its capabilities.
As well, the issues page for stdint has a ton of more than year old open issues, so, as I understood, OCaml does not, like F#, have all sizes and signedness of ints available in their fundamental language. Such a language is simply not a good fit for system-level programming, where bit-banging is essential. Such low-level int handling is simply not a part of the language, however much it may be able to be bolted on.
I just want to install a programming language, with its base compiler and libraries and preferably with man pages, open some files in vi, compile, correct, and run. That is my requirement for a "systems-level" language.
I would never in my life consider OCaml with opam and Dune for building systems-level software. I wish it could, but it's not copacetic for the task, whose sole purpose is to produce clean, simple, understandable binaries.
Thanks for helping me understand the situation.
Bilirubino
The modules Int64 and Int32 and part of the OCaml standard library. You mentioned that it is needed dune or Janestreet in your comments to have this functionality. They are part of the standard library. Really, they are part of Ocaml core developments. Actually, for example, you even can use the library big-arrays with these types and int8, int16, signed, unsigned... even more you have platform-native signed integers (32 bits on 32-bit architectures, 64 bits on 64-bit architectures) with Bigarray.nativeint_elt as part of the standard library so all these types are there.
You also mention that Int32 and Int64 are recent, however these libraries were part of OCaml already in the 4.X versions of the compiler and standard library (now we are in the 5.3).
Note that in OCaml you can use C libraries and it is quite common to manage Int32, Int64, signed etc...
eimrine
What is ML programming language? They say OCaml is the same thing with the different name, is it truth?
rowls66
Can a systems programming lanugage use garbage collection? I don't think so.
flavio81
You´d be surprised.
In the 1980s, complete workstations were written in Lisp down to the lowest level code. With garbage collection of course. Operating system written in Lisp, application software written in Lisp, etc.
Symbolics Lisp Machine
https://www.chai.uni-hamburg.de/~moeller/symbolics-info/fami...
LMI Lambda http://images.computerhistory.org/revonline/images/500004885...
We're talking about commercial, production-quality, expensive machines. These machines had important software like 3D design software, CAD/CAM software, etc. And very, very advanced OS. You could inspect (step into) a function, then into the standard library, and then you could keep stepping into and into until you ended up looking at the operating system code.
The OS code, being dynamically linked, could be changed at runtime.
seanw444
My two recommendations are easily Nim and Zig.
If you want something that is essentially just a modernized C, go with Zig. The concept of compile-time programming having the same appearance as runtime programming is very cool in my opinion. My only major complaint at the moment is that duck typing is fairly prevalent. Sometimes function arguments are declared `anytype` and you occasionally have to dive down multiple function calls to figure out what's going on, though that's not too much of a hindrance in practice, in my experience.
My personal favorite language is Nim. Efficient, but simple, memory management (drawing from C++/Rust). You rarely have to think too hard about it, yet making fast programs is not complicated. You can stick to the stack when you want to. The flexibility at compile-time gives you great power (but it requires great responsibility -- easy to abuse in a bad way). The type system is awesome. The only downside for me is the tooling. The LSP needs much optimization, for example.
sph
My issue with Nim is its import system. If you have a function "foo" it's hard to tell where is it imported from. I'm not sure why this bothers me when C is the same... probably because I'm familiar by now which header defines any C function.
Also, I believe high-level compiled languages suffer from the fact that it is very hard to tell which construct is expensive and which is a zero-cost abstraction. Rust has the same issue, but "zero-cost" is a major feature of the language so you don't feel bad using an Iterator, for example, in kernel code. With Nim it is hard to tell.
seanw444
It makes logical sense to do imports that way when operator overloading exists. Otherwise your custom operators would look like:
import other
varA other.`+` varB
Which is very ugly. At that point, we might as well just go with the function name approach that languages like Go take: customAdd(varA, varB)
I suppose you could change it so operators are imported into the same namespace, and non-operators still require a separate namespace when referred to. But that makes it even more complicated in my opinion. I agree it's less obvious what's coming from where, but I think when your libraries have distinct responsibilities, it usually ends up being pretty straight-forward what function comes from where based on how it's named (if it's written well).winrid
I find the type system in Nim to be pretty poor. It's difficult to reason about what is on the stack vs heap by looking at the business logic and not the types themselves, and also hard to reason about when you do copies vs pointers, since everything is defined on the type itself. I find it to be a bad design decision, I wouldn't build anything large with it.
optymizer
> The concept of compile-time programming having the same appearance as runtime programming is very cool in my opinion
https://tour.dlang.org/tour/en/gems/compile-time-function-ev...
flavio81
>The concept of compile-time programming having the same appearance as runtime programming is very cool in my opinion.
You mean, something that Lisp does since the early 1980s?
seanw444
I didn't say it was novel. It's just not something you see in modern languages.
akho
Should that make it uncool?
bsder
> You mean, something that Lisp does since the early 1980s?
Um, no. Debugging a macro in Lisp is a terrible experience while debugging a comptime function in Zig is brain dead simple.
Zig is the first "macro" system I've used that doesn't want to make me blow my brains out when I need to debug it.
perching_aix
Yes, I think that's what they mean.
kevlar700
Loving Ada without using exceptions or inheritance on embedded and desktop. Some love Ada full OOP tagged types. I love Ada procedural style with privacy and abstract data types. I wish Flutter was written in Ada but atleast Dart is better than JavaScript atleast for procedural code without it's oop boiler plate. You don't actually need OOP for widgets.
linuxlizard
I'm a big fan of Ada. I first encountered exceptions in Ada. When I first saw Python, way back in version 1.5, I was happy to see exceptions.
dominicrose
But is Dart better than Typescript? I prefer Typescript for multiple reasons but one of them is that you don't have to use classes to use the advanced typing system. Without a typing system I like Ruby the most, but sometimes we just need a typing system.
IshKebab
Dart is better in some ways and worse in others.
1. It has an actually sound type system.
2. The language and standard library are waaaaaaaay ahead of Javascript.
3. The tooling is top notch. Better than JS/TS.
But on the other hand:
4. Way smaller ecosystem.
5. Debugging is worse if you're compiling to JS. The fact that the code you run is basically identical to the code you write in TS can be a big advantage. Only really applies for web pages though.
6. Type unions are way nicer in TS.
7. Non-nullable types interact badly with classes. It can make writing methods correctly really awkward - you have to explicitly copy member variables to locals, modify them and then write them back.
8. Way smaller community.
ohmahjong
As someone curious about learning more about type systems, would you mind elaborating on 1.? I'm assuming you mean the formal definition of "sound", not just as a synonym for "sensible". Sound typing is often something handwaved away as not being particulary consequential in practice; what benefits have you seen there?
satvikpendem
> I wish Flutter was written in Ada but atleast Dart is better than JavaScript atleast for procedural code without it's oop boiler plate. You don't actually need OOP for widgets.
You can use other libraries for this like Riverpod with flutter_hooks and functional_widget which essentially removes the OOP structure of widgets and turns them more into functions, in a way.
numerosix
I second that. From 8 to 64 bits systems, embedded or system programming, Ada is the best choice. I've saved tons of missing hours, headhaches, etc. with this gem. Search Github Sowebio Adel for a good setup manual and, in the same repo, v22 for a good gp kiss framework...
johnisgood
What are you using Ada for?
numerosix
Embedded 8 and 32 bits microcontrollers to web linux based erp/crm softwares. Ada can be used for anything, with the speed of C/C++ but in a far more readable and safer way... Ada is a secret weapon. Don't spread theses infos ;)
mkovach
Free Pascal, but I am interested in Ada and will be learning it more this year. I love the readability of the syntax, and on the outside looking in, the community seems good.
I have also moved back hard to using TCL as my scripting language. I like it too much, and bouncing between Python, Go, and such for DevOps glue tires me out.
For systems, I love using plan9 (9front) to solve problems, which grounds me to C, awk, sed, and the rc shell.
pjmlp
That would be mix of D, Object Pascal, Swift, Ada, C#, Java.
A few decades ago plenty of Oberon dialects.
As language geek, I randomly select languages when doing hobby coding.
Regarding Go's remark, even if I dislike Go's authors decisions, back in my day writing compilers, linkers, firmware, networking stacks, and OS services was considered systems programming.
Likewise .NET team has been making wonders catching up to what C# 1.0 should have been for low level code, given its Delphi linage.
Java, in the context of being whole Android userspace, including drivers, there is very little systems exposed in the NDK. Vulkan is one of the few things not exposed to Java land, and that is being fixed with WebGPU like API in an upcoming version.
gnz11
What are your thoughts on D? My experience is limited but seems like a very underrated language.
sfpotter
I started using it recently for a prototype of something I'll eventually rewrite in C++ at work. I really like it.
Discarding the preprocessor and replacing it with a proper module system is huge. I got burnt by templates and horrifying compile times in C++, but haven't had any problems with D templates. The module system makes templates feel much more natural to use. The syntax for templates is a huge improvement, and throwing `static if` into the mix results in concise and easy-to-read code.
I also quickly realized (with the help of some people on the D discord) that the garbage collector is fine for my needs. So I don't have to spend any time thinking about memory management... put stuff on the stack when I can for speed, othrewise just GC and don't think about it. I think there may be some issue with multithreading and the GC, but this is supposed to get fixed with the new GC that's on the way.
There are a few other nice QOL improvements. Getting rid of `->` is honestly worth its weight in gold. There's nothing difficult about forgetting to change a `.` to a `->` or vice versa in C++, but not having to trip over it periodically when you're compiling makes the language that much smoother. I was also initially confused by the `inout` keyword but have come to really like that, as well. Little niceties like `const(T[])` are small but, again, reducing just a little bit of friction like this across the language makes D much, much more pleasant to deal with than C++.
I think the main challenge the language is facing right now is that it's huge and a lot of it is still getting worked out. I never thought I'd pine for C++'s "rule of 3/5/0", but it's a lot tighter and more logically consistent than the equivalent in D. But part of that is there being a huge community of C++ developers who have taken the time to promulgate rules of thumb in the community. I'd kill for an "Effective D" book to short circuit some of this process... after all, I'm trying to write code, not play at the margins, tinkering with D's idiosyncracies.
fuzztester
>I'd kill for an "Effective D" book
https://en.m.wikipedia.org/wiki/Scott_Meyers
The Last Thing D Needs - Scott Meyers - DConf 2014
e12e
> (...) for a prototype of something I'll eventually rewrite in C++ at work.
> (...) realized (with the help of some people on the D discord) that the garbage collector is fine for my needs.
Do you envision linking in a garbage collector in your eventual c++ rewrite?
dfawcus
I've been playing with it hacking a compiler written in C++ to be sort of transliterated to D. Just to see if it then makes the compiler easier to read, while not worrying about the performance yet.
So far in converting the lexer it does make it more comprehensible, it will probably do the same for the parser and AST. The real interesting bit will be once I tackle the later stages.
null
flohofwoe
C99 ;) ...compared to 'popular C' (which is essentially C89 plus some common extensions taken from early C++) C99's main improvements (designated initialization and compound literals) haven't really caught on yet even among many C programmers, but those features (IMHO) completely revolutionize the language, and especially library API design.
Also on a more serious note: I started some projects in Zig and even though most of my future projects will be built on a bedrock of C code, more and more of the top-level layers will happen in Zig.
codr7
There it is again, the urge to port my Lisp back to C.
What I love most about C is the fact that it doesn't talk down to me no matter what crazy ideas I come up with. It's therapeutic for me, reminds me why I started writing code in the first place.
I realize that's also what many hate about it, the fact that it gives other people freedoms they would never trust themselves with.
dfawcus
Designated initialisers and compound literals, sure they have caught on, one just has to know where to look:
https://github.com/danos/vyatta-dataplane/blob/master/src/npf/config/gpc_hw.c#L600-L623
https://github.com/danos/vyatta-dataplane/blob/master/src/npf/config/npf_rule_group.c#L252-L280
That is code which is around 4 years old.For the latter example, one could theoretically avoid declaring the variables 'event' an 'rg_match', instead direcly including the compound literals in the respective function calls. However it is a question of taste, and what is more readable.
(The above have designated initialisers, I'm can't remember if there are any compound literal examples there.
There is however one here, when the BSTR_K macro is also expanded, also the earlier BSTR_INIT:
https://github.com/danos/vyatta-dataplane/blob/master/src/npf/bstr.h#L199
cassepipe
I remember reading this some time ago : https://floooh.github.io/2019/09/27/modern-c-for-cpp-peeps.h...
I do use those so thank you :)
gw2
C#. While a popular language, it is criminally overlooked for high-performance programming. Obviously, you can't use it for embedded or kernel development. For other use cases though, it can almost reach the performance of C/C++/Rust when written with proper care.
Const-me
> Obviously, you can't use it for embedded
Embedded is diverse. I would not use .NET for small embedded, i.e. stuff running on Arduino or ESP32.
However, I have successfully used .NET runtime in production for embedded software running on top of more performant SoCs, like 4 ARMv7 cores, couple GB RAM, Linux kernel. The software still has large pieces written in C and C++ (e.g. NanoVG rendering library) but all higher-level stuff like networking, file handling, and GUI are in memory-safe C#.
graboid
I sometimes write C# in my day job. But I think I don't know much about how to write really fast C#. Do you have any recommendations for learning resources on that topic?
gw2
Sure. Here are some resources:
* Span<T>: https://learn.microsoft.com/en-us/archive/msdn-magazine/2018...
* C# now has a limited borrow checker-like mechanism to safely handle local references: https://em-tg.github.io/csborrow/
* Here is a series of articles on the topic: https://www.stevejgordon.co.uk/writing-high-performance-csha...
* In general, avoid enterprise style C# (ie., lots of class and design patterns) and features like LINQ which allocate a lot of temporaries.
neonsunset
LINQ is fine (but enterprise style never is, yes), it’s a matter of scale and what kind of a domain the code is targeted too. C# needs to be approached a little like C++ and Rust in this regard. Having standard performance optimization knowledge helps greatly.
Also can recommend reading all the performance improvements blog posts by Stephen Toub as well as learning to understand disassembly at a basic level which .NET offers a few convenient tools to get access to.
graboid
Thank you. I once read a bit about Span<T>, but some of this reference stuff is very new to me. Interesting, definitely. C# really is a big language nowadays...
xigoi
C# is specifically designed for enterprise-style OOP, so if you want to avoid that, why use C# at all?
CrimsonCape
Span<T>, ReadOnlySpan<T>, Memory<T>, CollectionsMarshal, CollectionsExtensions, ref struct, ref return, ArrayPool, ArraySegment, ValueTuple, and using interfaces/structs/generics carefully.
That is if you don't want to get into unsafe code.
HackerThemAll
A few important ones: - Avoid memory allocations as much as you can. That's a primary thing. For example, case insensitive string comparisons using "a.ToUpper() == b.ToUpper()" in a tight loop are a performance disaster, when "string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase)" is readily available. - Do not use string concatenation (which allocates), instead prefer StringBuilder, - Generally remember than any string operation (such as extracting a substring) means allocation of a new string. Instead use methods that return Span over the original string, in case of mystr.Substring(4,6) it can be a.AsSpan(4,6), - Beware of some combinations of Linq methods, such as "collection.Where(condition).First()" is faster than "collection.First(condition)" etc.
Apart from that (which simply concerns strings, as they're the great source of performance issues, all generic best practices, applicable to any language, should be followed.
There are plenty resources on the net, just search for it.
Rohansi
You actually can use it for embedded and kernel development! See .NET Nano Framework [1] for embedded - works on microcontrollers like ESP32. For kernel development there's nothing really built in to support it but people have built tools [2] to do it.
sterlind
Pour one out for Midori, which would have replaced Windows with a capability-based OS completely written from kernel to shell in a C# dialect. Async/await, spans, and immutable support came from it, along with an (opt-in) Rust-like borrow checker. Satya canceled it, and all the work was lost to history. Singularity was the early public prototype.
pjmlp
The only thing Singularity and Midori share is the idea.
You should also pour one out for Longhorn, where internal politics tanked the idea, and eventually Windows team redid all those .NET based ideas into COM/C++, and were even proud of doing so (see Hilo sample documentation), hence why nowadays COM based libraries are the main way to expose modern Windows APIs (aka post Windows XP).
Had they collaborated instead, probably Windows would be closer to something like Android userspace nowadays.
Or for Ironclad, another one from Microsoft research, lesser known, also from the same research group, which even includes type safe Assembly,
https://www.microsoft.com/en-us/research/publication/safe-to...
Microsoft Research has plenty of work in such domains, they also had a LLVM like compiler framework, based on MSIL, called Phoenix, among other stuff, e.g. Dafny, FStar, Drawbridge, also come from OS projects.
Unfortunely classical Microsoft management has been more like it isn't Windows, it isn't shipping.
bunderbunder
And arguably it beats the performance of C/C++/Rust when written without proper care: https://blog.codinghorror.com/on-managed-code-performance-ag...
The big take-away I got from this (admittedly quite old now) experiment is that getting advertised performance out of unmanaged languages for typical real-world (i.e., non-benchmark) tasks often requires a lot more care than people really account for. Nowadays memory dominates performance more so than CPU, and the combination of a JIT compiler and a good generational, compacting garbage collector - like C# and Java developers typically enjoy - often does a better job of turning idiomatic, non-hand-optimized code into something that minimizes walks of shame to the RAM chips.
codr7
Well in that case, Java :)
I've been having a lot of fun with Java lately, the maturity of the language/implementation and libraries allows me to focus on the actual problem I'm solving in ways no other language can currently match.
https://github.com/codr7/tyred-java https://github.com/codr7/eli-java
andreer
[dead]
Froedlich
The only true "system programming" I've done was in Microsoft Macro Assembler, a product I grew to hate with a passion.
A non-answer, but tangentially relevant:
I once fiddled with Forth, but never actually accomplished anything with it.
Several OSs are written in Lisp; in some of them the difference between OS and application is a bit vague. At the time none of them were available to me to play with.
I discovered Oberon and fell in love. My first real programming language was Pascal, and Oberon is part of the same family. Oberon consisted of a compiler, operating system, user interface, application software, and tools, all self-hosted on Oberon. There was even an Oberon CPU at one time. But Oberon turned out to be just an academic curiosity, and wasn't available for any hardware I had access to anyway.
Rochus
Have a look at https://github.com/rochus-keller/Oberon which runs on different operating systems and architectures. You can even generate platform-independent C which I e.g. used to port the Oberon System 3 (https://github.com/rochus-keller/OberonSystem3).
Snuggly73
"Microsoft Macro Assembler, a product I grew to hate with a passion."
Turbo Assembler FTW :)
lallysingh
MASM was always horrible.
nasm has been lovely, but I haven't used in 10+ years. https://github.com/netwide-assembler/nasm
2mlWQbCK
Why all this MASM hate?
I barely ever used it, but I noticed that MASM 5.1 is included (together with MSC 5.1 and various other Microsoft tools from 1988) in Microsoft's MIT-licensed MS-DOS repo. Trying some hello world level examples there was nothing obviously annoying about it so far.
https://github.com/microsoft/MS-DOS/tree/main/v4.0/src/TOOLS
gibsonf1
We have had a great experience using Common Lisp [1] for our causal space-time systems digital twin [2]
[1] http://sbcl.org/
codr7
I so envy people who manage to find interesting Common Lisp work, it's like we live in different dimensions.
wglb
There are many independent consultants working in Lisp.
Yes, it is rare.
zelphirkalt
Requires open minded middle management and that is rare.
felideon
or the CEO of Franz, Inc. as an advisor, it seems.
lopatin
I started using Idris a few years ago because the idea is fascinating. Such as state machines in your type system, the size of a list being defined in the static type system, even if the list size changes over time (pretty mind blowing), etc..
But ultimately I realized that I’m not writing the type of software which requires such strict verification. If I was writing an internet protocol or something like that, I may reach for it again.
TOGoS
Similar boat. I've read about Idris (and been 'shown the door' enough times) and I love the idea of it, but sadly I haven't yet had any reason to use it.
Less popular or less commonly used ones.
By that, I mean, not including the usual suspects, such as C, C++, Rust and Go (I know the controversy about the last one being a systems programming language or not).
I'm asking this because I used C for both application programming and systems programming, early in my career, before I moved to using other languages such as Java and Python.
And of late, I've been wanting to get back to doing some systems programming, but preferably in a more modern language (than C) which is meant for that.