TPL - konkurenční, paralelní a asynchronní kód pro náročné

Post on 02-Jul-2015

2,255 views 4 download

transcript

TPL – konkurenční, paralelní a asynchronní

kód pro náročné

René Steinhttp://renestein.net

TPL základy – co byste měli znát

• Třída Task. „Thread je mrtev, ať žije Task“?

• Spuštění tásku a základní operace pro skládání tásků (WaitAny, WaitAll).

• Kooperativní stornování tásku.

• Co je synchronizační kontext a proč máme metodu ConfigureAwait.

• Klíčová slov async a await v C#.

TPL základy – co byste měli znát II

• Asynchronní != paralelní. (a asynchronní nebo paralelní != zázrak)

• Proč bychom neměli používat async void metody.

• Jaký je životní cyklus objektu tásku?

• (Toto by neměl být váš životní cyklus)

„Přišel jsem, viděl jsem, bohatě stačilo a (nejpozději po svačině) rád odcházím“

Životní cyklus tásku

Zdroj: http://blog.stephencleary.com/2014/06/a-tour-of-task-part-3-status.html

Něco jednoduchého – problémy s TaskCompletionSource

„Co jednou Task spojil, toTaskCompletionSource

musí rozdělit“Věčnost?

TaskCompletionSource

• TaskCompletionSource = Promise.

• Task = Future.

• I při kódování by se sliby měly plnit. I když to občas znamená, že ten druhý si bude přát, abyste mu nikdy nic neslíbili, protože může od vás čekat je krev, pot, slzy, deadlock, a když jste v dobrém rozmaru, tak výjimku BTW:Jsou sliby oboustranné?

Rstein.Async – DebugTaskCompletionSource

• DebugTaskCompletionSourceServices.DetectBrokenTaskCompletionSources();

(Detekce nesplněných slibů bez záruky - jde jen o preview verzi)

Idioti jsou jako láska - slibují víc, než mohou splnit. (G. Laub) Na TaskCompletionSource bych v této souvislosti nezapomínal!

(Dodatek: René Stein)

Každý slib je na nejlepší cestě k tomu být falešný. (J.P. Sartre)

Scheduler a ThreadPool

TPL scheduler.Net ThreadPool

TPL scheduler se má k .Net

ThreadPoolu jako ?

TPL scheduler se má k .Net

ThreadPoolu jako ?

Co s hříšnými touhami po jiném Scheduleru?

•Potřebujeme jiné schedulery než ty, které jsou v .Net Frameworku?– „ThreadPoolScheduler“ - Default – „SynchronizationContextScheduler“

FromCurrentSynchronizationContext()– ConcurrentExclusiveSchedulerPair (náhrada

za „lock“, ReaderWriterLock)

• !!! Většinou ne !!! - ale když už ano

„Extra“ schedulery v PEE

•Další slušnou sbírku schedulerů naleznete v Parallel Extensions Extras

http://code.msdn.microsoft.com/ParExtSamples

Vlastní scheduler

Nejjednodušší je podle mě:

CurrentThreadScheduler(A v téhle jednoduchosti fakt nehledejte

žádnou krásu)

Vlastní scheduler – problémy a řešení

(Otravný) FallbackScheduler, který může použít CurrentThreadScheduler jako záložní scheduler

Rstein.Async – dvojice IProxyScheduler a ITaskScheduler

Integrace s TPL – „obyčejný“

TaskScheduler

Rstein.Async – ProxyScheduler a TaskSchedulerBase

FallbackScheduler s pořadovým číslem 2 je sice stále nudný, ale už jej alespoň dokážeme napsat a používat bez vyvolání výjimky.

FALLBACKSCHEDULER II

Rstein.Async a IoServiceScheduler

• Scheduler, který nevyřídí žádný tásk do té doby, dokud mu nepropůjčíte vlákno zavoláním jedné z jeho metod Poll, PollOne, Run, RunOne

• Boost.Asio .Net

Rstein.Async - IoServiceSynchronizationContext

Rstein.Async a IoServiceThreadPoolScheduler

• „Autonomní“ scheduler.

• (Velmi) jednoduchý threadpool.

• Používá IoServiceScheduler.

Nelehký životní cyklus SimpleUploaderu

• Jak by řekla nejen programátorka Maruška – funkčnost a čitelnost kódu nad zlato i rychlost.

• V praxi se nejčastěji setkáte s kódem, který je:– Občas nefunkční, ale nikdo neví „proč“.– Nečitelný, ale všichni vám zdůvodní „proč“.– Po čase pomalý a plný (dead)locků, které

jsou zpestřením nudného vývojářského života. Proč?

Aktor model

• Zjednodušeně – aktor je objekt (prozatím nekamenovat!), u kterého platí, že v jednom okamžiku zpracovává maximálně jednu zprávu („provádí jednu metodu“). A to bez ohledu na počet požadavků z různých vláken.

• Všechny požadavky na aktora jsou aktorem zpracovány sekvenčně!

Aktor jako objekt z lepší společnosti

• Objekty, u kterých se při volání metody může změnit jejich interní stav (a přitom se zbavíme „locků“)

• Aktor je (prý) lepší objekt než “klasické“ objekty (nejen) z C-like jazyků.

Charakteristika konvenčního aktor modelu

• Aktor při zpracování zprávy („po obdržení požadavku“) může:– Poslat zprávy (požadavky) dalším aktorům.– Změnit svůj stav. A připravit se tak na příjem

další zprávy (požadavku).– Vytvořit další aktory pro zpracování nových

zpráv (požadavků).

Aktoři a thready

• Jak zabít aktory i s aplikaci? Frontu požadavků každého aktora obsluhuje právě jeden thread. Tento thread je v exkluzivním vlastnictví aktora.

• Co je „threadless“ actor model?

Rstein.Async - StrandSchedulerDecorator

• STRAND = v jednom okamžiku běží maximálně jeden tásk

• Implicitní strand = m_originalScheduler.MaximumConcurrencyLevel = 1

StrandSchedulerDecorator

ITaskScheduler(nejčastěji

IoServiceThreadPoolScheduler)

Rstein.Async - podpora pro aktory

• Použita dynamická proxy

• Castle.DynamicProxy

var uploaderActorProxy = proxyEngine.CreateProxy<IService>(simpleUploaderActor);

ProxyGenerationHook „Jaké metody budeme

odchytávat v interceptorech“

ActorMethodInterceptor „metody budou zpracovány sekvenčně – každý aktor má svůj StrandScheduler“

PreventArgumentBaseTypeLeakInterceptor„Aktor nevydá svou pravou podstatu z žádné metody, ale vždy si navlékne proxy masku“

Tradiční ukázky aktorů I

Ping Pong (Tomáš Aquinský proti Sigeru

Brabantskému)

Tradiční ukázky aktorů II

(Problematický) Ping Pong s čekáním na odpověď

• Podle mě je takzvaný „ASK“ vzor pro většinu scénářů antivzor. „Don‘t ASK“

• Actor by měl komunikovat s ostatními aktory stylem „Fire & Forget”.– Budeme čekat na odpověď a blokovat

zpracování dalších zpráv?– Zpracujeme jinou zprávu?

(co vnitřní stav aktora?)

Schéma komunikace mezi aktory - ukázka III

ILibraryActor IBookLinesParserActor

IBookLineConsumerActor n(CountWordsInLineActor)

ICountWordAggregateActor

IBookLineConsumerActor 1(CountWordsInLineActor)

IResultProcessorActor(PrintTopWordsProces

sorActor)

Co naši aktoři prozatím nepodporují

• O „pravém“ actor modelu (Erlang, Elixir…) se dá mluvit teprve tehdy:– Jsme-li schopni aktory od sebe dokonale izolovat.– Jsme-li schopni aktory aktivovat v jiném procesu/na

jiném počítači (distribuovaní aktoři). Ošetření chyb např. elegantním a vývojáři milovaným stylem „Let it crash“.

• Přesto – i „naši“ zjednodušení aktoři jsou pro mnoho aplikací požehnáním

Alternativní knihovny pro psaní aktorů

• TPL Dataflow – např. pomocí ActionBlocku s konkurencí rovnou jedné.

• ActorFX - http://actorfx.codeplex.com/wikipage?title=ActorFx%20Basics

• F#

Zdroj: http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx

AKKA.NET

Zdroj: https://github.com/akkadotnet/akka.net/issues/144

Tradiční problémy s aktory

• Jestliže aktoři mohou modifikovat stav „zpráv“ (argumentů metod), máte „race condition“. Zprávy-argumenty musí být imutabilní.

• Ani použití aktorů neznamená jistotu, že se v aplikaci neobjeví deadlock.

• Jeden aktor se může snadno stát brzdou pro ostatních aktory. Výkonnostní problémy.

Alternativní konkurenční modely

• TPL Dataflow

• Reactive Extensions – RX framework

• Software transactional memory

• Communicating Sequential Processes (CSP)

• a mnoho dalších

Zdroje – malý výběr

• Knihovna Rstein.Async.

https://bitbucket.org/renestein/rstein.async/

• Seriál na blogu o knihovně (prozatím 5 dílů) http://jdem.cz/ba8kp3

Answer? answer = await Task.Run(()=>

);

Dotazy

René Stein

• Vývoj aplikací, veřejné a inhouse kurzy

• http://www.renestein.net/nabidka.aspx

http://blog.renestein.nethttp://twitter.com/renestein