6 ms·
Genuine question... We have way over a million lines of c#, in asp.net, mvc and windows forms. We get 80,000,000 http requests a day. We have no async (delega
by harrytuttle 13y ago
Genuine question...
We have way over a million lines of c#, in asp.net, mvc and windows forms. We get 80,000,000 http requests a day.
We have no async (delegates or 4.5 stuff), no threading other than what WCF, AppFabric and ASP.Net give us.
About 25% is generic CRUD code but the rest is complicated matching, integration and math code. We also touch most fundamental computer science domains.
This begs the question: you really need async in the language?
- latch 13y agoIt's about concurrency, not performance. What's the 95th percentile response time (backend only)? Take out all that complicated code, and replace it with a call to an external 3rd party API. They get a hiccup, your response time goes up by 500%, your cpu load drops, and you start timing out connections. C10M http://www.youtube.com/watch?v=D09jdbS6oSI http://www.youtube.com/watch?v=D09jdbS6oSI
- harrytuttle 13y agoWe use appfabric and workflow to handle all 3rd party integration. Nothing blocks threads. But we don't use async language features to do that. Workflow could be considered async but it's a tenuous link. 95% is 41ms.
- barrydahlberg 13y agoasync doesn't really give you anything new you couldn't do before, just nicer syntax for composing it all. As you say you've already found other ways to compose your asynchronous flows for you.
- barrydahlberg 13y ago"WCF, AppFabric and ASP.Net" happen to give you an awful lot of that sort of infrastructure for free, I rarely directly use anything async in my web apps either. I do wonder how you're managing responsiveness in the forms apps though? Where the async syntax really shines is dealing with external services. If you're calling a lot of database, web services, sockets etc it can make your life easier.
- harrytuttle 13y agoTo be honest our webforms app is tiny and only does basic integration tasks between legacy software and our web app so there are no points it can block. We do everything synchronously with respect to databases. Integration is all docoupled into workflows.
- beagle3 13y agoYou raise a question, but there's a missing detail in your input - how many machines (and what kind) you are using. If you have 80,000,000 machines serving 80,000,000 requests - that's not very impressive. Even if you have 80 servers, that's extremely unimpressive. If you can do all of that on 1 server, then YOU probably don't need async. In fact, unless you're wasting time, 80,000,000 averages less than 10 requests/second, and peak is likely less than 100 requests/second. That's really not much - I do that with interpreted python. But every language does need facility for async processing. edit: it's 1000/second, not 10/second, as everyone down here corrected. Apparently, I cannot math before coffee. (I don't drink coffee). Apologies. fun mnemonic: the number of seconds in a day is 864e2. (eight-six-four-(e)-two).
- einhverfr 13y ago> In fact, unless you're wasting time, 80,000,000 averages less than 10 requests/second... Please show your math. I took 80000000 / (24 * 60 * 60) and I got 925. So you seem off by about two orders of magnitude.
- harrytuttle 13y agoYour math is off. It's on a bell curve. We're regionally tied so we have 80,000,000 requests, 90% of which are over a 5 hour period so we can hit 5000 requests a second on a fun day :) We do this on 10 servers. 4 front end, 4 back end, 2 database nodes. They are all hefty machines (FE=8xXeon,16Gb;BE=16xXeon,32Gb,DB=48xXeon,96Gb;Storage=12TiB SAN). Our peak cluster load is about 20% (the sweet spot). We don't need async, even if we lost half of our nodes.
- coldtea 13y ago>This begs the question: you really need async in the language? Or even delegates. Or interfaces. Or LINQ. Basically you could write the same thing in C. Or assembly.
- statictype 13y agoStrawman. The parent isn't arguing that the new async constructs in the language don't make asynchronous programming easier. He's questioning the need for using asynchronous programming models at all, for the common use case of ASP.NET applications.
- coldtea 13y ago>The parent isn't arguing that the new async constructs in the language don't make asynchronous programming easier. He's questioning the need for using asynchronous programming models at all, for the common use case of ASP.NET applications. And, my comment questions this very idea that for language constructs to be added there has to be a "need". They is never a hard need. We can do everything with assembly. Language constructs are added to make things easier. And that includes ASP.NET applications. His might not have a use for patterns made easier by async, but others do, especially those doing real time websockety stuff.
- d4nt 13y agoI think async is a systems programming tool rather than an application programming tool. If you're writing a web server or a web browser, it'd be useful. But for a web application, you're already sitting on a highly scalable and robust async library called IIS so when you need a background task the easiest thing to do is to make it a RESTful API call. I find many web developers now intuitively break up their application into parallelizable chunks without ever really thinking about async or threads, they just just say "this web page is taking a long time to load, maybe I can defer some of the work until after the page load" or (as you seem to have done) "maybe I can use tools like AppFabric Workflow to orchestrate all these small tasks".
- harrytuttle 13y agoThe problem is that it's pretty useless in non-systems programming language.
- TeddyLondon 13y agoIt is pretty useful for ui stuff, you can start a wait cursor in a button event, do what you need to then put the cursor back when your done, all in one thread without having to use background threads or anything. It is pretty simple for that scenario and avoids the cross thread marshalling you need to do in win forms.
- thomasz 13y agoDon't forget the SOA scenario: One service calls 0..n others to fulfill a request. Each of those calls is IO bound.
- mullr 13y agoWhen you say that a background task should be made into a RESTful API call, I assume you mean that instead of spinning up a local thread to do the work you should defer it to another service. Certainly you can do that, but async/await is still relevant in that case. The key question is: while said REST call is happening, what is the caller doing? Normally, he's sitting there and blocking his thread until the call finishes (i.e. consuming one thread from the connection thread pool). With async/await, the thread is released back into the thread pool until the result is ready, then it picks up where it left off. So anything where you might want to deal with background operations that take a long time (including network / db / filesystem access, i.e. most applications that aren't pure functions) in a connection-oriented system can greatly benefit from async/await. Even if it's just a regular desktop app, it appears to be a useful mechanism for coordinating different background tasks.
- barrkel 13y agoIf you're not blocking threads, either explicitly on I/O, or on perceptibly lengthy CPU operations[1], and you don't have a high proportion of kernel CPU% that can be put down to the cost of thread switching, then you personally don't really need async. But it's a big leap to go from that to saying that nobody else needs async, so it need not go in the language. [1] Taking the calculation off the main thread isn't the only way async can help here. The primitives also give you a way for taking better advantage of multiple cores (futures) more easily.
- tomlu 13y agoMaybe you don't need concurrency, but I certainly have in almost all my jobs thus far. async/await is pretty great for this, especially when you need to mix concurrency and UI. Making it a language feature (instead of a library) makes the concurrent operations a lot more readable by avoiding a lot of nesting.
- rbanffy 13y ago> This begs the question: you really need async in the language? I too have applications that do a lot of stuff relying of asynchronous toolsets but without much explicit asynchronicity. However, I did a simple experiment a couple weeks back - I coded one of our simple but very asynchronous programs in Go. Compared to the Python original (which uses Twisted), the Go version had 70% of the lines and was much more readable and understandable by even team mates who had never seen Go. I believe that's the point of having async operation elegantly merged into the language.
- lmm 13y agoNeed? Of course not. It's always been possible to do the same thing "by hand". But you certainly do need to not have all your threads blocking while external calls happen (although from elsewhere in the thread it sounds like your peak is 500 requests/second/machine? That's not so many, maybe you can afford to make blocking DB calls in the request path), one way or another. A better question is how many lines of code the async feature saves, compared to the code you would write without it.
- jaegerpicker 13y agoThere millions if not billions of lines of c code in production today doing everything from web servers/cgi web pages to low level embedded oses. A shit ton of it is not using oo programming: do we really need it? It's about doing more, better, and easier. async allows a pretty complicated process to be much easier to write.
- snarfy 13y agoI didn't really get it until I watched Ander's original keynote on it. To appreciate async and await, you have to go through the exercise of converting some synchronous code to an event driven model with callbacks. Then do it using async/await. It's more syntactic sugar than anything. I appreciate it in how I appreciate the dynamic keyword. I know how to dynamically Invoke() methods at runtime using reflection. It's a lot of boilerplate and ceremony, and the dynamic keyword helps alleviate that.
- moogleii 13y agoJust fyi, you're raising the question, not begging it.
- dragonwriter 13y agoDespite the desires of pedantic prescriptivists obsessed with maintaining the "purity" of a poor translation into English of the Latin name of a logical fallacy as the sole use of the phrase "Begs the question" in English (a use which is always intransitive), the always-transitive (and thus, impossible to confuse with the fallacy name) use of "begs the question" in a way which makes more sense with the normal English definition of the words in the phrase is in widespread use, is well-understood, and actually provides an avenue for the intransitive fallacy-naming use to make some sense (as the intransitive use can be viewed as a special case of the transitive form where the object -- the question a call for the answer is made -- is the same question that the original proposition was attempting to answer.) So, the pedantry on this point is pointless and counterproductive.
- danabramov 13y agoIn some scenarios it simplifies the code greatly. It may or may not be applicable to your app. Just a few weeks ago I was able to convert a nightmare-ish recursive asynchronous method to a `foreach` loop with `await`s inside. It's cool when you can do this: var providerExceptions = new List<Exception> (); // Try each provider in turn foreach (var pi in providers) { token.ThrowIfCancellationRequested (); try { return await GetSession (provider, isLast, options, token); } catch (TaskCanceledException) { throw; } catch (Exception ex) { providerExceptions.Add (ex); // Fall back to next provider } } // Neither provider worked throw new AggregateException ("Could not obtain session via either provider", providerExceptions); Or this: async Task<Session> GetSession (AccountProvider provider, bool isLast, LoginOptions options, CancellationToken token) { if (!SessionManager.NetworkMonitor.IsNetworkAvailable) throw new OfflineException (); var account = await GetAccount (provider, !isLast, options); if (account == null) throw new Exception ("The user chose to skip this provider."); var service = provider.Service; var session = new Session (service, account); if (service.SupportsVerification) { // For services that support verification, do it now try { await service.VerifyAsync (account, token); } catch (TaskCanceledException) { throw; } catch (Exception ex) { throw new InvalidOperationException ("Account verification failed.", ex); } } return session; } Depending on the conditions, the method may or may not “freeze”, but the calling code doesn't care.
- mfn 13y agoIn your first code sample, I'm pretty sure you don't need the return await GetSession (provider, isLast, options, token); Unless there's more to the method, just remove the async modifier and directly return the task returned by GetSession.
- cmircea 13y agoawait will unwrap exceptions from the task object
- MichaelGG 13y agoFirst note: Async should NOT be in the language. Support for such constructs should be in the language, and then libraries should add features such as async (like F# has done for years). Second note: If your app has lots of short-ish lived requests, you can just achieve parallelism by having a decent-sized threadpool and just run each request on a thread. Who cares if you have 400 threads? It'll scale well enough (as you noticed). However, if the app is doing long-running requests/clients, and you dedicate a thread to each one, then you end up with a lot of extra overhead. Using C#'s async model can simplify the code while keeping things lightweight.
- mcgwiz 13y agoHeuristically, anytime you're doing I/O (network or filesystem) could be an opportunity to increase concurrency with async/await. By using asynchrnous I/O and trickling that asynchronocity all the way up to ASP.NET, you make much more efficient use of the ThreadPool and allow more requests to be served. That's because you are recouping cycles otherwise lost on blocking. This isn't the only way to increase concurrency. Obviously you can grow your IIS web farm as well. But async/await (or some other .NET asynchronous programming pattern[1]) is a one-time .NET development cost as opposed to a recurring infrastructure/hosting cost. [1] http://msdn.microsoft.com/en-us/library/jj152938.aspx http://msdn.microsoft.com/en-us/library/jj152938.aspx