News for hackers. Stuff that matters.
Re:Why Tracebit is written in C# by lordofgibbons on Friday January 31, 2025 @09:56PM (#42895214)
How does it compare with Kotlin for backend development, which inherits all of the JVM ecosystem?
Re:Why Tracebit is written in C# by caspper69 on Friday January 31, 2025 @10:11PM (#42895290)
There's a lot of banter as to which JIT environment is more performant.

As a big C# proponent, my gut tells me the JVM probably has the edge here, but it's not a clean sweep. The CLR has areas where it excels. I would also freely admit that the Java ecosystem is far larger and more mature. The NuGet ecosystem is no slouch, however.

But if I were a gambling man, I would bet that AOT compilation will become much more widespread in the .NET ecosystem while Oracle will ensure that you have to pay the piper for GraalVM to do anything interesting. Call it a hunch.

Re:Why Tracebit is written in C# by lordofgibbons on Friday January 31, 2025 @10:27PM (#42895366)
Thanks for the response. I mean from a productivity point of view when building real-world applications.

For example, in Go, the development productivity is great, but I'm not so sure about feature development velocity. There are a ton of HTTP libraries, but it's a barren wasteland when it comes to Auth solutions and you have to rely on a separate service which unnecessarily complicates the infrastructure. Need to quickly put together an application that supports enterprise OAuth? tough luck

Re:Why Tracebit is written in C# by caspper69 on Friday January 31, 2025 @10:42PM (#42895444)
Asp.Net supports both internal & external auth(n|z) providers.

I have to admit that I haven't done much with the interweb side. Truth be told, the few times I've used Asp.Net, I used KeyCloak as the authentication provider, and that's Java-based, lol.

That being said (and damn you for making me link to ms docs yet another time today), there is a built in provider, but my recollection is it did not support OAuth2 or JWT: https://learn.microsoft.com/en-us/aspnet/core/security/?view...

It may not suit your needs, but maybe that high-level doc can help you drill down quickly and not waste too much time on it.

I will say that I do always find it amazing how large sites can be sucessfully operated without too much fuss on the platform. Stack Overflow was notorious for being a very high traffic site that ran on a small cluster of machines and was all done in Asp.Net (might have been the old Windows framework, however).

I would like to add that I've been working with Entity Framework (EFCore) for the past year, and I've found it to provide velocity on that front. Never was a big ORM fan, but I can definitely see the use cases now.

Re:Why Tracebit is written in C# by cyberax on Friday January 31, 2025 @11:40PM (#42895693)
> Need to quickly put together an application that supports enterprise OAuth?

????

That's super easy. I added support for Clerk's OAuth to our app in literally 10 minutes. It was as easy as:

> token, err := jwt.ParseString(sessionToken, jwt.WithKeySet(r.keySet), jwt.WithAudience(r.audience))

JWT is from `github.com/lestrrat-go/jwx`

I'm not sure about SAML, but at this point it's probably best to not even touch it.

Re:Why Tracebit is written in C# by lordofgibbons on Saturday February 01, 2025 @12:55AM (#42896052)
I'm complaining about having to use external services to do auth, and your solution is to use external services lol
Re:Why Tracebit is written in C# by cyberax on Saturday February 01, 2025 @12:55PM (#42900389)
You can do Google/Microsoft/Apple OAuth is pretty much the same amount of code. E.g.: https://github.com/pgrok/pgrok/blob/dda32d9accfb46ab41f59cae...

What else do you need?

Re:Why Tracebit is written in C# by neonsunset on Saturday February 01, 2025 @12:40AM (#42895989)
OpenJDK used to offer a better baseline performance, particularly at very abstraction-heavy enterprise code. .NET has closed the gap with it since then. Nowadays, .NET can also have quite a Go-like memory profile, especially if you use NativeAOT, but has much higher GC throughput which offers a more foolproof set of tradeoffs. Go has a nice specialized GC design but you cannot tune it at all, and it is centered around moderate allocation rates and consistent latency with small memory footprint. The moment you step outside its boundaries it has problematic regressions .NET's GC implementation is robust against. Java GC implementations are even stronger, but Java also has much higher allocation traffic which offsets some of them.

Where .NET shines is by providing a performance ceiling completely unmatched by neither Java nor Go nor any other GC-based language. Performance ceiling in .NET sits every so slightly below Rust and C, in often an indistinguishable way. It is a very nice experience to write systems code in. It won't give you the same safety for writing concurrent code Rust does, but it is so much more productive than dealing with C or C++, especially when it comes to portable builds and tooling. Of course, it supports only a tiny fraction of platforms compared to C. But your target is more likely to be a server or a consumer device or a comparatively beefy Raspberry PI, and .NET works really well on all of those.

Re:Why Tracebit is written in C# by Capricorn2481 on Sunday February 02, 2025 @12:01AM (#42905990)
> Where .NET shines is by providing a performance ceiling completely unmatched by neither Java nor Go nor any other GC-based language

How does it do this, exactly? What does .NET have that is better than Java for performant code?

Re:Why Tracebit is written in C# by neonsunset on Sunday February 02, 2025 @04:00AM (#42907305)
> What does .NET have that is better than Java for performant code?

CIL bytecode, besides what JVM bytecode exposes, provides much lower level access. As a result, C# and Java are languages of different categories and weight classes completely as of 2025. C# is a proper systems programming language in all the ways Java is not. JVM bytecode is also a more difficult to optimize target because all calls are virtual by default and type information is erased. OpenJDK HotSpot has to perform a lot of work just to get to the baseline where CIL starts at, where you have to explicitly make a call virtual and where type information propagates through generic type arguments. OpenJDK used to have a much more powerful compiler but .NET has closed the gap in almost every area, and in other it has surpassed it, or will surpass in the upcoming release(s). It also has a world of optimizations for structs and struct generics which are monomorphized like in Rust, something OpenJDK might only get to in the future. As I said in my previous comment, performance ceiling of .NET is at approximately the level of C/C++/Rust/Zig. Somewhat lower due to compiler limitations but the gap is small enough for it to be easily competitive.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/... is a good demonstration of performance difference in optimized code in these two languages (note that on <1s execution time benchmarks the startup impact also works against both, so you could look at the comparison between C# AOT and Go to get another picture)

Re:Why Tracebit is written in C# by igouy on Sunday February 02, 2025 @11:20AM (#42909577)
> on <1s execution time benchmarks the startup impact also works against both

That would be 5 measurements out of 100?

With the tiny tiny benchmarks game programs startup and warmup and shutdown costs must effect measurements longer than 1s -- but less so.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Re:Why Tracebit is written in C# by neonsunset on Sunday February 02, 2025 @02:51PM (#42911200)
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Here reverse-complement and spectral-norm have >25% difference. When you look at the main comparison table for either, it might seem that C# lags behind natively compiled languages, but if you look at the NAOT numbers - it is right there next to them.

So I'm putting a disclaimer because of it.

Re:Why Tracebit is written in C# by igouy on Sunday February 02, 2025 @04:36PM (#42912093)
Will the real C# stand-up please.
Re:Why Tracebit is written in C# by igouy on Tuesday February 04, 2025 @07:35PM (#42941617)
Re:Why Tracebit is written in C# by waqar144 on Sunday February 02, 2025 @01:32PM (#42910601)
> performance ceiling of .NET is at approximately the level of C/C++/Rust/Zig

Not really. You don't have the same level of control over memory in managed languages

Re:Why Tracebit is written in C# by neonsunset on Sunday February 02, 2025 @02:46PM (#42911165)
You've never actually verified this claim, have you? Next time - please do it.

- structs, with auto, sequential and explicit layout, with complex SROA and promotion handling

- stack-allocated buffers, unsafe fixed and inline arrays, even managed objects can have their layout configured

- monomorphized struct generics compiled the same way they do in Rust

- raw and byref pointers with pointer arithmetic

- portable and platform-specific SIMD, platform-specific intrinsics

- zero-cost interop which enables calls into malloc/free at the cost of C/C++ (you do not actually need this - there is a managed reimplementation of mimalloc which is fully competitive with the original)

- static linking with native dependencies when using nativeaot

Re:Why Tracebit is written in C# by waqar144 on Monday February 03, 2025 @01:30AM (#42915546)
In C, I can just write the whole program without calling malloc. I write my own allocator tuned for my programs behavior, I even have multiple allocators if needed. I just have a lot more control available. If you can't do this in a language, you can't claim its performance is close to C. Performance is about control.
Re:Why Tracebit is written in C# by neonsunset on Monday February 03, 2025 @04:49AM (#42916602)
It's as if you didn't bother reading my previous comment. Incredible.
Re:Why Tracebit is written in C# by waqar144 on Monday February 03, 2025 @09:56AM (#42918775)
You keep ignoring the point. Show me how can I write a program in C# that works with a fixed size memory region, lets say 512KB. It should not do any dynamic memory allocation.

Here's a library that does this in C in case you are wondering: https://github.com/rxi/microui.

Re:Why Tracebit is written in C# by neonsunset on Monday February 03, 2025 @10:19AM (#42919023)
Sigh.

  // Please, just allocate a normal array instead, there is no benefit to this if it lives throughout the whole application lifetime
  var bytes = (stackalloc byte[512 * 1024]);

  // or, but, please, at least use a span instead of C nonsense of tracking offsets by hand
  // it's not 1980 anymore
  var ptr = stackalloc byte[512 * 1024]; // byte*

  // or
  [InlineArray(256 * 1024)]
  struct CommandList { byte _; }

  var commands = new CommandList();

  // or
  unsafe struct State
  {
    public fixed byte CommandList[256 * 1024];
  }
Whichever you like the most, they do have somewhat different implications - stackalloc is C alloca while struct-based definitions have the exact same meaning as in C.

To avoid running into stack space limitations, you can place a fixed buffer or any of these large arrays into a static field. It gets a fixed static offset in the memory.

C# goes much further and also provides zero-cost abstractions via struct generics with interface constraints. Or without - you can also apply pattern matching against a generic T struct and it will be zero-cost and evaluated at compilation (be it with RyuJIT or ILC (IL AOT Compiler)).

Re:Why Tracebit is written in C# by waqar144 on Monday February 03, 2025 @02:34PM (#42921890)
Nice, thanks a lot for sharing the knowledge.
Re:Why Tracebit is written in C# by cyberax on Friday January 31, 2025 @11:45PM (#42895723)
I still prefer Go, for its first-class lightweight threads. They make _everything_ so much better to debug, compared to async/await that is available in C# and Kotlin.

That being said, Java has recently released Project Loom, but it's poorly integrated and often causes subtle issues. It'll require a couple more years to mature.

C# doesn't have anything like this for now.

Re:Why Tracebit is written in C# by e3bc54b2 on Saturday February 01, 2025 @12:08AM (#42895838)
IIRC C# investigated virtual/green threads, but decided to drop it because of poor interactions with reentrant code from async/await. The fact that C# went all in on async/await when it was the rage has prevented it from adopting a better solution. Java's conservative attitude fares better for such fundamental changes.
Re:Why Tracebit is written in C# by neonsunset on Saturday February 01, 2025 @12:17AM (#42895867)
There is reason async/await got so popular after it was adopted by C# based in the early Async work in F# :)

Stackful coroutines have their pros but they are not a better choice. Rust did not and will not adopt them nor any other serious systems programming language will.

You don’t have to follow noisy style you often see - tasks compose nicely and express deferred operations incredibly well in a way that will not blow up on you in a surprising way.

There is an ongoing Async2 project which will massively reduce task state machine overhead further by only ever paying for it in the code that actually suspends rather than the code that just forwards the calls or doesn’t. It will likely land as preview in .NET 10 and as full release in .NET 11.

Re:Why Tracebit is written in C# by cyberax on Saturday February 01, 2025 @01:28AM (#42896205)
> Stackful coroutines have their pros but they are not a better choice.

Hard disagree. Coroutines are absolutely useless for anything non-trivial, as debugging them becomes a total hell. They are still a callback hell, just with a lot of sugary goo slathered on it.

Coroutines also result in the "colored function" problem, that is fundamental for them.

Meanwhile, Go lightweight threads just work. Debugging is simple, and you don't have to think about spooky actions at a distance from event loops that dispatch coroutines.

Re:Why Tracebit is written in C# by neonsunset on Saturday February 01, 2025 @03:41AM (#42896885)
Please re-read my reply. Goroutines are stackful coroutines.
Re:Why Tracebit is written in C# by namtab00 on Saturday February 01, 2025 @06:27AM (#42897594)
I only know C#'s async/await, and know nothing about goroutines / virtual or green threads.

You seem knowledgeable on the matter, care to share some resources that might help me grok the differences?

Re:Why Tracebit is written in C# by neonsunset on Saturday February 01, 2025 @12:07AM (#42895834)
Completely wrong. Go is worse at _lightweight_ concurrency because each Goroutines is much costlier than each .NET task. Also Go has rather poor concurrency semantics comparatively speaking because Goroutines cannot yield a value - you have to spawn a channel on top of spawning a Goroutines or you need to use a wait group or similar. .NET offers far better experience for concurrency-centric code at much lower overhead for code that has a light of finely grained concurrent operations.

https://hez2010.github.io/async-runtimes-benchmarks-2024/tak...

Re:Why Tracebit is written in C# by cyberax on Saturday February 01, 2025 @12:51PM (#42900341)
A million tasks results in 2.5G memory spent (for stacks).

This overhead is indeed real, but it is basically immaterial. If you're using that many goroutines, you are going to be CPU-bound unless it's a very special type of workload like a WebSocket dispatcher.

In return, you get _normal_ stack traces, and a normal debugging experience. Not a callback hell of async/await. Also no "colored functions" nonsense.

Coroutines make sense only for something small and trivial, like the classic tree iterator. And Go now has that: https://go.dev/blog/range-functions

Re:Why Tracebit is written in C# by neonsunset on Saturday February 01, 2025 @04:05PM (#42902323)
> In return, you get _normal_ stack traces, and a normal debugging experience.

Whatever language you have in mind, it isn't C#. Because all those work perfectly fine there. Please also do a cursory read of what coroutines (stackful vs stackless) in the context of concurrency are. And in Go, all functions are colored, often in ambiguous way due to poor culture of not passing the context where it matters, and goroutines panicking in dependencies that cause uncatchable application crashes. Never change, Go community.

Re:Why Tracebit is written in C# by orthoxerox on Saturday February 01, 2025 @04:47AM (#42897209)
They are very close. The biggest issue with Kotlin is that it has to keep up with Java language changes. It used to be a "strictly better Java", promising zero-friction migrations, but whenever Java adds a new language feature Kotlin has to accommodate it or it will no longer be able to "inherit all of the JVM ecosystem".

It's the same with F#. F# used to be ahead of C#, but now every time there's a new C# language feature it's F# that has to adjust or deal with friction in some other way. Discriminated unions are the next big thing that will require F# to put up with C#.