68
Plongée au coeur du framework .NET 4.5 : Finaxys Conseil et architecture IT-FINANCE 160 collaborateurs spécialisés en IT-Finance CA 2012 (prév.) de 16M€ Une large palette d’expertises : Conseil SI & fonctionnel Finance, AMOA SI et métiers Finance Ingénierie logicielle (architecture, études, conception, développement, intégration continue) Technologies Microsoft C++ et C#/.NET 4.0 Support et production applicative Un accompagnement global sur l’ensemble du cycle de vie projet, du cadrage à la recette, avec une démarche qualité intégrée Une contractualisation sur mesure : forfait, centre de service, assistance technique groupée ou assistance technique simple Nos références :

Plongée au cœur du Framework .NET 4.5

Embed Size (px)

DESCRIPTION

La nouvelle version du Framework .NET apporte des innovations majeures qui permettent encore plus de performance et accroissent le champ des possibles. Du poste client au serveur d’entreprise, ce jeu de nouvelles fonctionnalités logée au cœur du noyau vous offrent une gestion plus fine de votre code et donnent un nouveau souffle à vos applications. Ne manquez pas cette session et venez découvrir comment augmenter considérablement les performances de vos programmes et tirer parti de toute la puissance des ordinateurs modernes.

Citation preview

Page 1: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Finaxys

Conseil et architecture IT-FINANCE• 160 collaborateurs spécialisés en IT-Finance

• CA 2012 (prév.) de 16M€

• Une large palette d’expertises :

• Conseil SI & fonctionnel Finance,

• AMOA SI et métiers Finance

• Ingénierie logicielle (architecture, études, conception, développement, intégration continue)

• Technologies Microsoft C++ et C#/.NET 4.0

• Support et production applicative

• Un accompagnement global sur l’ensemble du cycle de vie projet, du cadrage à la recette, avec une

démarche qualité intégrée

• Une contractualisation sur mesure : forfait, centre de service, assistance technique groupée ou

assistance technique simple

• Nos références :

Page 2: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : MindMatcher

Moteur de recherche innovant appliqué au domaine du recrutement• Startup fondée en 2011

• 5 fondateurs

• Fonctionnalités principales :

• Méthodes de recherche probabilistes

• Aucune structuration des documents

• Aucun mot clef : utilisation du CV ou de l’offre d’emploi comme clef de recherche

• Algorithme d’enrichissement automatique

• Apprentissage par réseaux de neurones des préférences de l’utilisateur

• Rapidité et simplicité

• La pertinence augmente avec la taille de la base de documents

http://www.mindmatcher.org

[email protected]

Page 3: Plongée au cœur du Framework .NET 4.5

Les

nou

veau

tés

du

fr

am

ew

ork

.N

ET 4

.5

Plongée au coeur du framework .NET 4.5 : de quoi va-t-on parler ?

Page 4: Plongée au cœur du Framework .NET 4.5

Agenda

Plongée au coeur du framework .NET 4.5 : agenda

Garbage collector JITTER

Concurrence

A

Debugging

1 2

34Q/A5

Page 5: Plongée au cœur du Framework .NET 4.5

Fonctionnement général

Plongée au coeur du framework .NET 4.5 : fonctionnement général du garbage collector

Garbage collector

JITTER

Concurrence

Debugging

1

Q/A

Page 6: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : fonctionnement général du garbage collector

Fondamentaux sur le Garbage Collector (GC pour les intimes)

• Le GC gère la mémoire• Le GC est de type « générationnel » car :

– Plus un objet est récent, plus courte sera sa durée de vie– Plus un objet est vieux, plus longue sera sa durée de vie– Réclamer la mémoire sur une petite portion est plus

rapide que sur toute la mémoire

• Le GC .NET utilise 3 générations

Page 7: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : fonctionnement général du garbage collector

Une animation pour expliquer tout ça

Mémoire allouée dans le processus

A B C D E

Génération 0

Etape 0 (démarrage du processus)• Le GC alloue une portion de mémoire (généralement 32Mo)• Le GC décide d’une quantité de mémoire à allouer à la génération 0• Une fois que c’est fini, il donne la main au code utilisateur

F

Etape 1 (exécution du code utilisateur)• L’utilisateur alloue des objets….• …jusqu’à ce que le budget de la génération 0 soit epuisé

Etape 2 (le GC reprend la main et déclenche une collection en 4 phases)

void main(){ A a = new A(); B b = new B(); C c = new C(); D d = new D(); E e = new E(); F f = new F();

Console.WriteLine("{0}{1}{2}{3}",a,c,e,f);}

F f = new F();

• Phase 1 : le GC pause tous les threads

Console.WriteLine("{0}{1}{2}{3}",a,c,e,f);}

• Phase 2 : il regarde les objets qui ne sont plus utilisés (marquage)

B D

• Phase 3 : il compacte les objets (compactage)

Génération 1

• Phase 4 : il alloue l’objet et redonne la main au code utilisateur

F

Etapes suivantes : le GC continue à gérer les objets de la même façon, en créant la génération 2 dans un deuxième passage (si des objets de la génération 1 sont toujours accessibles) et en allouant plus de mémoire dans le processus si besoin

G H I J

Mémoire allouée dans le processus

Génération 0Génération 2

Mémoire allouée dans le processus

Génération 0Génération 1Génération 2

Page 8: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : fonctionnement général du garbage collector

Les points faibles du GC

• Le GC pause tous les threads pendant qu’il travaille

• Un seul thread fait tout le travail• Marquer et compacter la génération

2 peut-être très long

Les différents moyens de configurer le GC permettent de diminuer l’impact de tel ou tel point

Page 9: Plongée au cœur du Framework .NET 4.5

Configuration

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Garbage collector

JITTER

Debugging

1

Q/A

Concurrence

Page 10: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : une pause philosophique

Une pause philosophique

« Ne change le paramétrage du GC qu’après mûre réflexion »

Parole de sage, par Gordon Liu

http://msdn.microsoft.com/en-us/library/ff647790.aspx

Page 11: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Configuration workstation/server

<configuration> <runtime> <gcServer enabled=“false"/> </runtime> </configuration>

• Mode workstation (par défaut)– Optimisé pour les applications graphiques– Le GC essaie de minimiser le temps passé à

faire son travail, et donc minimise le temps de pause des threads, pour une meilleure expérience utilisateur

– Plusieurs processus sur une même machine peuvent être en mode workstation sans poser de problème de performance

Page 12: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Configuration workstation/server

<configuration> <runtime> <gcServer enabled=“true"/> </runtime> </configuration>

• Mode server– Optimisé pour les applications serveurs– Le GC crée un thread par processeur logique

(avec une priorité haute)– Le GC crée un tas managé et un Large Object

Heap par processeur logique– Le GC part du principe qu’il a toute la

puissance de l’ordinateur à sa disposition : une seule application par ordinateur devrait utiliser ce mode

Page 13: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Configuration concurrent/non concurrent

<configuration> <runtime> <gcConcurrent enabled=“true"/> </runtime> </configuration>

• Mode concurrent (mode par défaut)– Utilise un ou plusieurs threads dédiés à la

collection de la génération 2– Lors d’une collection de génération 2 :

• Les autres threads managés ne sont (pratiquement) pas stoppés

• Une collection de génération 0 ou 1 est possible (mais reste bloquante)

<configuration> <runtime> <gcConcurrent enabled=“false"/> </runtime> </configuration>

• Mode non concurrent– Le thread qui demande la collection fait le travail et

bloque les autres threads

Page 14: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Les différentes collections du point de vue des threads

User thread 1

User thread 2

User thread 3

Workstation / non concurrent

user working

GC working

suspended

Collecte des génération 0, 1 et/ou 2

Page 15: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Les différentes collections du point de vue des threads

User thread 1

User thread 2

User thread 3

Workstation / concurrent (mode par défaut)

user working

foreground GC working

suspendedGC background thread

background GC working

Collecte des génération 0 et 1

Collecte de la génération 2 idle

Page 16: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Les différentes collections du point de vue des threads

User thread 1

User thread 2

User thread 3

Server / concurrent (sur un biprocesseur)

GC background thread CPU 0

Collecte des génération 0 et 1 (répartition du travail entre les threads)

Collecte de la génération 2 (répartition du travail entre les threads

user working

foreground GC working

suspended

background GC working

idle

GC thread CPU 0

GC thread CPU 1

GC background thread CPU 1

Page 17: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Les différentes collections du point de vue des threads

User thread 1

User thread 2

User thread 3

Server / non concurrent (sur un biprocesseur)

Collecte des génération 0, 1 et/ou 2 (répartition du travail entre les threads)

user working

suspended

GC working

idleGC thread CPU 0

GC thread CPU 1

Page 18: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Dernier réglage : System.Runtime.GCSettings.LatencyMode

• 4 valeurs possibles– Batch : par default en Server mode, passe en mode non concurrent– Interactive : par default en Workstation mode, passe en mode

concurrent– LowLatency : à utiliser de manière temporaire, le GC évite le plus

possible les collections de génération 2– SustainedLowLatency : le GC ne fait des collections de génération 2

que si l’OS déclenche le « Low Memory Condition ». Attention, dans ce mode il vaut mieux avoir beaucoup de mémoire vive…

Page 19: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : configuration du garbage collector

Finalement : l’arbre de décision

Appliquer les conseils de Microsoft

Mode = Server / concurrentSi pas suffisant, tenter dans l’ordre :- LowLatency dans les opérations

critiques- SustainedLowLatency (et

acheter beaucoup de RAM !)- Augmenter le nombre de CPU

Mode = Workstation / concurrentSi pas suffisant, tenter dans l’ordre :- LowLatency dans les

opérations critiques- Workstation / non

concurrent- Mettre l’application seule

sur un ordinateur

Mode workstation obligé. Tenter dans l’ordre :- Mode concurrent- Acheter une

nouvelle machine

L’application ne réponds pas

pendant de longs moments

?

Machine mono-

processeur ?

Application seule sur

l’ordinateur ?

Problème de GC ?

oui

non

oui

oui

non

non

Page 20: Plongée au cœur du Framework .NET 4.5

Large Object Heap

Plongée au coeur du framework .NET 4.5 : Large Object Heap

Garbage collector

JITTER

Debugging

1

Q/A

Concurrence

Page 21: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Large Object Heap

Le Large Object Heap (LOH pour les intimes)

• Il est long de compacter (= déplacer) des gros objets

Pour remédier à ce problème :– Le GC alloue les objets considérés « gros » (>85Ko) dans le LOH.– le LOH n’est pas compacté : on gagne en temps dans le GC, mais la création

d’un gros objet est par contre beaucoup plus lente

• Le framework .NET 4.5 apporte une amélioration de 30% de la vitesse d’allocation dans le LOH par rapport au framework 4.

Page 22: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Large Object Heap

Avant, le LOH acceptait les gros objets, mais pas trop gros quand même

• Pour allouer des objets plus gros que 2Go avec le framework 4.5

• Ce n’est disponible qu’en 64bits• Cela ne change pas le fait qu’un Array ne peut pas contenir plus de 0xFFFFFFFF =

4,294,967,295 éléments toutes dimensions confondues, et chaque dimension ne peut pas contenir plus de 0X7FEFFFFF = 2,146,435,071 indexes (0x7FFFFFC7 = 2,147,483,591 si ce sont des bytes)

• La taille maximum du type String ne change pas (à savoir 0x7fffffff = 2,147,483,647 caractères)

<configuration> <runtime> <gcAllowVeryLargeObjects enabled="true" /> </runtime> </configuration>

Page 23: Plongée au cœur du Framework .NET 4.5

Fonctionnement général

Plongée au coeur du framework .NET 4.5 : fonctionnement général du JITTER

Garbage collector

JITTER

Debugging

Q/A

2

Concurrence

Page 24: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : fonctionnement général du JITTER

Le compilateur Just-In-Time (JITTER pour les intimes)

• Transforme à la volée le code IL (résultat de la compilation de source .NET) en code assembleur

• Ne fait la compilation qu’à la demande (just in time), et une seule fois par fonction

• Certaines applications/services ont besoin de démarrer le plus vite possible, et souffrent du temps de JIT

• Il est possible de compiler à l’avance (NGEN.exe) mais cela pose d’autres problèmes

MAIS !

Page 25: Plongée au cœur du Framework .NET 4.5

Multicore JIT

Plongée au coeur du framework .NET 4.5 : Multicore JIT

Garbage collector

JITTER

Debugging

Q/A

2

Concurrence

Page 26: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Multicore JIT

Accélérer le JIT : le Multicore JIT

• Permet d’enregistrer dans un fichier les décisions du JITTER, ainsi que la liste des fonctions à compiler

• Seulement deux lignes à ajouter

• De 20% à 50% de gain sur les démarrages d’application

ProfileOptimization.SetProfileRoot(@"C:\Startup"); ProfileOptimization.StartProfile("Startup.Profile");

Page 27: Plongée au cœur du Framework .NET 4.5

MPGO

Plongée au coeur du framework .NET 4.5 : Managed Profile Guided Optimization

Garbage collector

JITTER

Debugging

Q/A

2

Concurrence

Page 28: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Managed Profile Guided Optimization

• Le code généré par NGEN.exe est généralement moins optimal que celui du JITTER

• Le MPGO remédie (en partie) à ce problème

Améliorer NGEN : le Managed Profile Guided Optimization

Page 29: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Managed Profile Guided Optimization

Le Managed Profile Guided Optimization : comment l’utiliser ?

• 4 étapes– Compilation des assembly– Utilisation de l’exécutable MPGO.exe

– Utilisation de l’exécutable ainsi lancé– Optimisation

Mpgo.exe –scenario Toto.exe –OutDir .\Data –AssemblyList Toto.exe

NGEN.exe .\Data\Toto.exe

Page 30: Plongée au cœur du Framework .NET 4.5

ReadOnly

ReadOnly

Plongée au coeur du framework .NET 4.5 : Managed Profile Guided Optimization

Le Managed Profile Guided Optimization : ça fait quoi exactement ? Espace m

émoire utilisé par l’assem

bly

Espace mém

oire du processus

Page

Fonction 1

Fonction 2

ReadOnly

Copy-on-write

Copy-on-write

Copy-on-write

ReadOnly

ReadOnlyLa mémoire est divisée en pages

Une page peut être :ReadOnly (le code des fonctions)Copy-on-write (les membre statiques)

Localité des fonctionsLocalité des données

Donnée 1

Donnée 2

Le MPGO s’assure de compartimenter la mémoire entre très/peu utilisé et Readonly/Copy-on-write

Fonctions très utilisées

Données très utilisées

Fonctions peu utilisées

Données peu utilisées

Page 31: Plongée au cœur du Framework .NET 4.5

NGEN Automatique

Plongée au coeur du framework .NET 4.5 : NGEN Automatique

Garbage collector

JITTER

Debugging

Q/A

2

Concurrence

Page 32: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : NGEN Automatique

Améliorer NGEN : Le NGEN automatique

• Disponible uniquement sous Windows 8 (version desktop, pas serveur)

• Selon la fréquence d’utilisation, installe ou désinstalle la version native des assembly

• Cibles :– Sous .NET 3.5 et 4.0, le framework seulement– Sous .NET 4.5

• Applications desktop : seulement dans le GAC– Windows Store App : tout

Page 33: Plongée au cœur du Framework .NET 4.5

Re-JIT & Memory Heap Debugging APIs

Plongée au coeur du framework .NET 4.5 : Re-JIT & Memory Heap Debugging APIs

Garbage collector

JITTER

Concurrence

Debugging

Q/A

3

Page 34: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Re-JIT & Memory Heap Debugging APIs APIs

Re-JIT & Memory Heap Debugging APIs

• Re-JIT : il est possible de profiler temporairement du code, puis revenir comme avant, sans redémarrer le processus

• ICoreDebugProcess5 : permet d’énumerer très facilement les objets des tas managés

• …

Page 35: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Garbage collector

JITTER

Concurrence

Debugging

Q/A

4

MotivationsFondamentauxPerformances

Page 36: Plongée au cœur du Framework .NET 4.5

• Croissance d’Internet / du Cloud• Utilisateurs réclament des interfaces plus

disponibles

• La latence provient de deux sources- Calcul CPU intensif- Entrées/Sorties (Disque, Réseaux …)

La latence devient un sujet très important

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 37: Plongée au cœur du Framework .NET 4.5

Synchrone & Asynchrone au quotidien

C’est l’histoire d’un coup de fil

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 38: Plongée au cœur du Framework .NET 4.5

• Offre une meilleure combinaison efficacité/scalabilité• Evite de bloquer des threads

• Appelant n’a pas à coder une couche de plomberie

• Appelant est dégagé de problèmes de threading• Offre une forme d’abstraction vis-à-vis de la

concurrence

Les avantages de l’asynchronisme

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 39: Plongée au cœur du Framework .NET 4.5

À quoi ressemblerait la méthode asynchrone la plus simple possible ?

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 40: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Du synchrone à l’asynchrone

string GetWebPage (string uri){ ... ...}

void Test(){ string html = GetWebPage(“...”); Console.WriteLine (html);}

Page 41: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Utilisation de Action<TResult>

void GetWebPageAsync (string uri, Action<string> continuation){ ... ...}

void Test(){ GetWebPageAsync(“...”, Console.WriteLine);}

Page 42: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Utilisation de Task<TResult>

Task<string> GetWebPageAsync (string uri){ ... ...}

Task<TResult>

Propriété Result Propriété

Exception

Méthode ContinueWith

()

Page 43: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Implémentation avec Task<TResult>

Task<string> GetWebPageAsync (string uri){ ... ...}

void Test(){ GetWebPageAsync(“...”).ContinueWith (task => Console.WriteLine (task.Result));}

Page 44: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Introduction d’une boucle !

string GetWebPage (string uri){ ... ...}

void Test(){ for (int i = 0; i < 5; i++) { string html = GetWebPage(“...”); Console.WriteLine (html); }}

Page 45: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Adaptation du code

Task<string> GetWebPageAsync (string uri){ ... ...}

int _i = 0;void Test(){ GetWebPageAsync(“...”).ContinueWith (task => { Console.WriteLine (task.Result); if (++_i < 5) Test(); });}

Page 46: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Etude de cas – Utilisation de C# 5.0

Task<string> GetWebPageAsync (string uri){ ... ...}

async void Test(){ for (int i = 0; i < 5; i++) { string html = await GetWebPageAsync(“...”); Console.WriteLine (html); }}

Continuation s’exécutera dans le même thread de l’appelant lorsque GetWebPageAsync sera terminée.Donc pas de problème de mise à jour inter-threads vis-à-vis de l’interface graphique.

GetWebPageAsync retourne après avoir initialisée l’appel asynchrone

La boucle est capturée aussi de manière similaire au « yield return »

Page 47: Plongée au cœur du Framework .NET 4.5

• Continuations et code impératif ne peuvent pas être mélangé proprement !

• Ceci explique pourquoi nous avons besoin du support du langage pour produire du code asynchrone facilement maintenable– Moins de ligne de code à écrire– Complexité cyclomatique fortement

réduite

Pourquoi utiliser le support async / await ?

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 48: Plongée au cœur du Framework .NET 4.5

demoASYNC / AWAITSynchrone vs Asynchrone

Plongée au coeur du framework .NET 4.5 : Motivations async/await

Page 49: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await

Garbage collector

JITTER

Debugging

Q/A

Concurrence

4

MotivationsFondamentauxPerformances

Page 50: Plongée au cœur du Framework .NET 4.5

• Task• Task<TResult>• Généralement retourné depuis des APIs async .NET 4.5

– Vous pouvez aussi produire vos propres méthodes asynchrones

• Attendre une tâche qui s’exécute déjà• Attendre directement un appel asynchrone• Ou attendre plusieurs fois• Stocker la tâche et attendre ultérieurement

Quel type pouvons-nous attendre avec le mot clef await?

Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await

Page 51: Plongée au cœur du Framework .NET 4.5

• async Task FooAsync(…);

• Peut-être attendu• “Retourne le contrôle”• Délègue le traitement en

asynchrone

• Utilisable par des Task Helpers

• Utilisable par des méthodes de librairies

• async void Foo_Click(…);

• Ne peut être attendu• “Fire and forget” • Poursuis un flot

d’exécution indépendant

• Utilisable par des event handlers

• Utilisable pour surcharger des méthodes “void”

Retourner une Task versus retourner void

Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await

Page 52: Plongée au cœur du Framework .NET 4.5

• Céder le contrôleawait Task.Delay(5000);await Task.Yield();

• Exécution en tâche de fondvar result = await Task.Run(() => { … work … });

• Composition ParallèleTask first = await Task.WhenAny(task1, task2);var results = await Task.WhenAll(task1, task2);

Task helpers

Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await

Page 53: Plongée au cœur du Framework .NET 4.5

demoASYNC / AWAITMise au point d’un code asynchrone

Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await

Page 54: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Performances async/await

Garbage collector

JITTER

Debugging

Q/A

Concurrence

4

MotivationsFondamentauxPerformances

Page 55: Plongée au cœur du Framework .NET 4.5

• Des années d’expérience dans la production de code synchrone

Analyse d’une simple méthode synchrone

Plongée au coeur du framework .NET 4.5 : Performances async/await

public static void SimpleBody() { Console.WriteLine("Hello, Async World!");}

.method public hidebysig static void SimpleBody() cil managed{ .maxstack 8 L_0000: ldstr "Hello, Async World!" L_0005: call void [mscorlib]System.Console::WriteLine(string) L_000a: ret }

• Des années d’expérience à produire du code optimisé

Page 56: Plongée au cœur du Framework .NET 4.5

• Les méthodes asynchrones ont-elles un coût faible ?

Plongée au coeur du framework .NET 4.5 : Performances du parallélisme

Analyse d'une simple méthode asynchrone

public static async Task SimpleBody() { Console.WriteLine("Hello, Async World!");}

.method public hidebysig static class [mscorlib]System.Threading.Tasks.Task SimpleBody() cil managed{ .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 ) // Code size 32 (0x20) .maxstack 2 .locals init ([0] valuetype Program/'<SimpleBody>d__0' V_0) IL_0000: ldloca.s V_0 IL_0002: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create() IL_0007: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_000c: ldloca.s V_0 IL_000e: call instance void Program/'<SimpleBody>d__0'::MoveNext() IL_0013: ldloca.s V_0 IL_0015: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_001a: call instance class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task() IL_001f: ret}s

.method public hidebysig instance void MoveNext() cil managed{ // Code size 66 (0x42) .maxstack 2 .locals init ([0] bool '<>t__doFinallyBodies', [1] class [mscorlib]System.Exception '<>t__ex') .try { IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0008: ldc.i4.m1 IL_0009: bne.un.s IL_000d IL_000b: leave.s IL_0041 IL_000d: ldstr "Hello, Async World!" IL_0012: call void [mscorlib]System.Console::WriteLine(string) IL_0017: leave.s IL_002f } catch [mscorlib]System.Exception { IL_0019: stloc.1 IL_001a: ldarg.0 IL_001b: ldc.i4.m1 IL_001c: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0021: ldarg.0 IL_0022: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_0027: ldloc.1 IL_0028: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetException( class [mscorlib]System.Exception) IL_002d: leave.s IL_0041 } IL_002f: ldarg.0 IL_0030: ldc.i4.m1 IL_0031: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0036: ldarg.0 IL_0037: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_003c: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetResult() IL_0041: ret}

Page 57: Plongée au cœur du Framework .NET 4.5

• “await task;” se poursuit sur:

– Le SynchronizationContext courant

– Si nul alors « await » utilise le TaskScheduler courant

• Au niveau du code applicatif:– Ce comportement est presque toujours ce que vous

voulez

• Au niveau du code d’une librairie :– Ce comportement n’est jamais ce que vous voulez !

Plongée au coeur du framework .NET 4.5 : Performances async/await

SynchronizationContext

Page 58: Plongée au cœur du Framework .NET 4.5

• Task.ConfigureAwait(bool continueOnCapturedContext)– true (défaut)

• Poste une continuation vers le contexte actuel/scheduler

– false• Si possible, poursuivre l'exécution de la continuation dans une

tâche du pool

• Implications– Performance

• Eviter si possible le marshaling inter-threads, très couteux• Deadlock

– Le code ne devrait pas bloquer le thread de l’interface graphique pour éviter des « dead-locks » potentiels

Plongée au coeur du framework .NET 4.5 : Performances async/await

SynchronizationContext

Page 59: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Performances async/await

Utiliser ConfigureAwait(false)

async void button1_Click(…){ await DoWorkAsync();}

async void button1_Click(…){ DoWorkAsync().Wait();}

async Task DoWorkAsync(){ await Task.Run(…); Console.WriteLine("Done task");}

1. DoWorkAsync appelé depuis thread

graphique

3. Await capture le SynchronizationContext et

engendre une continuation à exécuter lorsque la tâche sera

terminée

4. IHM bloque en attendant que la

méthode DoWorkAsync termine sa

tâche6. thread graphique est

toujours bloqué en attente que l’opération asynchrone se termine.

Deadlock!.ConfigureAwait(false) évite le deadlock.

async Task DoWorkAsync(){ await Task.Run(…).ConfigureAwait(false); Console.WriteLine("Done task");} 2. Task.Run exécute la

tâche dans le pool de threads

5. Task.Run se termine dans le pool & invoque la continuation qui est repoussée dans le thread

graphique

Page 60: Plongée au cœur du Framework .NET 4.5

• Les variables locales doivent survivre à la suspension d’exécution– Compilateur converti les variables locales en champs dans la machine à

état• La machine à état “boxe” les variables à la première suspension

– Plus il y a de variables locales plus il y a d’allocations !

• Éviter les variables inutiles pour minimise le nombre de champs alloués et recopiés

Limiter les variables locales

Plongée au coeur du framework .NET 4.5 : Performances async/await

public static async Task FooAsync() { var dto = DateTimeOffset.Now; var dt = dto.DateTime; await Task.Delay(1000); Console.WriteLine(dt);}

[CompilerGenerated, StructLayout(LayoutKind.Sequential)]private struct <FooAsync>d__0 : <>t__IStateMachine { public DateTimeOffset <dto>5__1; public DateTime <dt>5__2; ...}

public static async Task FooAsync() { var dt = DateTimeOffset.Now.DateTime; await Task.Delay(1000); Console.WriteLine(dt);}

[CompilerGenerated, StructLayout(LayoutKind.Sequential)]private struct <FooAsync>d__0 : <>t__IStateMachine { public DateTime <dt>5__2; ...}

Page 61: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 4.5

Garbage collector

JITTER

Debugging

Q/A

Concurrence

4Quoi de neuf en 4.5

?

Page 62: Plongée au cœur du Framework .NET 4.5

• ConcurrentExclusiveSchedulerPair– Fourni un support pour orchestrer des tâches de type lecteur/écrivain

• CancellationTokenSource intégration d’un timeout– Nouveauté CancellationTokenSource(timeout).Token

• ThreadLocal<T>.Values– Facilite l’implémentation du pattern Fork/Join avec réduction

• TaskCreationOptions– Plus de contrôle avec l’intégration de code provenant de tierces parties

• DenyChildAttach, HideScheduler

• EnumerablePartitionerOptions– Nouvelle option NoBuffering

• …

Encore plus d’options pour contrôler l’exécution

Plongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 4.5

Page 63: Plongée au cœur du Framework .NET 4.5

demoCONTRÔLER L’EXÉCUTIONConcurrentExclusiveSchedulerPair

Plongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 4.5

Page 64: Plongée au cœur du Framework .NET 4.5

demoPlongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 4.5

PERFORMANCE ENTRE 4.0 ET 4.5

Page 65: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 4.5

.NET 4.5 & Visual Studio 2012

Parallel Pattern LibraryTask Parallel Library

PLINQ

Managed Native

WindowsOperating System

Runtime

Programming Models

CLR ThreadPool

Task Scheduler

Resource Manager

Data

Stru

cture

s Data

Str

uct

ure

s

Tools

Tooling

Parallel Debugger

Concurrency Visualizer

AsyncAgent

sLibrar

y

Stacks

Tasks

Watch

CPU

Threads

Cores

C#/VB/F#

AsyncDataflo

w C++AMP

DirectX

GPU

CPU GPU

ConcRT

Task Scheduler

Resource Manager

New Updated

IEnumerable<T> TakeTop<T>( this IEnumerable<T> source, int count){ return source .AsParallel() .OrderBy(k => k) .Take(count);}

var tl = new ThreadLocal<int>(trackAllValues: true);Parallel.For(0, 1000, i =>{ tl.Value += Compute(i);});int result = tl.Values.Sum();

var consumer = new ActionBlock<int>( item => Process(item));…consumer.Post(42);consumer.Post(43);…

async Task<string> ReplaceAsync(Stream input, string oldText, string newText){ string contents = await new StreamReader(input).ReadToEndAsync(); return contents.Replace(oldText, newText); }

Task t = Task.WhenAny( Task.Delay(10000)), Task.Run(() => Parallel.ForEach(…)));

Page 66: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Q/A

Garbage collector

JITTER

Concurrence

Debugging

Q/A5

Page 67: Plongée au cœur du Framework .NET 4.5

Plongée au coeur du framework .NET 4.5 : Sources

Sources

• CLR via C# by Jeffrey Richter (the best !)• http://blogs.msdn.com/b/dotnet• http://msdn.microsoft.com/en-us/magazine/hh882452.aspx• http://www.techbubbles.com/microsoft/multicore-jit-in-net-framework-4-5/• http://msdn.microsoft.com/en-us/library/0xy59wtx(v=vs.110).aspx• http://msdn.microsoft.com/en-us/library/e7k32f4k(v=vs.110).aspx• http://blogs.microsoft.co.il/blogs/pavely• http://blogs.msdn.com/b/davbr• http://blogs.msdn.com/b/pfxteam/• http://blogs.microsoft.co.il/blogs/sasha• http://eknowledger.wordpress.com/2012/04/27/clr-4-5-managed-profile-guided-optimizati

on-mpgo/

Page 68: Plongée au cœur du Framework .NET 4.5

Formez-vous en ligne

Retrouvez nos évènements

Faites-vous accompagner gratuitement

Essayer gratuitement nos solutions IT

Retrouver nos experts Microsoft

Pros de l’ITDéveloppeurs

www.microsoftvirtualacademy.com

http://aka.ms/generation-app

http://aka.ms/evenements-developpeurs

http://aka.ms/itcamps-france

Les accélérateursWindows Azure, Windows Phone,

Windows 8

http://aka.ms/telechargements

La Dev’Team sur MSDNhttp://aka.ms/devteam

L’IT Team sur TechNethttp://aka.ms/itteam