异步/等待高性能服务器应用程序? [英] async/await for high performance server applications?

查看:72
本文介绍了异步/等待高性能服务器应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#5中新的async/await关键字看起来非常有前途,但我读了一篇有关对那些应用程序的性能影响的文章,因为编译器将为异步方法生成一个非常复杂的状态机.

the new async/await keywords in C# 5 look very promising but I read an article about the performance impact on those applications since the compiler will generate a quite complex state machine for async methods.

使用这些关键字进行异步编程要容易得多,但是它与Sockets的SocketAsyncEventArgs一样好吗?

Async-programming using these keywords is so much easier but is it as good as say SocketAsyncEventArgs for Sockets ?

第二个问题:像Stream.WriteAsync之类的异步IO方法是否真的是异步的(.net上的完成端口或Mono上的epoll/poll),或者这些方法是廉价的包装器,用于将写调用推送到线程池?

Second question: Are asynchronous IO methods like Stream.WriteAsync really asynchronous (Completion Ports on .Net or epoll/poll on Mono) or are these methods cheap wrappers for pushing a write call to a threadpool ?

第三个问题:除了UI应用程序的SynchronizationContext外,还有没有一种方法可以实现某种单线程上下文?像事件循环之类的东西,以便已完成的任务在主线程上继续进行? 我发现了Nito.AsyncEx库,但是我不确定这是否是我需要的.

Third question: Beside the SynchronizationContext of an UI application, is there a way to implement some kind of sinlge-threaded context ? Something like an event loop so that finished tasks continues on the main thread ? I discovered the Nito.AsyncEx library, but I'm not quite sure whether or not this is what i need.

推荐答案

async本身非常出色.做了很多工作.

async itself is quite performant. A ton of work went into this.

通常,在服务器端,您担心async I/O.我将忽略async CPU绑定的方法,因为async的开销无论如何都会在噪音中丢失.

In general, on the server side you're concerned about async I/O. I'm going to ignore async CPU-bound methods because the async overhead will get lost in the noise anyway.

异步I/O将增加每个请求的内存使用量,但会减少每个请求的线程使用量.因此,您最终会获胜(临界病理性极端情况除外).对于所有异步I/O,包括async,都是如此.

Asynchronous I/O will increase your memory usage per request, but it'll reduce your thread usage per request. So you end up winning (except borderline pathological corner cases). This is true for all asynchronous I/O, including async.

await设计有一种模式-不仅是Task类型-因此,如果您需要挤出尽可能多的性能,则可以.

await was designed with a pattern - not just the Task type - so if you need to squeeze out as much performance as possible, you can.

我读了一篇关于性能对那些应用程序影响的文章,因为编译器将为异步方法生成一个非常复杂的状态机.

I read an article about the performance impact on those applications since the compiler will generate a quite complex state machine for async methods.

Stephen Toub撰写的文章非常好.我还建议 Zen异步视频(同样由Stephen Toub创作).

The article you read by Stephen Toub is excellent. I also recommend the Zen of Async video (also by Stephen Toub).

使用这些关键字进行异步编程要容易得多,但是否与Sockets的SocketAsyncEventArgs一样好?

Async-programming using these keywords is so much easier but is it as good as say SocketAsyncEventArgs for Sockets ?

首先,请了解SocketAsyncEventArgs具有更高的可伸缩性,因为它减少了内存浪费.使用async套接字的更简单方法将产生更多的内存垃圾,但是由于await是基于模式的,因此您可以

First, understand that SocketAsyncEventArgs is more scalable because it reduces memory garbage. The simpler way to use async sockets will generate more memory garbage, but since await is pattern-based you can define your own async-compatible wrappers for the SocketAsyncEventArgs API (as seen on Stephen Toub's blog... I'm sensing a pattern here ;). This allows you to squeeze every ounce of performance out.

从长远来看,通常最好设计一个横向扩展系统,而不是扭曲代码以避免一些内存分配.恕我直言.

Though it's usually better in the long run to design a scale-out system rather than twisting the code to avoid a few memory allocations. IMHO.

第二个问题:像Stream.WriteAsync之类的异步IO方法是否真的是异步的(.net上的完成端口或Mono上的epoll/poll),或者这些方法是廉价的用于将写调用推送到线程池的包装器?

Second question: Are asynchronous IO methods like Stream.WriteAsync really asynchronous (Completion Ports on .Net or epoll/poll on Mono) or are these methods cheap wrappers for pushing a write call to a threadpool ?

我不知道Mono.在.NET上,大多数异步I/O方法基于完成端口. Stream类是一个明显的例外.默认情况下,Stream基类将执行廉价包装",但允许派生类重写此行为.来自网络通信的Stream始终会覆盖它以提供真正的异步I/O. Stream处理文件的文件仅在流明确为异步I/O构造的情况下覆盖此.

I don't know about Mono. On .NET, most asynchronous I/O methods are based on a completion port. The Stream class is a notable exception. The Stream base class will do a "cheap wrapper" by default, but allows derived classes to override this behavior. Streams that come from network communications always override this to provide truly asynchronous I/O. Streams that deal with files only override this if the stream was constructed explicitly for asynchronous I/O.

第三个问题:除了UI应用程序的SynchronizationContext之外,还有没有一种方法可以实现某种单线程上下文?

Third question: Beside the SynchronizationContext of an UI application, is there a way to implement some kind of single-threaded context ?

ASP.NET也有一个SynchronizationContext,因此,如果您使用的是ASP.NET,则已经设置好了.

ASP.NET also has a SynchronizationContext, so if you're using ASP.NET you're already set.

如果您要使用自己的基于套接字的服务器(例如Win32服务),则可以使用我的AsyncEx库中的AsyncContext类型.但这听起来并不是您真正想要的. AsyncContext将在当前线程上创建一个单线程上下文.但是async对于服务器应用程序的真正威力来自于扩展请求而不是线程.

If you are doing your own socket-based server (e.g., a Win32 service), then you could use the AsyncContext type in my AsyncEx library. But it doesn't sound like this is what you'd actually want. AsyncContext will create a single-threaded context on the current thread. But the true power of async for server applications comes from scaling requests instead of threads.

考虑ASP.NET SynchronizationContext的工作方式:随着每个 request 的出现,它会抓取线程池线程并构造一个SynchronizationContext(针对该 request ).当该请求具有异步工作要做时,它将在SynchronizationContext中注册,并且运行该请求的线程将返回到线程池.稍后,异步工作完成时,它将获取线程池线程( any 线程),在其上安装现有的SynchronizationContext,然后继续处理该请求.当请求最终完成时,其SynchronizationContext被处置.

Consider how the ASP.NET SynchronizationContext works: as each request comes in, it grabs a thread pool thread and constructs a SynchronizationContext (for that request). When that request has asynchronous work to do, it registers with the SynchronizationContext and the thread running that request returns to the thread pool. Later, when the asynchronous work completes, it grabs a thread pool thread (any thread), installs the existing SynchronizationContext on it, and continues processing that request. When the request is finally completed, its SynchronizationContext is disposed.

该过程中的关键是当请求正在等待(await)异步操作时,没有 no 线程专用于该请求.与 thread 相比,由于 request 相当轻巧,因此服务器可以更好地扩展.

The key in that process is that when the request is waiting (await) asynchronous operations, there are no threads dedicated to that request. Since a request is considerably lightweight compared to a thread, this enables the server to scale better.

如果给每个请求一个单线程的SynchronizationContext(例如AsyncContext),即使没有任何关系,这也会将一个线程绑定到每个请求.几乎没有什么比同步多线程服务器更好.

If you gave each of your requests a single-threaded SynchronizationContext such as AsyncContext, this would bind a thread to each request even when it has nothing to do. That's hardly any better than a synchronous multithreaded server.

如果我的关于SynchronizationContext 的MSDN文章可能会有用您想解决发明自己的SynchronizationContext问题.在那篇文章中,我还将介绍异步方法如何注册"和安装"上下文.这是由async voidawait自动完成的,因此您不必显式地执行此操作.

You may find my MSDN article on SynchronizationContext useful if you want to tackle inventing your own SynchronizationContext. I also cover in that article how asynchronous methods "register" and "install" the context; this is done mostly-automatically by async void and await so you won't have to do it explicitly.

这篇关于异步/等待高性能服务器应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆