neonsunset
async Task<User> FetchUser(int id, HttpClient http, CancellationToken token)
{
var addr = $"https://api.example.com/users/{id}";
var user = await http.GetFromJsonAsync<User>(addr, token);
return user ?? throw new Exception("User not found");
}NativeAOT's primary goal is reducing memory footprint, binary size, making "run many methods once or rarely" much faster (CLI and GUI applications, serverless functions) and also shipping to targets where JIT is not allowed or undesirable. It can also be used to ship native dynamically or statically (the latter is tricky) linked libraries.
https://em-tg.github.io/csborrow/
> Ownership model for example, would it be possible to enforce practice via some-sort of meta framework?
It should be possible to at least write an analyzer which will be based on IDisposable-ness of types to drive this. Notably, it is not always more efficient to malloc and free versus using GC, and generational moving GCs do not operate on "single" objects allocating and freeing them, no, so you cannot "free" memory either (and it's a good thing - collection is marking of live objects and everything unused can be reclaimed in a single step).
Also the underlying type system and what bytecode allows is quite a bit more powerful than what C# makes use of, so a third language targeting .NET could also yield a better performance baseline by better utilizing existing (very powerful) runtime implementation.
Lastly, there have been many improvements around devirt and object escape analysis, and GC changes are also a moving target (thanks to Satori GC), so .NET is in quite a good spot and many historical problems were or are in the process of being solved, that make Rust-style memory management less necessary (given in Rust you also make use of it because you want to be able to run your code on bare metal or without GC at all, only relying on host-provided allocator - if you do not have such requirement, you have plenty of more convenient options).
On M4 Max, Go takes 0.982s to run while C# (non-SIMD) and F# are ~0.51s. Changing it to be closer to Go makes the performance worse in a similar manner.
C# is using CoreCLR/NativeAOT. Which does not use GCC or LLVM also. Its compiler is more capable than that of Go.
.NET, unlike Go, has all needed management commands built into its CLI too: dotnet new {template}, dotnet add/remove package, dotnet sln add/remove, etc.
Another example, note how these implementations, one in unsafe C# and another in safe F# have almost identical performance: https://benchmarksgame-team.pages.debian.net/benchmarksgame/..., https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Unless you literally mean awaiting non-awaitable type which...just doesn't make sense in any statically typed language?
These people could not care less about engaging with the subject, they are here because they feel obliged to engage in a moment of hatred of what they think is an enemy tribe.
For those interested as to why: https://news.ycombinator.com/item?id=43396171
A few more arguments while we're at it:
https://dotnet.microsoft.com/en-us/platform/telemetry (Linux leads with 77% of all systems invoking .NET CLI commands)
https://github.com/dotnet/runtime/blob/main/src/libraries/Sy... (first-class epoll/kqueue integration with async, much like the one Go has with goroutines via netpoll)
https://github.com/dotnet/runtime/blob/main/src/coreclr/gc/u... (GC implementation is cgroups-aware, unlike Go)
Have you never worked with any other language which lets you do these?
var say = (string s) => Console.WriteLine(s);
or struct Lease(DateTime expiration)
{
public bool HasExpired => expiration < DateTime.UtcNow;
}
or var num = obj switch
{
"hello" => 42,
1337 => 41,
Lease { HasExpired: false } => 100,
_ => 0
};
You'll see forms of it in practically every (good) modern language. How on Earth is it confusing?Authentication is generally a difficult subject, it is a weaker(-ish) aspect of (otherwise top of the line) ASP.NET Core. But it has exactly zero to do with C#.
Do you have any examples?
This looks like an interesting potential alternative to GxHash. GxHash is nice but sadly I found AES intrinsics to have somewhat high latency on AMD's Zen 2/3 cores, making it a loss on short strings (but until I measured it on our server hw, M4 Max sure had me fooled, it has way better latency despite retiring more AES operations!).
- https://news.ycombinator.com/item?id=43226624
- https://news.ycombinator.com/item?id=43584056
- https://news.ycombinator.com/item?id=36736326
And more. I'm not sure what you found in (checked) exceptions. If you'd like explicit error handling, we have holy grail in the form of Rust which beautifully solves it with implicit returns, error type conversions and disambiguation between error and panic model. I'd prefer to use that one as it actually reduces boilerplate and improves correctness, the opposite to the outcome of using checked exceptions.
For example, Go does not understand cgroups limits and needs an external package to solve this. .NET can read and accommodate those natively. It also ships with excellent epoll-based socket engine implementation. It's on par with Go (although I'm not sure which one is better, but .NET performs really well on high-throughput workloads).
They also tend to be of higher quality and provide better performance.
If you don't want to join on some other virtual thread or goroutine completing immediately (and with Goroutines it's additionally painful since you need to communicate completion separately), it's more difficult and costlier than doing so with tasks/futures.
You are not free from having to worry about it with virtual threads either. If you block a carrier thread with such a low-level API call, the runtime will have a bad time. Or you will always end up paying for a context switch (if you maintain a separate pool of block-able threads).
Green threading UX is better for "regular" code that never bothers to take advantage of concurrency features, but if you do want them, you are quickly back to usually more ceremonious structured concurrency abstractions which, lo and behold, can reimplement the same task system with a worker pool but on top of virtual threads.
If you start to care about cancellation, suddenly you are back to coloring problem regardless. I agree with you that having to write many await's in quick succession is tiresome and unnecessary. It's partially a fault of library authors who name methods "GetSomeLongNameAsync" instead of "Get" or "Query". But other than this it's not as invasive as people make it out to be, and encourages writing highly concurrent code - reducing latency 2x can require moving one or two awaits around. Not so much in Java/Erlang/Go.
https://github.com/dotnet/runtime/blob/main/docs/design/spec...
Mind you, short-lived operations are much cheaper with stackless co-routine model like in C#/F# or Rust than spawning an entire, even if virtual, thread/process.