The problem is in the SqlClient 5.1 version, which is the latest LTS version and therefore the one used by EFCore, it is possible to solve this problem by switching to 5.2
Hi Nick, I always enjoy your videos. Thanks for that. In this case I feel, that some things you say in this video are a bit besides the point. At 2:57 you say one would expect the async-version to be faster than the sync version. I never expected that. in the end, the async version of a call does the same work as the the sync version, but with added complexity. Of course, it should not take almost twice as long as the sync version. So you are right to point out this issue. And I agree, it is a problem that people need to know about, until it hopefully is fixed at some point. But it is not a general issue of async programming. sync and asyn is not primarily about speed. Its not called fast and slow version. Its call sync and async version. And therefore I expect the async version to allow my app to do other things, while the async call is in progress. The sync version will not allow for that. So, if my app needs to stay responsive at all times, I might even accept the much longer runtime in this special case for the added benefit of responsiveness.
True, if you know performance is the number one priority over everything else, then test everything and use the fastest, and sync may often be faster al long as hogging the thread is not a problem. But in this case, if you read this and then do some processing of the read data, async and parallell processing will very very likely beat the sync version. Edge cases should never decide your default solution :)
Async-await is not for performance. It is for scalability. Think: doing something else while the IO is on the way. (Glad you came to that same conclusion in the end - I think you could have given that a little more emphasis).
@@meJevin What he means is that it's not locking down a thread while waiting for the response. It can serve other requests and comes back when it's done, even if it takes longer. However, the memory allocation difference is a big one.
If you have a threaded webserver, you are already scalable. The OS inherently switches threads while waiting on resources. async/await is treated like some kind of magic maguffin that instantly makes your code better, but that is rarely the case. There are only two scenarios where they actually benefit you, and the purpose of both of those scenarios is improve performance, not scalability. 1. Many fetches from the same resource (db/fs/etc) in the same round trip. 2. Event-based model like JS, where the response can be deferred
If someone thinks that an async version of a method should have better performance than a sync one, they simply don't understand how it works and what it's for.
You ask me it is pretty clear to use async always unless you know that for some specific reason sync works better. 99/100 times you are correct choosing async.
This is an edge-case, and usually edge cases are tricky to handle. Depends on the actual problem you're trying to solve. Agree with your conclusion and other people here. I'd design those edge cases with configs to run it sync or async, where it can be toggled on or off anytime.
The best way to learn multithreading is to have student programmers manually multithread applications first, the way it was done in the past. Then you begin to see how many scenarios in which multithreading is unnecessary and could lead to more problems than it solves. For example, if a line of code executes instantaneously (e.g., a simple mathematical calculation) and does not affect the performance of the application, it's not necessary to create an (async await) state machine to handle that operation. For longer running processes or processes that make external calls, like database calls, that could hang-up your current thread, then yes you do want to multi-thread that process. With that said, the async await pattern is still handy and probably overused.
this ^ Async / await is taught as an "always do this!" instead of "here's what's actually happening when you do this". We should get back to teaching the difference between synchronous and asynchronous paradigms before teaching dogmatic async practices.
@@andreikashin You can use async/await without multithreading. But since everything runs in the same thread, that would be lunacy. As someone who remembers when that was introduced and what is was like before that time, the primarily reason async/await was introduced was to manage threads (Tasks) that would otherwise be more difficult to manage. Go learn about it first before you advise others online. This is a waste of my time.
Using async is about to avoid blocking platform threads, of which there are only a handful on the machine where you're application is running, and thus about scalability / level of concurrency, not about making individual method calls faster. Obviously, the call times you measured are primarily determined by the underlying database request, which is the same in both cases, and the async variant will be more complex than the sync variant and there may (and hopefully will) be additional work being done asynchronously by your application in the meanwhile. Which means that it is to be expected that the individual async call will not be faster and probably slower than the individual sync call. But when a single REST-API request of your application runs in a single thread, then using sync database access will limit the number of parallel requests an application service instance can handle to the size of the thread pool of the .NET runtime, which itself is upper bounded by the number of platform threads available on the machine / operating system. There will be no such strict limitation for async database calls and thus no such strict limitation for how many parallel requests you application can handle. Of course, other resources such as memory will still be a limiting factor, but that's a different story.
The title of this video is a bit misleading. (click bait?) It suggests that there are times when you shouldn't use await async, but that's not really the case. The main point is that there is a specific issue with SqlClient version 5.1. in the way they implement the Async methods which are memory intensive. Has nothing to do with general async await, like if someone creates a bad object implementation and you would have a video title "when you shouldnt use Object". no sense.
Ran into this same problem a year ago and found the GitHub issue you are referring to. Changing the slow performing async method to sync solved the issue.
Not sure if this is comparing sync vs async or promoting the new package :( I'd rather have a comparison between DbContext AddAsync and DbContext Add, or when to return the Task and when to return the value in an Async method, those are concepts that can confuse a lot of programmers that do not have enough experience with Async/Await and EF Contexts.
I don’t think there’s anything of note to discuss with AddAsync vs Add. Have you read the documentation remarks for AddAsync? They tell you to not use AddAsync at all except for some niche case that I’ve personally never seen.
As with anything related to performance. You should write it so it is easy to understand and/or consistent with the existing code base. If you are using async everywhere, then keep doing that. Until you run into a perf issue, then run benchmarks and optimize till the performance is satisfactory.
I've run into this issue before when we had some archiving server which was used to bring up historic data for a bimonthly audit. They need 100k records (which is a small dataset for this particular company) with a large variable page size on the SQL server. You could make an optimization like not using varchar(max) as well. But in this instance we did change to synchronous and because the only responsibility of this service is 3 routes which spit out 100k rows the performance benefits of making the CPU run hot for quicker retrieval outweighed the scaling issues associated with not using async await. You could argue that a lot of micro services with a simple retrieval responsibility would be better served in synchronous run time while this big exists
Not much context given to this video. This is not valid for postgresql. Tested it and async await twice of the performance of sync in posgres. Memory allocation is alnost the same. Below is the result: Time taken to fetch data sync: 00:00:04.1417377 ms Total memory used: 2035098592 bytes Retrieved 1000000 records Time taken to fetch data async: 00:00:02.7830356 ms Total memory used: 2035709168 bytes Retrieved 1000000 records
Using StreamWriter (or maybe in general Streams🤷🏻♂), sync is mostly wallclock faster. Most writing is smaller stuff, written directly to the buffer, without the need for flushing or growing. Then the async threading overhead makes it more expensive & slower. Of course there are exceptions, if you write enough for every call, then flushing or growing is needed and async is more scalable. But if you are not thread starved, scalability is probably not an issue (single-threaded job or a large machine)
yeah faced that and ended up doing sync over async. For my use case the difference was tens of seconds for a pretty heavy background job. Sound advice.
There's a video from .Net conf going into detail about this exact issue. If you force it to use the latest Microsoft.Data.SqlClient package it greatly negates the effect of the problem.
Interesting. Question tho, is this specific with EFC+MsSQL? Does this also occur with EFC+Postgres? Etc…. Also what if I use Dapper instead? Does the same issue exists?
It is a problem in the SqlClient library, so unless postgres's client did the same thing (not likely) it won't have the same issue. Yes, this problem affects dapper as well when run over SqlClient.
Not quite the same analogy, but it's like comparing bubble sort to quick sort on a presorted collection. It's not a fair comparison when you only have one initial condition.
We're never affected by some obscure, corner-case issue until we are - and, if you're an IT consultant, you will encounter these cases more often than not.
If you have to manage such huge application, multiple microservices or what not, optimization should be done last and on a separate session. Just make everything that is intuitively resource intensive async, you'll do just fine. However, learn when to call async await though. I've seen too many people just call async await consecutively on something that could have fired in parallel and await or await all.
This is a good example of sub-system optimization. Optimizing a block of code in isolation, without reference to it's impact on the rest of the application.
I totally agree with your last argument, async does scale better. But I also totally agree, they need to fix that memory time etc. For the record, this is only with EFC as you said at 03:16 ? or async await in general?
From my understanding there's a problem specifically in EF. Mainly because of how they buffer the reading of the text, the amount of Task objects spawned, etc.
In fact that's a good thing. If there is an I/O operation going on it doesn't make sense to have a sync version. The ones that exist on the framework is because of backwards compatibility with the APIs before aync and await were introduced. Similarly if an API is not I/O bound then there is no reason to have an async version.
At work it feels like we use async await waaaaay too much. Literally every other method being called is async and I can't help but wonder, when you consider all the state machine code generated in the background, ... if it actually less performant overall. Not to mention all the additional logic and complications you have to consider when things are asynchronous. In a lot of cases, large chunks of code have been refactored to make them async compatible just because one small function at the end of it needs to be await. Its this "thing" that spreads throughout the entire application usually only for a few places where it actually might benefit things.
Good solution design does a lot to limit the "async plague" (in domain layer and in most of application services you shouldn't need async) and also use ValueTask if the code might often not actually run asynchronously.
The real question is why there is a sync version at all. The reason is because of backwards compatibility with older code from the time async and await haven't been introduced yet.
The answer is partly because the language started out without it. But even if async/await had been in C# from the beginning, it still would not be the default. This is because only methods involving I/O should be async, whereas CPU bound work should be sync.
@@jondoty There is no such thing as default. Given two methods one sync and another async you either call one or the other. The compiler doesn't choose for you.
@carlosmunozrodriguez, I agree. I was assuming @SuperLabeled was asking about when declaring a method in C#, not calling one of two sync/async methods. Because as you say, there is no "default" when calling. But sync is the default behavior when declaring a method because it takes extra work to make a method async.
Nice video, I didn't know this bug or feature existed but thankfully i haven't met it yet We have a WinForms + WPF Application and it has been reported that it has gotten slower than it should doing certain operations, do you think ultra is a good fit to see how they compare and perform? Ideally I want to easily find out how much CPU it uses and especially which functions take the most amount of time - or can dotTrace do that?
ask a DBA. The answer is "oh heck, no what is wrong with you what kind of idiot would even think of anything like that crazy madness, begone satan". Or words to that effect. Those guys know DBs, listen to them.
@nickchapsas Please do an update to this which shows the same comparison once you put an explicit dependency at the Top Level on Microsoft.Data.SqlClient v5.2.0+ This was an inefficiency in previous versions. So whilst EF Core by default only brings in v5.1 (the LTS SqlClient) if you explicitely reference a higher version, then EF Core will use that and you can get the performance benefits (or the lack of performance regression in async).
OK, but that's just EF issue, that you wouldn't even have by just not using it XD Also, as a more general comment: I'd like to see comparison with async2 that was supposed to be a runtime solution
Do you understand sync vs async? Async creates a new thread to process the task, sync forces the program to wait for the task to complete async allows the program to wait for it to complete while you can do other tasks.
Thanks for the content, really interesting as usual. The whole sync/async issues still make me wonder, how you would recommend usage in other scenarios than website or -services. In native Desktop clients the need for scaling is less and at least I'm used to explictly assign workloads to different threads. I know there are concepts for async/await here and sure they do work, but I would like to hear your opinion.
I'd say the more general answer would be "do you expect it to scale, be it up or down, at all?". If you DON'T, manually using whatever number of threads you need seems fine. If you do, then the next question would be "how much?". If it's "a little", then probably sticking to manual allocation is fine. If it's "a bit but not too crazy", then maybe a/a is the way. And if it's "a lot, maybe a crazy lot", you need to thread carefully or it might bite you hard depending on circumstances, "how much control do you need and how does the platform behave?". Running the exact same code with happy go lucky Task.Run's on Windows and iOS made next to no difference on Windows and would bog the iPad to a crawl, to the point it would look "frozen", which it wasn't it was having to juggle too much. Cue writing a "parallel executor" with a fixed number of threads, because having a predictable cost was better. No easy answers, it's more of "take an educated guess depending on use case".
Scaling isn't an issue for websites that are already heavily threaded, and async code that is half the perf means it doesn't scale better anyway! Strangely enough UIs are the only place where async offers a benefit: click a buttona nd it fails to respond, you don't block the entire UI if the calls are async.
No one's loading 100k records into memory in one go, bro. Certainly not with the large text included (You'll do that in the single blog UI which has a dedicated endpoint). And this is an issue with EF as you mentioned
Hi, I was looking at bogus and it seems pretty nice at faking data. It is possible though to use the same concept to generate some fake data, then pass as the result it of a mock of a dbContext query?
@@nickchapsas I always heard the technology named as "async await", but I didn't even notice you typed it the other way, and everyone knows what it means, so doesn't matter
@@nickchapsasIdk, it makes more sense to me to call it async-await per the order they come in code. You can declare a function as async and not await anything. Doesn't matter anyway, I refer to NginX as N-Ginx and it drives everyone insane 😈
Hello Nick, The main goal of Async is not blocking the multiple requests. Your test should be something like if you got 100 users, you must need to have async or 1 second processing time could generate a queue of 100 seconds to wait for the user get his 1 second of processing time with 100 users, Async resolves this problem
of course if we talking about some client solution that there is only 1 user and blocking role application when it is processing, it makes sense to have sync
Why should async ever be faster? It will literally always be slower because there's overhead. The point of using async is not to be faster, it's to release the main thread to do something else. This is important e.g. so that the UI doesn't freeze. Of course, you can get a speed up of running multiple threads in parallel using async functions, but it's not clear that this should be happening here at all.
Seems there isnt much conversation about storing large amounts of data in Sql Server just being a bad idea. I can't imagine writing many queries tgat you expect to be fast on a large amount of text in Sql Server. Other types of technology would be better for that type of data. So moral of the story is understand try to understand the trade offs being made when storing various types of data.
it’s was developed so that your thread doesn’t spinlock while waiting for I/O. which is especially important for servers, as few cores can serve many requests with interweaving continuations when they ask for I/O. that way those core will always do work. but: Task is a class and needs allocations. continuations are delegates and need allocations. the async state machine is a class and needs memory (and also lifts locals to fields, which can slow things a bit) having a responsive app is mostly a client thing, and that worked fine with explicit threads. async can interweave between I/O even if you only use a single thread (in theory)
The problem isn't async, the problem is SQL client. Now try with Postgres and it is fast So it's a stupid click bait video and it's a bug that is open for years!
Hi, u took some specific behavior which actually is a bug and on that basis u generalized theory (for sure title of this movie) that we shouldn't use await async. So for clickbait reasons or getting more viewers to your channel it is probably good. I don't buy it because u are focusing on this specific bug. U are not mentioning when really it is good to sacrifice async version for sync version in general - so for me low quality material. U should prepare more examples when sync version really shines over async.
Every multi-step process (e.g. create, replace, update, delete, login, load a file) is naturally thought of as "do step 1, then do step 2, then do step 3" etc. An example might be, "display loading indicator, then send the request, then read the response, then display the data, then remove the loading indicator". NONE of this requires async/await. Async just adds complexity with no performance benefit except when there are thousands of such multi-step processes happening simultaneously on the same machine! Of course there are times where you are forced to use async/await (like in browsers, because they only allow one thread), and times where you might have danger of too many threads, and times when you can get two parts of a multi-step process to happen in parallel. Otherwise, I propose that we NEVER use async/await except for these special situations. Or, perhaps you want to make sure it is more difficult to replace you in your coding job because all your code is unnecessarily complex.
Async/Await is NOT designed to be faster since the code will always wait and then repopulate the stack.. It's designed to not block clients... If you make that call from MVC you WILL see the difference in the UI...
@@ChristianHowell actually it is meant for file reading :) "super large file" doesn't mean anything. Run your tests again with large number of readers on in-memory disks, SSD, fast and slow hard drives, SAN drive. And "Task Parallel was slower" because of the obvious reason: multiple concurrent readers can't read data faster than one data reader from a single data stream.
Me see async me put await
await this comment
The problem is in the SqlClient 5.1 version, which is the latest LTS version and therefore the one used by EFCore, it is possible to solve this problem by switching to 5.2
Can’t believe he didn’t go over the solution, poorly researched video imo
@@flygonfiasco9751 wanted to show this profiler stuff :D
Hi Nick, I always enjoy your videos. Thanks for that. In this case I feel, that some things you say in this video are a bit besides the point. At 2:57 you say one would expect the async-version to be faster than the sync version. I never expected that. in the end, the async version of a call does the same work as the the sync version, but with added complexity. Of course, it should not take almost twice as long as the sync version. So you are right to point out this issue. And I agree, it is a problem that people need to know about, until it hopefully is fixed at some point. But it is not a general issue of async programming. sync and asyn is not primarily about speed. Its not called fast and slow version. Its call sync and async version. And therefore I expect the async version to allow my app to do other things, while the async call is in progress. The sync version will not allow for that. So, if my app needs to stay responsive at all times, I might even accept the much longer runtime in this special case for the added benefit of responsiveness.
True, if you know performance is the number one priority over everything else, then test everything and use the fastest, and sync may often be faster al long as hogging the thread is not a problem.
But in this case, if you read this and then do some processing of the read data, async and parallell processing will very very likely beat the sync version.
Edge cases should never decide your default solution :)
Hi Nick
This is only for SQLServer. Sqlite and postgresql is not affected.
Async-await is not for performance. It is for scalability. Think: doing something else while the IO is on the way.
(Glad you came to that same conclusion in the end - I think you could have given that a little more emphasis).
what?
>not for performance
>gives an example of more efficient resource utilization
bro you good?😂
@@meJevin What he means is that it's not locking down a thread while waiting for the response. It can serve other requests and comes back when it's done, even if it takes longer.
However, the memory allocation difference is a big one.
@@PelFox makes sense 👍
Scalability is a performance :)))???
If you have a threaded webserver, you are already scalable. The OS inherently switches threads while waiting on resources.
async/await is treated like some kind of magic maguffin that instantly makes your code better, but that is rarely the case. There are only two scenarios where they actually benefit you, and the purpose of both of those scenarios is improve performance, not scalability.
1. Many fetches from the same resource (db/fs/etc) in the same round trip.
2. Event-based model like JS, where the response can be deferred
If someone thinks that an async version of a method should have better performance than a sync one, they simply don't understand how it works and what it's for.
Using the Firefox profiler UI to interact with this is very clever
You ask me it is pretty clear to use async always unless you know that for some specific reason sync works better. 99/100 times you are correct choosing async.
Or if nothing else can happen until the call is done, might as well use sync at that point
This is an edge-case, and usually edge cases are tricky to handle. Depends on the actual problem you're trying to solve. Agree with your conclusion and other people here. I'd design those edge cases with configs to run it sync or async, where it can be toggled on or off anytime.
The best way to learn multithreading is to have student programmers manually multithread applications first, the way it was done in the past. Then you begin to see how many scenarios in which multithreading is unnecessary and could lead to more problems than it solves. For example, if a line of code executes instantaneously (e.g., a simple mathematical calculation) and does not affect the performance of the application, it's not necessary to create an (async await) state machine to handle that operation. For longer running processes or processes that make external calls, like database calls, that could hang-up your current thread, then yes you do want to multi-thread that process. With that said, the async await pattern is still handy and probably overused.
this ^
Async / await is taught as an "always do this!" instead of "here's what's actually happening when you do this". We should get back to teaching the difference between synchronous and asynchronous paradigms before teaching dogmatic async practices.
async/await is not about multithreading
@@andreikashin You can use async/await without multithreading. But since everything runs in the same thread, that would be lunacy. As someone who remembers when that was introduced and what is was like before that time, the primarily reason async/await was introduced was to manage threads (Tasks) that would otherwise be more difficult to manage. Go learn about it first before you advise others online. This is a waste of my time.
Using async is about to avoid blocking platform threads, of which there are only a handful on the machine where you're application is running, and thus about scalability / level of concurrency, not about making individual method calls faster. Obviously, the call times you measured are primarily determined by the underlying database request, which is the same in both cases, and the async variant will be more complex than the sync variant and there may (and hopefully will) be additional work being done asynchronously by your application in the meanwhile. Which means that it is to be expected that the individual async call will not be faster and probably slower than the individual sync call. But when a single REST-API request of your application runs in a single thread, then using sync database access will limit the number of parallel requests an application service instance can handle to the size of the thread pool of the .NET runtime, which itself is upper bounded by the number of platform threads available on the machine / operating system. There will be no such strict limitation for async database calls and thus no such strict limitation for how many parallel requests you application can handle. Of course, other resources such as memory will still be a limiting factor, but that's a different story.
Yes, thank you. I don't know why anyone would think that async should somehow be faster.
People really can't grasp the difference between latency and bandwidth.
The title of this video is a bit misleading. (click bait?) It suggests that there are times when you shouldn't use await async, but that's not really the case. The main point is that there is a specific issue with SqlClient version 5.1. in the way they implement the Async methods which are memory intensive. Has nothing to do with general async await, like if someone creates a bad object implementation and you would have a video title "when you shouldnt use Object". no sense.
Danke!
Ran into this same problem a year ago and found the GitHub issue you are referring to. Changing the slow performing async method to sync solved the issue.
Not sure if this is comparing sync vs async or promoting the new package :(
I'd rather have a comparison between DbContext AddAsync and DbContext Add, or when to return the Task and when to return the value in an Async method, those are concepts that can confuse a lot of programmers that do not have enough experience with Async/Await and EF Contexts.
I don’t think there’s anything of note to discuss with AddAsync vs Add. Have you read the documentation remarks for AddAsync? They tell you to not use AddAsync at all except for some niche case that I’ve personally never seen.
@@bass-tones Agreed. The video might not be useful for us, but may be useful for others.
As with anything related to performance. You should write it so it is easy to understand and/or consistent with the existing code base. If you are using async everywhere, then keep doing that. Until you run into a perf issue, then run benchmarks and optimize till the performance is satisfactory.
Ultra tool reminded me the profiler of nvcc - basically a profiler for CUDA runtime functions. Ultra is a really cool one! I agree.
I've run into this issue before when we had some archiving server which was used to bring up historic data for a bimonthly audit. They need 100k records (which is a small dataset for this particular company) with a large variable page size on the SQL server. You could make an optimization like not using varchar(max) as well. But in this instance we did change to synchronous and because the only responsibility of this service is 3 routes which spit out 100k rows the performance benefits of making the CPU run hot for quicker retrieval outweighed the scaling issues associated with not using async await.
You could argue that a lot of micro services with a simple retrieval responsibility would be better served in synchronous run time while this big exists
Not much context given to this video. This is not valid for postgresql. Tested it and async await twice of the performance of sync in posgres. Memory allocation is alnost the same.
Below is the result:
Time taken to fetch data sync: 00:00:04.1417377 ms
Total memory used: 2035098592 bytes
Retrieved 1000000 records
Time taken to fetch data async: 00:00:02.7830356 ms
Total memory used: 2035709168 bytes
Retrieved 1000000 records
Using StreamWriter (or maybe in general Streams🤷🏻♂), sync is mostly wallclock faster.
Most writing is smaller stuff, written directly to the buffer, without the need for flushing or growing.
Then the async threading overhead makes it more expensive & slower.
Of course there are exceptions, if you write enough for every call, then flushing or growing is needed and async is more scalable.
But if you are not thread starved, scalability is probably not an issue (single-threaded job or a large machine)
Example: streaming a lot of CSV rows & columns directly to a HTTP response stream. Mostly smallish string values & single char separators
yeah faced that and ended up doing sync over async. For my use case the difference was tens of seconds for a pretty heavy background job. Sound advice.
There's a video from .Net conf going into detail about this exact issue. If you force it to use the latest Microsoft.Data.SqlClient package it greatly negates the effect of the problem.
Interesting. Question tho, is this specific with EFC+MsSQL? Does this also occur with EFC+Postgres? Etc…. Also what if I use Dapper instead? Does the same issue exists?
It is a problem in the SqlClient library, so unless postgres's client did the same thing (not likely) it won't have the same issue. Yes, this problem affects dapper as well when run over SqlClient.
@ thanks
This memory bug is really a big one and I'm surprised that Microsoft doesn't fixed it for 5 year's. That's crazy
Async is about scalability
Not quite the same analogy, but it's like comparing bubble sort to quick sort on a presorted collection. It's not a fair comparison when you only have one initial condition.
We're never affected by some obscure, corner-case issue until we are - and, if you're an IT consultant, you will encounter these cases more often than not.
If you have to manage such huge application, multiple microservices or what not, optimization should be done last and on a separate session. Just make everything that is intuitively resource intensive async, you'll do just fine. However, learn when to call async await though. I've seen too many people just call async await consecutively on something that could have fired in parallel and await or await all.
Async is very beneficial in webservers and similar situation
This is a good example of sub-system optimization. Optimizing a block of code in isolation, without reference to it's impact on the rest of the application.
I totally agree with your last argument, async does scale better. But I also totally agree, they need to fix that memory time etc. For the record, this is only with EFC as you said at 03:16 ? or async await in general?
Only for EFC. Async/await itself is not at fault for this
From my understanding there's a problem specifically in EF. Mainly because of how they buffer the reading of the text, the amount of Task objects spawned, etc.
It is a problem in the SqlClient library, so it affects EF, Dapper, SqlCommand equally.
I'm a bit annoyed that some libraries do not have sync methods any more.
There is life outside of webApis.
In fact that's a good thing. If there is an I/O operation going on it doesn't make sense to have a sync version. The ones that exist on the framework is because of backwards compatibility with the APIs before aync and await were introduced. Similarly if an API is not I/O bound then there is no reason to have an async version.
There’s nothing stopping you from using async/await in a console or desktop application.
At work it feels like we use async await waaaaay too much. Literally every other method being called is async and I can't help but wonder, when you consider all the state machine code generated in the background, ... if it actually less performant overall. Not to mention all the additional logic and complications you have to consider when things are asynchronous. In a lot of cases, large chunks of code have been refactored to make them async compatible just because one small function at the end of it needs to be await. Its this "thing" that spreads throughout the entire application usually only for a few places where it actually might benefit things.
Good solution design does a lot to limit the "async plague" (in domain layer and in most of application services you shouldn't need async) and also use ValueTask if the code might often not actually run asynchronously.
I once followed a SQ recommendation and replaced sync IDataReader calls with async ones in a heavily-loaded service, had to roll back
I've always been curious, if everyone should use async await, why isn't it the default and we specify when we want synchronous code instead?
The real question is why there is a sync version at all. The reason is because of backwards compatibility with older code from the time async and await haven't been introduced yet.
The answer is partly because the language started out without it. But even if async/await had been in C# from the beginning, it still would not be the default. This is because only methods involving I/O should be async, whereas CPU bound work should be sync.
@@jondoty There is no such thing as default. Given two methods one sync and another async you either call one or the other. The compiler doesn't choose for you.
@carlosmunozrodriguez, I agree. I was assuming @SuperLabeled was asking about when declaring a method in C#, not calling one of two sync/async methods. Because as you say, there is no "default" when calling. But sync is the default behavior when declaring a method because it takes extra work to make a method async.
Nice video, I didn't know this bug or feature existed but thankfully i haven't met it yet
We have a WinForms + WPF Application and it has been reported that it has gotten slower than it should doing certain operations, do you think ultra is a good fit to see how they compare and perform? Ideally I want to easily find out how much CPU it uses and especially which functions take the most amount of time - or can dotTrace do that?
Nice, but I have one question about the documents created in DB - is it a good idea to use Guid in Id field?
ask a DBA. The answer is "oh heck, no what is wrong with you what kind of idiot would even think of anything like that crazy madness, begone satan". Or words to that effect. Those guys know DBs, listen to them.
@nickchapsas Please do an update to this which shows the same comparison once you put an explicit dependency at the Top Level on Microsoft.Data.SqlClient v5.2.0+
This was an inefficiency in previous versions. So whilst EF Core by default only brings in v5.1 (the LTS SqlClient) if you explicitely reference a higher version, then EF Core will use that and you can get the performance benefits (or the lack of performance regression in async).
OK, but that's just EF issue, that you wouldn't even have by just not using it XD
Also, as a more general comment: I'd like to see comparison with async2 that was supposed to be a runtime solution
Oh, interesting, I don't know about this async2, what it is?
@@diadetediotedio6918 youtube keeps removing my comment with github link, just google C# async2
Do you understand sync vs async? Async creates a new thread to process the task, sync forces the program to wait for the task to complete async allows the program to wait for it to complete while you can do other tasks.
No, no creates. It may create - it depends on async scheduler Async is for saving os resources
Thanks for the content, really interesting as usual.
The whole sync/async issues still make me wonder, how you would recommend usage in other scenarios than website or -services. In native Desktop clients the need for scaling is less and at least I'm used to explictly assign workloads to different threads. I know there are concepts for async/await here and sure they do work, but I would like to hear your opinion.
I'd say the more general answer would be "do you expect it to scale, be it up or down, at all?". If you DON'T, manually using whatever number of threads you need seems fine. If you do, then the next question would be "how much?". If it's "a little", then probably sticking to manual allocation is fine. If it's "a bit but not too crazy", then maybe a/a is the way. And if it's "a lot, maybe a crazy lot", you need to thread carefully or it might bite you hard depending on circumstances, "how much control do you need and how does the platform behave?". Running the exact same code with happy go lucky Task.Run's on Windows and iOS made next to no difference on Windows and would bog the iPad to a crawl, to the point it would look "frozen", which it wasn't it was having to juggle too much. Cue writing a "parallel executor" with a fixed number of threads, because having a predictable cost was better.
No easy answers, it's more of "take an educated guess depending on use case".
Scaling isn't an issue for websites that are already heavily threaded, and async code that is half the perf means it doesn't scale better anyway! Strangely enough UIs are the only place where async offers a benefit: click a buttona nd it fails to respond, you don't block the entire UI if the calls are async.
No one's loading 100k records into memory in one go, bro. Certainly not with the large text included (You'll do that in the single blog UI which has a dedicated endpoint). And this is an issue with EF as you mentioned
Never heard anyone calling serial / synchronous execution "sync" 😀
if the database is the bottleneck, then async won'´t help in practice? maybe even make it slower?
Have you tried it with other db providers ? cuz it seems to be like SQLClient problem.
Hi, I was looking at bogus and it seems pretty nice at faking data. It is possible though to use the same concept to generate some fake data, then pass as the result it of a mock of a dbContext query?
Async isn't about performance, it's about thread safety.
async is about scalability and responsiveness
This is an issue with SqlClient, not EF Core. Other databases shouldn’t have this problem
I would code for async... Once the bug is fixed... Instantly faster without doing anything
Once devs start understing async-await != concurrency, the world would be a better place.
yay! I'm faster than sync method!
Is there a reason it's await-async and not async-await?
In my head it makes more sense to say await async because you await an async method
@@nickchapsas I always heard the technology named as "async await", but I didn't even notice you typed it the other way, and everyone knows what it means, so doesn't matter
@@nickchapsasIdk, it makes more sense to me to call it async-await per the order they come in code. You can declare a function as async and not await anything. Doesn't matter anyway, I refer to NginX as N-Ginx and it drives everyone insane 😈
@@nickchapsas You declare a method async in order to be able to use await.
Hello Nick,
The main goal of Async is not blocking the multiple requests.
Your test should be something like if you got 100 users, you must need to have async or 1 second processing time could generate a queue of 100 seconds to wait for the user get his 1 second of processing time with 100 users, Async resolves this problem
of course if we talking about some client solution that there is only 1 user and blocking role application when it is processing, it makes sense to have sync
Experienced coders always knew this to be true.
Why should async ever be faster? It will literally always be slower because there's overhead. The point of using async is not to be faster, it's to release the main thread to do something else. This is important e.g. so that the UI doesn't freeze. Of course, you can get a speed up of running multiple threads in parallel using async functions, but it's not clear that this should be happening here at all.
async would be faster when your application starts to suffer from thread starvation.
Not only, since it handles threads by itself It manages it better on average than any programmer in various situations
Seems there isnt much conversation about storing large amounts of data in Sql Server just being a bad idea. I can't imagine writing many queries tgat you expect to be fast on a large amount of text in Sql Server. Other types of technology would be better for that type of data. So moral of the story is understand try to understand the trade offs being made when storing various types of data.
Ultra looks amazing, but Windows only :(
Who on earth is requesting a collection of massive strings all at once? Have they ever heard of a get details by id call
Async is there to make your program more responsive not faster.
it’s was developed so that your thread doesn’t spinlock while waiting for I/O.
which is especially important for servers, as few cores can serve many requests with interweaving continuations when they ask for I/O. that way those core will always do work.
but: Task is a class and needs allocations. continuations are delegates and need allocations. the async state machine is a class and needs memory (and also lifts locals to fields, which can slow things a bit)
having a responsive app is mostly a client thing, and that worked fine with explicit threads. async can interweave between I/O even if you only use a single thread (in theory)
Reading "char" as in charizard vs. character is the new pineapple on pizza.
I am simple man, I see async in title and I click the video 🎉
The problem isn't async, the problem is SQL client. Now try with Postgres and it is fast
So it's a stupid click bait video and it's a bug that is open for years!
Probably when it is unnecessary.
And now i will watch the video.
Hi, u took some specific behavior which actually is a bug and on that basis u generalized theory (for sure title of this movie) that we shouldn't use await async. So for clickbait reasons or getting more viewers to your channel it is probably good. I don't buy it because u are focusing on this specific bug. U are not mentioning when really it is good to sacrifice async version for sync version in general - so for me low quality material. U should prepare more examples when sync version really shines over async.
6:54
I think this is a good reminder that we should ask the question, should this be async and why?
This type of explanations, Code snipets, and blah blah blah, it's why all programs has 'Starship Troopers' LVL bugs.
Every multi-step process (e.g. create, replace, update, delete, login, load a file) is naturally thought of as "do step 1, then do step 2, then do step 3" etc. An example might be, "display loading indicator, then send the request, then read the response, then display the data, then remove the loading indicator". NONE of this requires async/await. Async just adds complexity with no performance benefit except when there are thousands of such multi-step processes happening simultaneously on the same machine! Of course there are times where you are forced to use async/await (like in browsers, because they only allow one thread), and times where you might have danger of too many threads, and times when you can get two parts of a multi-step process to happen in parallel. Otherwise, I propose that we NEVER use async/await except for these special situations. Or, perhaps you want to make sure it is more difficult to replace you in your coding job because all your code is unnecessarily complex.
Pretty sure it’s a feature
CLICK BAIT
Advertising async await practices on the basis of a bug!
Really disappointed
Massive clickbait
It would all be faster if you didn’t use entity framework…
This issue is not related to EF rather than SqlClient.
I hear its poor form to publicly knock crappy ORMs.
First?
The sync method below was faster
Comments.First(), actually.
Async/Await is NOT designed to be faster since the code will always wait and then repopulate the stack.. It's designed to not block clients... If you make that call from MVC you WILL see the difference in the UI...
But also, it is not designed for file reading... I had to read lines from a super large file and found that even Task Parallel was slower...
@@ChristianHowell actually it is meant for file reading :) "super large file" doesn't mean anything. Run your tests again with large number of readers on in-memory disks, SSD, fast and slow hard drives, SAN drive. And "Task Parallel was slower" because of the obvious reason: multiple concurrent readers can't read data faster than one data reader from a single data stream.
@@volodymyrusarskyy6987 WHatever you say, I guess... I haven't been using async since delegates...