News for hackers. Stuff that matters.
Re:.NET 5.0 by lwansbrough on Tuesday November 10, 2020 @12:07PM (#25048211)
Authentication is in the request pipeline, so it makes sense that it's async if you're talking to some sort of storage engine. We're using the async APIs to pull user/client app information from our database. Why would we want that to be synchronous?
Re:.NET 5.0 by jniedrauer on Tuesday November 10, 2020 @01:52PM (#25049655)
> Why would we want that to be synchronous?

Authentication is blocked by accessing storage. You cannot proceed until the storage read operation is completed. There is no parallel work to be accomplished here. This isn't UI code. There's no event loop. Why would you want this to be asynchronous? This seems like async as a dogma, rather than as a tool to accomplish something specific.

Re:.NET 5.0 by manigandham on Tuesday November 10, 2020 @02:40PM (#25050679)
Async means non-blocking, not parallel. It helps keep the app responsive while using less resources and avoiding lockups and crashes.

.NET is used by millions of developers. Strong and scalable foundations matter, and performance is an explicit goal with asp.net being one of the fastest web frameworks. Async is a core part of this.

There's very little - if any - overhead that you need to worry about with async code from the language to Visual Studio.

Re:.NET 5.0 by merb on Tuesday November 10, 2020 @03:26PM (#25051424)
> It helps keep the app responsive while using less resources and avoiding lockups and crashes.

it actually uses more resources. async has a cost, but it is really low.

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @04:39PM (#25052338)
There is a resource tradeoff. async/await has a minor CPU/memory impact, but it can also free up threads to do other work during an I/O bound operation.

Threads have their own resource cost.

Re:.NET 5.0 by nullsense on Tuesday November 10, 2020 @02:33PM (#25050562)
>You cannot proceed until the storage read operation is completed.

Exactly. So when you await it, that thread that would have but blocked waiting for the I/O instead can be used to service other requests until the I/O has finished.

Re:.NET 5.0 by ko27 on Tuesday November 10, 2020 @02:45PM (#25050772)
Async is not used just to enable parallel execution. Using 1 thread per every long running request is a good way to bottleneck your web server.
Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @03:20PM (#25051327)
> There is no parallel work to be accomplished here.

Concurrency is not parallelism [1].

[1]: https://blog.golang.org/waza-talk

Re:.NET 5.0 by jniedrauer on Tuesday November 10, 2020 @04:17PM (#25052054)
Each HTTP request in a Go webserver spawns a goroutine, and there is no need to think about "freeing up threads" since coroutines are not OS threads. There's also no need to leak the word `async` all over your codebase. The problem being solved here with async/await is also being caused by async/await.
Re:.NET 5.0 by oaiey on Tuesday November 10, 2020 @05:47PM (#25053127)
Goroutine like .NET IAwaitable/Task both abstract the thread away. No one thinks about threads when programming async/await code despite in any await keyword a thread change can happen.

Both solve the same problem with the same technique (under the hood it is all the same). One language had the benefit of late birth (go), the other suffers with its friends through a library/language migration (C#, C++, Java, JavaScript, Python, ...). async/await is effectively the modernization of structural programming to benefit from modern concurrency.

Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @09:49PM (#25055014)
Worth noting that "late birth" is not the only thing at play here - Rust _had_ green threads at one point and removed them - only to add async/await later.
Re:.NET 5.0 by WorldMaker on Wednesday November 11, 2020 @12:38PM (#25060582)
async/await has underpinnings in monadic computation expressions (via F#/Haskell). There are some benefits to the model, despite a lot of its detractors in the thread here. Such as it is possible to work with multiple monads (many languages that support async/await are not strict about which monad they rewrite for; C# supports any Monad that has a GetAwaiter() method of the right shape, JS supports any object with a then() and/or catch() of the right shape, etc).

While async/await is nowhere structurally as capable/composable as for instance Haskell's do notation, it's still more composable than a lot of alternatives and a lot of manual thread management techniques.

The biggest thing though is that these concerns are orthogonal. You can have green threads backing an async/await monad (with some caveats), but you can't as easily swap in anything that follows monad rules into code written specifically just for green threads. (Python makes you explicitly define your threading model before using async/await; the others provide methods to configure it.)

Which is to say "late birth" isn't really a consideration in async/await, it's as much a consideration of flexibility/composition of abstractions. JS, for example, needed that flexibility/composition in the wild west of multiple disparate Promise implementations early on, and may need it again if/when Browsers ever decide to support proper multi-threading whether it is green threads or something else. In such a future you should still be able to compose existing async/await code without modifying it, even as you take advantage of newer threading options.

Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @09:52PM (#25055029)
The issue is that Go simply does not allow large classes of system which require direct and unfettered access to the operating system primitives to be built.

I'm a huge fan of Go, but pretending the two systems are equivalent either is either disingenuous or belies misunderstanding.

Re:.NET 5.0 by MarkSweep on Tuesday November 10, 2020 @11:13PM (#25055444)
There is sort of an event loop: the .NET Threadpool. It is used by async by default. It will by default quickly create an number of threads equal to the number of CPU cores, but then slowly increase it beyond that. If you are blocking in a threadpool thread, the work item queue will back up. This is called threadpool starvation.

Some articles:

https://docs.microsoft.com/en-us/archive/blogs/vancem/diagno...

https://github.com/Microsoft/vs-threading/blob/master/doc/th...

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @02:22PM (#25050364)
Awaiting a storage operation (ie. look up user) in C# will allow other calls to proceed until the I/O is available to read.

Synchronous code locks you into the model of handling one request per thread.

Given the minor overhead (both cognitive and runtime) of a sync/await, I can’t see why you wouldn’t want to do it here.

Re:.NET 5.0 by balfirevic on Tuesday November 10, 2020 @02:31PM (#25050515)
Because async/await infects everything it touches and forces me to spread irrelevant junk words all over the code which have nothing to do with the task I'm trying to accomplish.
Re:.NET 5.0 by hackerfromthefu on Tuesday November 10, 2020 @08:17PM (#25054451)
What about the far worse stack traces and debugging?

Whats a way to get the utility of normal debugging while using async?

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @08:31PM (#25054565)
Stack traces were massively improved in 2.1.

Using a good IDE (Rider or Visual Studio), debugging async/await code works as expected.

Are you doing interop or calling unmanaged code?

Re:.NET 5.0 by hackerfromthefu on Wednesday November 11, 2020 @04:44AM (#25056981)
Thanks, I will make sure to check this out. Does anyone have any articles or documentation on this?
Re:.NET 5.0 by benaadams on Wednesday November 11, 2020 @08:17PM (#25065216)
Stacktrace improvements in .NET Core 2.1: Intelligible stack traces for async, iterators and Dictionary (key not found)

https://www.ageofascent.com/2018/01/26/stack-trace-for-excep...

Re:.NET 5.0 by hackerfromthefu on Tuesday November 17, 2020 @05:59AM (#25122282)
Awesome! Thank you. Wonderful to see these open source contributions to .NET.
Re:.NET 5.0 by mmis1000 on Tuesday November 10, 2020 @12:17PM (#25048351)
For simplicity? Just like how js get async await thing eventually.
Re:.NET 5.0 by buraktamturk on Tuesday November 10, 2020 @12:31PM (#25048515)
async/await is the first class citizen .NET and C#. You just mark your function as async and return Task<OriginalReturnValue> and you can call any async function with await, just like js.
Re:.NET 5.0 by hackerfromthefu on Tuesday November 10, 2020 @08:32PM (#25054568)
That's a factual definition of how to use the first step of async, however it's missing the point.

Async makes your code do significantly more complex thnigs, and while the compiler makes the easy stuff easy, the underlaying complexity hasn't gone away it's just been abstracted, and somewhat leakily.

You can't do 'just' what you said, you also have to deal with of boundary conditions that don't exist in non-async code, plus if you want to understand what your code is doing you now need to keep two mental models of program execution in your mind.

For an introduction to the complexity of async, and practical considerations you need to manage to use it well this official documentation is a place to start - and note the article is pretty long, async does have a lot of additional complexity.

https://docs.microsoft.com/en-us/archive/msdn-magazine/2011/...

Btw I'm not saying don't use Async. Async is an incredibly powerful and valuable tool. But it has costs and those are weighted toward downstream in the software lifecycle and you should be aware of them when deciding which situations that tool is appropriate in.

Yes async is a first class citizen in .NET and thats emphasised by the framework libraries using it everywhere. But they are writing a framework to be consumed widely by users of differing requirements so they have real reasons to support the widest possible use with highest possible performance. Most application code doesn't really have those needs.

Using async should be considered as a tool to reach for (when appropriate) not a default for every situation because it has significant costs through the lifecycle of the system.

Re:.NET 5.0 by ClumsyPilot on Tuesday November 10, 2020 @12:54PM (#25048808)
I fail to see how this is sensible in the slightest - you then have to re-write the code if you want the application to scale. Otherwise you are wasting memory, trashing GC, spawning all these extra threads.All awaitable operations like network requests, disk reads, etc, should be async. Why would you write potato code?
Re:.NET 5.0 by nullsense on Tuesday November 10, 2020 @02:36PM (#25050620)
>Why would you write potato code?

Side note: this gave me a good laugh. I just pictured it being used as a sign off on PR reviews.

Is it a technical term? If it's not I think it should be, and if it is I want to know what the exact nature of potato code is, so I can call it out when I see it in the wild.

Re:.NET 5.0 by Scarbutt on Tuesday November 10, 2020 @09:53PM (#25055036)
you then have to re-write the code if you want the application to scale.

Scaling machines (VMs, containers) is a solved problem and very easy to do today.

Re:.NET 5.0 by withinboredom on Tuesday November 10, 2020 @12:21PM (#25048407)
So you want to pause the thread and keep it from processing other requests for simplicity?
Re:.NET 5.0 by CodesInChaos on Tuesday November 10, 2020 @12:46PM (#25048713)
Unless you have a lot of concurrent connections (C10k problem), having one thread per active request isn't a big deal. For my web applications, requests spend most of their time waiting on the database, and an open transaction is at least as expensive as a thread in an app server for many databases. So I agree that for most applications async isn't worth the complexity they introduce. In many implementations they also mess up your stacktraces, which makes debugging production issues harder.
Re:.NET 5.0 by manigandham on Tuesday November 10, 2020 @02:37PM (#25050643)
.NET has millions of developers. They optimize for the greatest impact and async is necessary for performance. In fact high-performance is an explicit goal of the framework and it ranks at the top of the TechEmpower benchmarks.

Even if you don't need the performance, async code helps keep your app responsive and use less resources on your server. It's far better to have async and not need it then try to refactor your entire ap when it's necessary.

Re:.NET 5.0 by nullsense on Tuesday November 10, 2020 @02:41PM (#25050701)
The web server uses a threadpool anyway. You're not creating threads that don't already exist. You're simply able to use the threads you do have for other tasks while waiting for I/O.
Re:.NET 5.0 by mmis1000 on Tuesday November 10, 2020 @12:34PM (#25048543)
That is literally how php does. Let's fire a thread for every request and block on db reading or any action that require io. And it seems it works (at least for php)
Re:.NET 5.0 by virgilp on Tuesday November 10, 2020 @12:49PM (#25048750)
.NET is meant for stuff like microservices; you don't see lots of those written in php, right?

Also, for high-traffic websites, that's really not a great idea. You might say "but Facebook, PHP" - I'm really certain that their current codebase doesn't have a thread that blocks on DB for each user request.

Re:.NET 5.0 by zerkten on Tuesday November 10, 2020 @02:18PM (#25050294)
> .NET is meant for stuff like microservices;

What does this mean? .NET has been around before SOA was a term and microservices is an evolution of that. The concepts are orthogonal and you could write microservices in PHP, if you really wanted. Like Java, the .NET runtime and platform is highly efficient. That's what .NET has historically had over PHP/Python/Ruby, but I don't keep up with the PHP and Ruby platforms these days.

I feel like this is another one of those discussions like the "Python GIL problem." Whether it's a really a problem depends on the circumstances, and the circumstances were it is a problem affects fewer people than the HN threads suggest.

Re:.NET 5.0 by int_19h on Tuesday November 10, 2020 @03:33PM (#25051520)
I'm not sure where SOA as a specific term showed up, but the very first release of .NET very much emphasized web services in the docs, presentations etc. Back then, this meant SOAP.
Re:.NET 5.0 by BoorishBears on Tuesday November 10, 2020 @01:26PM (#25049250)
I don't get why the auth being async is a hang up but at the same time, most projects can handle not scaling to Facebook-scale and the sooner developers accept that, the sooner we can escape a great gnashing of teeth.

I'd be willing to bet more projects have been killed by trying to architecture for performance up front than have been killed by being too successful for their own good and keeling over.

If Twitter could make it past the Fail Whale days, I think most of us can too.

Re:.NET 5.0 by virgilp on Tuesday November 10, 2020 @02:12PM (#25050158)
I'd agree if you talk about "most projects". But here we're talking about a platform - you can't fault Microsoft for caring about performance! .NET is absolutely not meant only for small sites, my current employer is heavily invested in .NET and we'd probably be dead (performance-wise) without async. Definitely couldn't run our services with PHP (not without Facebook-like investments), we already outgrew that kind of traffic.
Re:.NET 5.0 by oaiey on Tuesday November 10, 2020 @05:51PM (#25053158)
Until you look who is faster and has more througput. The only way how PHP can do (via swoole and friends) is by adopting non-blocking frameworks. And remember througput * duration = Serverlese costs
Re:.NET 5.0 by jhomedall on Tuesday November 10, 2020 @12:58PM (#25048864)
That's just standard threading, not async/await.