SlideShare uma empresa Scribd logo
1 de 24
Async demystified
.NET Core Summer event 2019 – Brno, CZ
Karel Zikmund – @ziki_cz
Agenda
• History of async patterns in .NET
• History and evolution of
• Task
• async-await
APM pattern:
Asynchronous Programming Model
.NET Framework 1.0/1.1 … 2002-2003
interface IAsyncResult
{
bool IsCompleted;
bool IsCompletedSynchronously;
object AsyncState;
WaitHandle AsyncWaitHandle;
}
Across BCL:
IAsyncResult BeginFoo(..., AsyncCallback callback, object state);
void EndFoo(IAsyncResult iar);
APM pattern
IAsyncResult BeginFoo(..., AsyncCallback callback, object state);
void EndFoo(IAsyncResult iar);
Synchronous call:
Foo();
Achieving the same:
EndFoo(BeginFoo(..., null, null));
Leveraging asynchronous calls:
BeginFoo(..., iar => {
T val = EndFoo(iar);
// do stuff ...
});
APM – Example
Copy stream to stream:
int bytesRead;
while ((bytesRead = input.Read(buffer)) != 0) {
output.Write(buffer, 0, bytesRead);
}
APM – Nesting problem
BeginRead(..., iar => {
int bytesRead = EndRead(iar);
input.BeginWrite(..., iar2 => {
int bytesWritten2 = EndWrite(iar2);
BeginRead(..., iar3 => {
int bytesRead3 = EndRead(iar3);
BeginWrite(..., iar4 => {
// ... again and again
});
});
});
});
APM – IsCompletedSynchronously
IAsyncResult r = BeginRead(..., iar => {
if (!iar.IsCompletedSynchronously) {
// ... asynchronous path as shown earlier
}
});
if (r.IsCompletedSynchronously) {
// ... Synchronous path
}
• Even worse in loop
• Overall very complicated
• Queueing on ThreadPool much simpler
EAP:
Event-based Asynchronous Pattern
• .NET Framework 2.0
obj.Completed += (sender, eventArgs) => {
// ... my event handler
}
obj.SendPacket(); // returns void
• Did not solve multiple-calls problem, or loops
• Introduced context
Task
• .NET Framework 4.0
• MSR project – parallel computing
• Divide & conquer efficiently (e.g. QuickSort)
• Shaped Task – similar to today
• Task – represents general work (compute, I/O bound, etc.)
= promise / future / other terminology
• Task / Task<T> – operation (with optional result T)
1. T … in the case of Task<T>
2. State related to synchronization
3. State related to callback
Task / TaskCompletionSource
• Task
• Here's a callback, invoke it when you're done, or right now if you've already
completed
• I want to block here, until your work is done
• Cannot be completed by user directly
• TaskCompletionSource … wrapper for Task
• Holds Task internally and operates on it via internal methods
• Methods:
• SetResult
• SetException
• SetCancelled
Task – Consumption
Task<T> t;
Either:
t.Wait(); // Blocks until Task is completed
Or:
t.ContinueWith(callback); // Will be executed after Task is completed
Even multiple times:
t.ContinueWith(callback2);
t.ContinueWith(callback3);
ContinueWith:
• Does not guarantee order of executions
• Always asynchronous (queued to ThreadPool/scheduler in general)
Task.Run
We complicated things 
Task<T> Task.Run(delegate d)
• Adds field to Task with ‘d’
• Queues work to ThreadPool
• Thread grabs it, executes it, marks task completed
Task.Run implementation
Task<T> Run(Func<T> f) {
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(() => {
try {
T result = f();
tcs.SetResult(result);
} catch (ex) {
tcs.SetException(ex);
}
});
return tcs.Task;
}
async-await
.NET Framework 4.5 / C# 5
Example of asynchronous code:
Task<int> GetDataAsync();
Task PutDataAsync(int i);
Code:
Task<int> t = GetDataAsync();
t.ContinueWith(a => {
var t2 = PutDataAsync(a.Result);
t2.ContinueWith(b => Console.WriteLine("done"));
});
async-await
Task<int> t = GetDataAsync();
t.ContinueWith(a => {
var t2 = PutDataAsync(a.Result);
t2.ContinueWith(b => Console.WriteLine("done"));
});
C# 5 with async-await helps us:
Task<int> t = GetDataAsync();
int aResult = await t;
Task t2 = PutDataAsync(aResult);
await t2;
Console.WriteLine("done");
Awaiter pattern
int aResult = await t;
Translated to:
var $awaiter1 = t.GetAwaiter();
if (! $awaiter1.IsCompleted) { // returns bool
// ...
}
int aResult = $awaiter1.GetResult(); // returns void or T
// If exception, it will throw it
Awaiter pattern – details
void MoveNext() {
if (__state == 0) goto label0;
if (__state == 1) goto label1;
if (__state == 42) goto label42;
if (! $awaiter1.IsCompleted) {
__state = 42;
$awaiter1.OnCompleted(MoveNext);
return;
}
label42:
int aResult = $awaiter1.GetResult();
}
State Machine
string x = Console.ReadLine();
int aResult = await t;
Console.WriteLine("done" + x);
State machine:
struct MethodFooStateMachine {
void MoveNext() { ... }
local1; // would be ‘x’ in example above
local2;
params;
_$awaiter1;
}
State Machine – Example
public async Task Foo(int timeout) {
await Task.Delay(timeout);
}
public Task Foo(int timeout) {
FooStateMachine sm = default;
sm._timeout = timeout;
sm._state = 0;
sm.MoveNext();
return ???;
}
struct FooStateMachine {
int _timeout; // param
// locals would be here too
void MoveNext() { ... }
int _state;
TaskAwaiter _$awaiter;
}
State Machine – Example
public Task Foo(int timeout) {
FooStateMachine sm = default;
sm._tcs = new TaskCompletionSource();
sm._timeout = timeout;
sm._state = 0;
sm.MoveNext();
return sm._tcs.Task;
}
AsyncValueTaskMethodBuilder.Create();
_tcs.Task -> _builder.Task;
struct FooStateMachine {
int _timeout; // param
// locals would be here too
void MoveNext() {
// ...
_tcs.SetResult(...);
}
int _state;
TaskAwaiter _$awaiter;
TaskCompletionSource _tcs;
}
State Machine – Summary
What about Task allocation?
• Builder can reuse known tasks
• Task.CompletedTask (without value)
• boolean – True/False
• int … <-1,8>
• LastCompleted (e.g. on MemoryStream)
• Does not work on SslStream (alternates headers and body)
• Size: 64B (no value) / 72B (with value)
• Azure workloads OK (GC will collect)
• Hot-path: up to 5%-10% via more GCs
ValueTask
• .NET Core 2.0
• Also as nuget package down-level
struct ValueTask<T> {
T;
Task<T>;
}
• Only one of them: T+null or default+Task<T>
• NET Core 2.1
ValueTask<int> Stream.ReadAsync(Memory<byte>, ...)
ValueTask – Can we improve more?
• What about the 1% asynchronous case?
• .NET Core 2.1
struct ValueTask<T> {
T;
Task<T>;
IValueTaskSource<T>;
}
struct ValueTask {
Task;
IValueTaskSource;
}
Summary
• APM pattern = Asynchronous Programming Model
• .NET Framework 1.0/1.1 (2002-2003)
• IAsyncResult, BeginFoo/EndFoo
• Limited nesting / loops
• EAP = Event-based Asynchronous Pattern (.NET Framework 2.0)
• Events – similar problems as APM
• Task (.NET Framework 4.0)
• Wait / ContinueWith
• TaskCompletionSource (for Write)
• async-await (.NET Framework 4.5 / C# 5)
• Awaiter pattern, state machine
• ValueTask (.NET Core 2.0)
• Don’t use unless you are on hot-path
• Hyper-optimizations possible, stay away! 
@ziki_cz

Mais conteúdo relacionado

Mais procurados

Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
Abed Bukhari
 

Mais procurados (20)

A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio moduleA deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio module
 
Python meetup: coroutines, event loops, and non-blocking I/O
Python meetup: coroutines, event loops, and non-blocking I/OPython meetup: coroutines, event loops, and non-blocking I/O
Python meetup: coroutines, event loops, and non-blocking I/O
 
C++ idioms.pptx
C++ idioms.pptxC++ idioms.pptx
C++ idioms.pptx
 
C++ references
C++ referencesC++ references
C++ references
 
Go Concurrency Basics
Go Concurrency Basics Go Concurrency Basics
Go Concurrency Basics
 
Kirk Shoop, Reactive programming in C++
Kirk Shoop, Reactive programming in C++Kirk Shoop, Reactive programming in C++
Kirk Shoop, Reactive programming in C++
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common Lisp
 
Go Concurrency Patterns
Go Concurrency PatternsGo Concurrency Patterns
Go Concurrency Patterns
 
MFC Message Handling
MFC Message HandlingMFC Message Handling
MFC Message Handling
 
node ffi
node ffinode ffi
node ffi
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Go Concurrency
Go ConcurrencyGo Concurrency
Go Concurrency
 
Class ‘increment’
Class ‘increment’Class ‘increment’
Class ‘increment’
 
C++11
C++11C++11
C++11
 
Grand Central Dispatch in Objective-C
Grand Central Dispatch in Objective-CGrand Central Dispatch in Objective-C
Grand Central Dispatch in Objective-C
 
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
 
asyncio internals
asyncio internalsasyncio internals
asyncio internals
 
C++11 & C++14
C++11 & C++14C++11 & C++14
C++11 & C++14
 
Promise of an API
Promise of an APIPromise of an API
Promise of an API
 
C++11 move semantics
C++11 move semanticsC++11 move semantics
C++11 move semantics
 

Semelhante a .NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund

In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
bradburgess22840
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/O
Jussi Pohjolainen
 

Semelhante a .NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund (20)

NDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel ZikmundNDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
 
Async and parallel patterns and application design - TechDays2013 NL
Async and parallel patterns and application design - TechDays2013 NLAsync and parallel patterns and application design - TechDays2013 NL
Async and parallel patterns and application design - TechDays2013 NL
 
JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
CSharp for Unity Day2
CSharp for Unity Day2CSharp for Unity Day2
CSharp for Unity Day2
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
History of asynchronous in .NET
History of asynchronous in .NETHistory of asynchronous in .NET
History of asynchronous in .NET
 
Appsec obfuscator reloaded
Appsec obfuscator reloadedAppsec obfuscator reloaded
Appsec obfuscator reloaded
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
 
Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
 
Advanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingAdvanced patterns in asynchronous programming
Advanced patterns in asynchronous programming
 
Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)
 
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/O
 
Microkernel Development
Microkernel DevelopmentMicrokernel Development
Microkernel Development
 

Mais de Karel Zikmund

Mais de Karel Zikmund (20)

.NET Conf 2022 - Networking in .NET 7
.NET Conf 2022 - Networking in .NET 7.NET Conf 2022 - Networking in .NET 7
.NET Conf 2022 - Networking in .NET 7
 
NDC London 2020 - Challenges of Managing CoreFx Repo -- Karel Zikmund
NDC London 2020 - Challenges of Managing CoreFx Repo -- Karel ZikmundNDC London 2020 - Challenges of Managing CoreFx Repo -- Karel Zikmund
NDC London 2020 - Challenges of Managing CoreFx Repo -- Karel Zikmund
 
WUG Days 2022 Brno - Networking in .NET 7.0 and YARP -- Karel Zikmund
WUG Days 2022 Brno - Networking in .NET 7.0 and YARP -- Karel ZikmundWUG Days 2022 Brno - Networking in .NET 7.0 and YARP -- Karel Zikmund
WUG Days 2022 Brno - Networking in .NET 7.0 and YARP -- Karel Zikmund
 
.NET Core Summer event 2019 in Vienna, AT - .NET 5 - Future of .NET on Mobile...
.NET Core Summer event 2019 in Vienna, AT - .NET 5 - Future of .NET on Mobile....NET Core Summer event 2019 in Vienna, AT - .NET 5 - Future of .NET on Mobile...
.NET Core Summer event 2019 in Vienna, AT - .NET 5 - Future of .NET on Mobile...
 
.NET Core Summer event 2019 in Linz, AT - War stories from .NET team -- Karel...
.NET Core Summer event 2019 in Linz, AT - War stories from .NET team -- Karel....NET Core Summer event 2019 in Linz, AT - War stories from .NET team -- Karel...
.NET Core Summer event 2019 in Linz, AT - War stories from .NET team -- Karel...
 
.NET Core Summer event 2019 in Brno, CZ - .NET Core Networking stack and perf...
.NET Core Summer event 2019 in Brno, CZ - .NET Core Networking stack and perf....NET Core Summer event 2019 in Brno, CZ - .NET Core Networking stack and perf...
.NET Core Summer event 2019 in Brno, CZ - .NET Core Networking stack and perf...
 
.NET Core Summer event 2019 in Brno, CZ - War stories from .NET team -- Karel...
.NET Core Summer event 2019 in Brno, CZ - War stories from .NET team -- Karel....NET Core Summer event 2019 in Brno, CZ - War stories from .NET team -- Karel...
.NET Core Summer event 2019 in Brno, CZ - War stories from .NET team -- Karel...
 
.NET Core Summer event 2019 in Prague, CZ - War stories from .NET team -- Kar...
.NET Core Summer event 2019 in Prague, CZ - War stories from .NET team -- Kar....NET Core Summer event 2019 in Prague, CZ - War stories from .NET team -- Kar...
.NET Core Summer event 2019 in Prague, CZ - War stories from .NET team -- Kar...
 
.NET Core Summer event 2019 in Vienna, AT - War stories from .NET team -- Kar...
.NET Core Summer event 2019 in Vienna, AT - War stories from .NET team -- Kar....NET Core Summer event 2019 in Vienna, AT - War stories from .NET team -- Kar...
.NET Core Summer event 2019 in Vienna, AT - War stories from .NET team -- Kar...
 
.NET Core Summer event 2019 in NL - War stories from .NET team -- Karel Zikmund
.NET Core Summer event 2019 in NL - War stories from .NET team -- Karel Zikmund.NET Core Summer event 2019 in NL - War stories from .NET team -- Karel Zikmund
.NET Core Summer event 2019 in NL - War stories from .NET team -- Karel Zikmund
 
NDC Oslo 2019 - War stories from .NET team -- Karel Zikmund
NDC Oslo 2019 - War stories from .NET team -- Karel ZikmundNDC Oslo 2019 - War stories from .NET team -- Karel Zikmund
NDC Oslo 2019 - War stories from .NET team -- Karel Zikmund
 
DotNext 2017 in Moscow - Challenges of Managing CoreFX repo -- Karel Zikmund
DotNext 2017 in Moscow - Challenges of Managing CoreFX repo -- Karel ZikmundDotNext 2017 in Moscow - Challenges of Managing CoreFX repo -- Karel Zikmund
DotNext 2017 in Moscow - Challenges of Managing CoreFX repo -- Karel Zikmund
 
DotNext 2017 in Moscow - .NET Core Networking stack and Performance -- Karel ...
DotNext 2017 in Moscow - .NET Core Networking stack and Performance -- Karel ...DotNext 2017 in Moscow - .NET Core Networking stack and Performance -- Karel ...
DotNext 2017 in Moscow - .NET Core Networking stack and Performance -- Karel ...
 
.NET MeetUp Brno 2017 - Microsoft Engineering teams in Europe -- Karel Zikmund
.NET MeetUp Brno 2017 - Microsoft Engineering teams in Europe -- Karel Zikmund.NET MeetUp Brno 2017 - Microsoft Engineering teams in Europe -- Karel Zikmund
.NET MeetUp Brno 2017 - Microsoft Engineering teams in Europe -- Karel Zikmund
 
.NET MeetUp Brno 2017 - Xamarin .NET internals -- Marek Safar
.NET MeetUp Brno 2017 - Xamarin .NET internals -- Marek Safar.NET MeetUp Brno 2017 - Xamarin .NET internals -- Marek Safar
.NET MeetUp Brno 2017 - Xamarin .NET internals -- Marek Safar
 
.NET MeetUp Brno - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Brno - Challenges of Managing CoreFX repo -- Karel Zikmund.NET MeetUp Brno - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Brno - Challenges of Managing CoreFX repo -- Karel Zikmund
 
.NET Fringe 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET Fringe 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund.NET Fringe 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET Fringe 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
 
.NET MeetUp Prague 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Prague 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund.NET MeetUp Prague 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Prague 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
 
.NET MeetUp Prague 2017 - .NET Standard -- Karel Zikmund
.NET MeetUp Prague 2017 - .NET Standard -- Karel Zikmund.NET MeetUp Prague 2017 - .NET Standard -- Karel Zikmund
.NET MeetUp Prague 2017 - .NET Standard -- Karel Zikmund
 
.NET MeetUp Amsterdam 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Amsterdam 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund.NET MeetUp Amsterdam 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
.NET MeetUp Amsterdam 2017 - Challenges of Managing CoreFX repo -- Karel Zikmund
 

Último

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Último (20)

WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 

.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund

  • 1. Async demystified .NET Core Summer event 2019 – Brno, CZ Karel Zikmund – @ziki_cz
  • 2. Agenda • History of async patterns in .NET • History and evolution of • Task • async-await
  • 3. APM pattern: Asynchronous Programming Model .NET Framework 1.0/1.1 … 2002-2003 interface IAsyncResult { bool IsCompleted; bool IsCompletedSynchronously; object AsyncState; WaitHandle AsyncWaitHandle; } Across BCL: IAsyncResult BeginFoo(..., AsyncCallback callback, object state); void EndFoo(IAsyncResult iar);
  • 4. APM pattern IAsyncResult BeginFoo(..., AsyncCallback callback, object state); void EndFoo(IAsyncResult iar); Synchronous call: Foo(); Achieving the same: EndFoo(BeginFoo(..., null, null)); Leveraging asynchronous calls: BeginFoo(..., iar => { T val = EndFoo(iar); // do stuff ... });
  • 5. APM – Example Copy stream to stream: int bytesRead; while ((bytesRead = input.Read(buffer)) != 0) { output.Write(buffer, 0, bytesRead); }
  • 6. APM – Nesting problem BeginRead(..., iar => { int bytesRead = EndRead(iar); input.BeginWrite(..., iar2 => { int bytesWritten2 = EndWrite(iar2); BeginRead(..., iar3 => { int bytesRead3 = EndRead(iar3); BeginWrite(..., iar4 => { // ... again and again }); }); }); });
  • 7. APM – IsCompletedSynchronously IAsyncResult r = BeginRead(..., iar => { if (!iar.IsCompletedSynchronously) { // ... asynchronous path as shown earlier } }); if (r.IsCompletedSynchronously) { // ... Synchronous path } • Even worse in loop • Overall very complicated • Queueing on ThreadPool much simpler
  • 8. EAP: Event-based Asynchronous Pattern • .NET Framework 2.0 obj.Completed += (sender, eventArgs) => { // ... my event handler } obj.SendPacket(); // returns void • Did not solve multiple-calls problem, or loops • Introduced context
  • 9. Task • .NET Framework 4.0 • MSR project – parallel computing • Divide & conquer efficiently (e.g. QuickSort) • Shaped Task – similar to today • Task – represents general work (compute, I/O bound, etc.) = promise / future / other terminology • Task / Task<T> – operation (with optional result T) 1. T … in the case of Task<T> 2. State related to synchronization 3. State related to callback
  • 10. Task / TaskCompletionSource • Task • Here's a callback, invoke it when you're done, or right now if you've already completed • I want to block here, until your work is done • Cannot be completed by user directly • TaskCompletionSource … wrapper for Task • Holds Task internally and operates on it via internal methods • Methods: • SetResult • SetException • SetCancelled
  • 11. Task – Consumption Task<T> t; Either: t.Wait(); // Blocks until Task is completed Or: t.ContinueWith(callback); // Will be executed after Task is completed Even multiple times: t.ContinueWith(callback2); t.ContinueWith(callback3); ContinueWith: • Does not guarantee order of executions • Always asynchronous (queued to ThreadPool/scheduler in general)
  • 12. Task.Run We complicated things  Task<T> Task.Run(delegate d) • Adds field to Task with ‘d’ • Queues work to ThreadPool • Thread grabs it, executes it, marks task completed
  • 13. Task.Run implementation Task<T> Run(Func<T> f) { var tcs = new TaskCompletionSource<T>(); ThreadPool.QueueUserWorkItem(() => { try { T result = f(); tcs.SetResult(result); } catch (ex) { tcs.SetException(ex); } }); return tcs.Task; }
  • 14. async-await .NET Framework 4.5 / C# 5 Example of asynchronous code: Task<int> GetDataAsync(); Task PutDataAsync(int i); Code: Task<int> t = GetDataAsync(); t.ContinueWith(a => { var t2 = PutDataAsync(a.Result); t2.ContinueWith(b => Console.WriteLine("done")); });
  • 15. async-await Task<int> t = GetDataAsync(); t.ContinueWith(a => { var t2 = PutDataAsync(a.Result); t2.ContinueWith(b => Console.WriteLine("done")); }); C# 5 with async-await helps us: Task<int> t = GetDataAsync(); int aResult = await t; Task t2 = PutDataAsync(aResult); await t2; Console.WriteLine("done");
  • 16. Awaiter pattern int aResult = await t; Translated to: var $awaiter1 = t.GetAwaiter(); if (! $awaiter1.IsCompleted) { // returns bool // ... } int aResult = $awaiter1.GetResult(); // returns void or T // If exception, it will throw it
  • 17. Awaiter pattern – details void MoveNext() { if (__state == 0) goto label0; if (__state == 1) goto label1; if (__state == 42) goto label42; if (! $awaiter1.IsCompleted) { __state = 42; $awaiter1.OnCompleted(MoveNext); return; } label42: int aResult = $awaiter1.GetResult(); }
  • 18. State Machine string x = Console.ReadLine(); int aResult = await t; Console.WriteLine("done" + x); State machine: struct MethodFooStateMachine { void MoveNext() { ... } local1; // would be ‘x’ in example above local2; params; _$awaiter1; }
  • 19. State Machine – Example public async Task Foo(int timeout) { await Task.Delay(timeout); } public Task Foo(int timeout) { FooStateMachine sm = default; sm._timeout = timeout; sm._state = 0; sm.MoveNext(); return ???; } struct FooStateMachine { int _timeout; // param // locals would be here too void MoveNext() { ... } int _state; TaskAwaiter _$awaiter; }
  • 20. State Machine – Example public Task Foo(int timeout) { FooStateMachine sm = default; sm._tcs = new TaskCompletionSource(); sm._timeout = timeout; sm._state = 0; sm.MoveNext(); return sm._tcs.Task; } AsyncValueTaskMethodBuilder.Create(); _tcs.Task -> _builder.Task; struct FooStateMachine { int _timeout; // param // locals would be here too void MoveNext() { // ... _tcs.SetResult(...); } int _state; TaskAwaiter _$awaiter; TaskCompletionSource _tcs; }
  • 21. State Machine – Summary What about Task allocation? • Builder can reuse known tasks • Task.CompletedTask (without value) • boolean – True/False • int … <-1,8> • LastCompleted (e.g. on MemoryStream) • Does not work on SslStream (alternates headers and body) • Size: 64B (no value) / 72B (with value) • Azure workloads OK (GC will collect) • Hot-path: up to 5%-10% via more GCs
  • 22. ValueTask • .NET Core 2.0 • Also as nuget package down-level struct ValueTask<T> { T; Task<T>; } • Only one of them: T+null or default+Task<T> • NET Core 2.1 ValueTask<int> Stream.ReadAsync(Memory<byte>, ...)
  • 23. ValueTask – Can we improve more? • What about the 1% asynchronous case? • .NET Core 2.1 struct ValueTask<T> { T; Task<T>; IValueTaskSource<T>; } struct ValueTask { Task; IValueTaskSource; }
  • 24. Summary • APM pattern = Asynchronous Programming Model • .NET Framework 1.0/1.1 (2002-2003) • IAsyncResult, BeginFoo/EndFoo • Limited nesting / loops • EAP = Event-based Asynchronous Pattern (.NET Framework 2.0) • Events – similar problems as APM • Task (.NET Framework 4.0) • Wait / ContinueWith • TaskCompletionSource (for Write) • async-await (.NET Framework 4.5 / C# 5) • Awaiter pattern, state machine • ValueTask (.NET Core 2.0) • Don’t use unless you are on hot-path • Hyper-optimizations possible, stay away!  @ziki_cz

Notas do Editor

  1. Based on internal talk from author of Task, async and all good things around – Stephen Toub, architect of BCL
  2. IAsyncResult AsyncWaitHandle – ManualResetEvent or AutoResetEvent Across BCL Usage either: Wait for callback to be called, or Call EndFoo which will block until completed
  3. Single operation works fine, but in reality you do more – e.g. in a loop
  4. Manually it does not work – somehow turn it into loop It’s possible but extremely long and tricky Further complications with IsCompletedSynchronously
  5. For perf reasons In the loop it is even more complicated However: On MemoryStream, the data is already available … instead of ThreadPool, call delegate immediately -> Leads to recursive calls -> 10K StackOverflow Bottom part: Even BCL lots of wrappers (e.g. in Networking: LazyAsyncResult) with lots of specializations Very complicated
  6. Straightforward idea – Completed event Kick off operation, then Completed handler is invoked (generally on ThreadPool) 5-10 classes in BCL … like SmtpMail, TcpClient, BackgroundWorker Downsides: We shipped it in .NET Framework 2.0 and quickly realized that it is interesting experiment, but not exactly addressing real needs
  7. 90% right, 10% keeps Toub awake at night even after 10 years and would love to change it NOT tied to ThreadPool – not tied to executing delegate Shove result into it Can be completed Can wake up someone waiting on it
  8. Task – something to consume - hook up to, not to change directly (no control) TaskCompletionSource – can alter state of Task … has control over Task Lazy initialization (something over network) … you are in charge who can change complete the work
  9. Wait - creates ManualResetEvent which will be signaled when one of the SetResult/SetException/SetCancelled is called Option: TaskExecutionOption to do it synchronously APM - IAsyncResult … no shared implementation Everyone had to have their own implementation Task model - you don't pass delegate at creation, but you can walk up on any of them and say "call me when you're done" Abstractions enabled - like async-await await hooks up the callback
  10. Sets completed = execute callback, waking up things waiting on it, etc.
  11. TaskCompletionSource creates Task Returns Task to be awaited on, etc. Now we implemented Task.Run without storing any delegate on Task
  12. GetData/PutData … maybe across the wire
  13. Compiler translates it to the code above (hand-waving involved) Compiler does not treat Task specially, but it just looks for pattern (awaiter pattern)
  14. Bold methods are pattern matching
  15. “! IsCompleted” part is complicated – I have to hook up code that comes back here when task completes All of it is part of MoveNext method -- it is a state machine, every await in method is state in state machine (hand waving a bit) OnCompleted has slightly more complicated signature
  16. How does ‘x’ survive continuation? (it is just on stack) – need to capture it Same in continuations - C# compiler lifts it to keep it on heap allocated object (floats through closures) Same in state machine Compiler optimizes - stores here things only crossing await boundary In debug -- struct is class -- for debuggability, but for perf struct Why? These async methods often complete synchronously – example: BufferedStream … large buffer behind with inner stream If I ask for 1B, but it reads 10K in bulk, then lots of calls end up synchronously If it was class, then we would allocate per call
  17. _tcs on state machine is logically there problem 2 allocations – TaskCompletionSource and Task (inside) For the synchronous case we want 0 allocations ideally (BufferedStream example) Even the Task/TaskCompletionSource is problematic, because it is anything Task-like Each Task-like type (except Task) has attribute defining builder - builder pattern ValueTask has one -> AsyncValueTaskMethodBuilder instead of new TaskCompletionSource() -> AsyncValueTaskMethodBuilder.Create(); We have internally in System.Runtime.CompilerServices structs: AsyncTaskMethodBuilder, AsyncTaskMethodBuilder<T>, AsyncVoidMethodBuilder instead of _tcs.Task -> _builder.Task We eliminated TaskCompletionSource allocation What about the Task?
  18. Methods are 1-liners (if Task<T> == null, do something, else something else) Nicely handles synchronously completing case Note: Non-generic ValueTask does not make sense - only Task inside … we have CompletedTask .NET Core 2.1 Luckily we introduced Memory<T> at the same time, as we cannot overload on return type That's why sometimes in PRs we wrap byte[] in Memory first … to use the ValueTask Design-guidelines: Start with Task … use ValueTask only in hot-path scenarios
  19. IValueTaskSource – complicated interface almost the awaiter pattern: Are you completed? Hook up a call back Get a result All implementations on ValueTask are now ternary Value: You can implement it however you want, incl. reset (reuse) Complicated to do, so not everywhere Socket.SendAsync/ReceiveAsync Object per send/receive … if one at a time (typical) 0 allocation for loop around Send/Receive on Socket Same: NetworkStream, Pipelines, Channels