async/await für high-performance-server-Anwendungen?
den neuen async - /await-Schlüsselwörter in C# 5 sehen sehr vielversprechend aus, aber Las ich einen Artikel über die performance-Auswirkungen auf diese Anwendungen, da der compiler generiert ein Recht komplexer Zustandsautomat für asynchrone Methoden.
Async-Programmierung mit Hilfe dieser Schlüsselwörter ist so viel einfacher aber ist es so gut wie sagen SocketAsyncEventArgs für Steckdosen ?
Zweite Frage: Sind asynchrone IO-Methoden wie Stream.WriteAsync wirklich asynchron (Abschluss-Ports auf .Net oder epoll/poll auf Mono) oder sind diese Methoden Billig-Wrapper für das drücken einer write-Aufruf an einen threadpool ?
Dritte Frage: Neben dem Synchronisierungskontext einer UI-Anwendung, gibt es eine Möglichkeit zu implementieren, eine Art von Single-threaded-Kontext ? So etwas wie eine event-Schleife, so dass erledigte Aufgaben weiterhin auf dem main-thread ?
Ich entdeckte den Nito.AsyncEx Bibliothek, aber ich bin mir nicht ganz sicher, ob oder nicht das ist, was ich brauche.
- Link im Artikel?
- msdn.microsoft.com/en-us/magazine/hh456402.aspx
Du musst angemeldet sein, um einen Kommentar abzugeben.
async
selbst ist sehr performant. Eine Menge Arbeit ging in diese.Im Allgemeinen, auf der server-Seite sind Sie besorgt über
async
I/O. ich werde ignorierenasync
CPU-bound-Methoden, weil dieasync
overhead verloren gehen in dem Lärm sowieso.Asynchrone I/O erhöhen Sie Ihre memory-Nutzung pro Anfrage, aber es wird senken Sie Ihre thread-Nutzung pro Anfrage. So dass Sie am Ende gewinnen (außer borderline-pathologische Ecke Fälle). Dies gilt für alle asynchronen I/O, einschließlich
async
.await
wurde mit einem Muster - nicht nur dieTask
Typ - also, wenn Sie brauchen, um squeeze-out so viel Leistung wie möglich, Sie können.Den Artikel, die Sie Lesen von Stephen Toub ist ausgezeichnet. Ich empfehle auch die Zen des Async-video (auch von Stephen Toub).
Zuerst verstehen, dass
SocketAsyncEventArgs
ist besser skalierbar, weil es reduziert Speicher-Müll. Die einfachere Methode zu verwendenasync
sockets erzeugen mehr Speicher Müll, aber daawait
ist pattern-basiert, können Sie definieren Sie Ihre eigenenasync
-kompatibel-Wrapper für dieSocketAsyncEventArgs
- API (gesehen auf Stephen Toub blog... ich bin sensing, hier ein Muster ;). Dies ermöglicht Ihnen zu quetschen jedes Quäntchen an Leistung heraus.Obwohl es in der Regel auf lange Sicht besser zur Gestaltung einer scale-out-system, anstatt verdrehen der code, um ein paar Speicherzuordnungen. IMHO.
Weiß ich nicht Mono. Auf .NET, die meisten asynchrone I/O-Methoden basieren auf einer completion-port. Die
Stream
Klasse ist eine Bemerkenswerte Ausnahme. DieStream
Basis-Klasse wird eine "Billig-wrapper" standardmäßig, aber können von abgeleiteten Klassen zu überschreiben, dieses Verhalten.Stream
s, die kommen aus dem Netzwerk - - Kommunikation immer überschreiben Sie diese zu wirklich asynchrone I/O.Stream
s, der Umgang mit Dateien nur überschreiben diese wenn der stream gebaut wurde explizit für asynchrone I/O.ASP.NET hat auch eine
SynchronizationContext
, so dass, wenn Sie mit ASP.NET Sie sind bereits festgelegt.Wenn Sie tun, Ihre eigene socket-basierte server (z.B. einen Win32-Dienst), dann könnte Verwendung der
AsyncContext
Typ in meinem AsyncEx Bibliothek. Aber es klingt nicht wie das ist, was Sie eigentlich wollen.AsyncContext
wird, erstellen Sie einen single-threaded Kontext auf den aktuellen thread. Aber die wahre macht derasync
für server-Anwendungen kommt von der Skalierung Anfragen statt threads.Überlegen, wie die ASP.NET
SynchronizationContext
funktioniert: wie jedes Anfrage kommt, es packt einen thread-pool-thread und erstellt einSynchronizationContext
(für die, die Anfrage). Bei dieser Anfrage hat der asynchronen Arbeit zu tun haben, registriert er mit derSynchronizationContext
und der thread läuft, die Anfrage zurück an den thread-pool. Später, wenn die asynchrone Arbeit abgeschlossen ist, schnappt sich ein threadpool-thread (alle thread), installiert die vorhandenenSynchronizationContext
auf es, und setzt die Verarbeitung Fort, die Anfrage. Wenn die Anforderung ist nun endlich fertig, seineSynchronizationContext
entsorgt wird.Den Schlüssel in diesem Prozess ist, dass, wenn die Anforderung warten (
await
) asynchronen Operationen gibt es keine threads, die sich um diese Anfrage. Seit ein Anfrage ist deutlich geringes Gewicht im Vergleich zu einer thread, dies ermöglicht dem server zu skalieren besser.Wenn Sie gab jedem Ihrer Wünsche eine single-threaded -
SynchronizationContext
wieAsyncContext
würde dies binden Sie einen Faden um jede Anfrage, auch wenn es nichts zu tun hat. Das ist kaum besser als ein synchrones Multithreading-server.Können Sie finden meine MSDN-Artikel auf
SynchronizationContext
nützlich, wenn Sie wollen anzugehen, erfinden Ihre eigenenSynchronizationContext
. Ich decken auch in diesem Artikel, wie Sie asynchrone Methoden "registrieren" und "installieren" Rahmen; dies erfolgt meist automatisch durchasync void
undawait
so dass Sie nicht haben, um es explizit tun.Wenn Sie in den Kontext der async-IO-es ist ein strittiger Punkt. Die Zeit, die auf Ihre Datenbank-operation, Datei - /Netzwerk-E /a usw. werden Millisekunden am besten. Der Aufwand
async
werden Mikrosekunden im schlimmsten Fall, wenn keine Nanosekunden. Wo müssen Sie vorsichtig sein, wenn Sie eine viel von Operationen, die Sie erwarten (wie Sie in tausenden, Zehntausenden oder mehr) und diese Vorgänge sind sehr schnell. Wenn diejenigen, die asynchrone Operationen darstellen, CPU-gebundene Arbeit ist es sicherlich möglich, der Aufwand mitawait
zu sein, zumindest spürbar. Beachten Sie, dass der generierte code für die state-Maschine ist relativ Komplex, in Bezug auf das menschliche verstehen-Fähigkeit, aber der Staat Maschinen im Allgemeinen neigen dazu, führen Sie eher gut als ganzes.Die Methoden werden nicht nur Wrapper, die sperren eines thread-pool-thread, Nein. Das würde den Zweck verfehlen, was
await
darstellt. Diese Methoden blockieren Sie nicht alle thread und verlassen sich auf OS-Haken, um die Aufgabe abzuschließen.Sicher, Sie können erstellen Sie Ihre eigenen
SynchronizationContext
statt sich ganz auf eine bestehende von Ihrem UI-framework. Hier ist ein tolles Beispiel. Nur vorsichtig sein, wenn Sie so etwas wie dieses; es ist ein gutes Werkzeug für die richtige Aufgabe, aber kann missbraucht werden, um eine zu erstellen Weg blockieren, wenn Sie sollte nur tun, alles asynchron.