plongée au cœur du framework .net 4.5
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.TRANSCRIPT
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 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
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 ?
Agenda
Plongée au coeur du framework .NET 4.5 : agenda
Garbage collector JITTER
Concurrence
A
Debugging
1 2
34Q/A5
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
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
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
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
Configuration
Plongée au coeur du framework .NET 4.5 : configuration du garbage collector
Garbage collector
JITTER
Debugging
1
Q/A
Concurrence
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
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
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
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
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
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
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
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
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…
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
Large Object Heap
Plongée au coeur du framework .NET 4.5 : Large Object Heap
Garbage collector
JITTER
Debugging
1
Q/A
Concurrence
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.
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>
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
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 !
Multicore JIT
Plongée au coeur du framework .NET 4.5 : Multicore JIT
Garbage collector
JITTER
Debugging
Q/A
2
Concurrence
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");
MPGO
Plongée au coeur du framework .NET 4.5 : Managed Profile Guided Optimization
Garbage collector
JITTER
Debugging
Q/A
2
Concurrence
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
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
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
NGEN Automatique
Plongée au coeur du framework .NET 4.5 : NGEN Automatique
Garbage collector
JITTER
Debugging
Q/A
2
Concurrence
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
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
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
• …
Plongée au coeur du framework .NET 4.5 : Motivations async/await
Garbage collector
JITTER
Concurrence
Debugging
Q/A
4
MotivationsFondamentauxPerformances
• 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
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
• 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
À quoi ressemblerait la méthode asynchrone la plus simple possible ?
Plongée au coeur du framework .NET 4.5 : Motivations async/await
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);}
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);}
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
()
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));}
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); }}
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(); });}
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 »
• 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
demoASYNC / AWAITSynchrone vs Asynchrone
Plongée au coeur du framework .NET 4.5 : Motivations async/await
Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await
Garbage collector
JITTER
Debugging
Q/A
Concurrence
4
MotivationsFondamentauxPerformances
• 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
• 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
• 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
demoASYNC / AWAITMise au point d’un code asynchrone
Plongée au coeur du framework .NET 4.5 : Fondamentaux async/await
Plongée au coeur du framework .NET 4.5 : Performances async/await
Garbage collector
JITTER
Debugging
Q/A
Concurrence
4
MotivationsFondamentauxPerformances
• 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é
• 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}
• “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
• 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
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
• 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; ...}
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
?
• 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
demoCONTRÔLER L’EXÉCUTIONConcurrentExclusiveSchedulerPair
Plongée au coeur du framework .NET 4.5 : Parallélisme, quoi de neuf en 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
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(…)));
Plongée au coeur du framework .NET 4.5 : Q/A
Garbage collector
JITTER
Concurrence
Debugging
Q/A5
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/
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