Mot clé dynamic C # – Pénalité d’exécution?

Définir une instance dynamic en C # signifie-t-il:

  1. Le compilateur n’effectue pas de vérification de type à la compilation, mais la vérification à l’exécution a lieu comme elle le fait toujours pour toutes les instances.

  2. Le compilateur n’effectue pas de vérification de type à la compilation, mais une vérification à l’exécution a lieu, contrairement à d’autres instances non dynamics.

  3. Identique à 2, et cela vient avec une pénalité de performance (sortingvial? Potentiellement significatif?).

La question est très déroutante.

Définir une instance dynamic en C # signifie-t-il:

Par “définir une instance”, voulez-vous dire “déclarer une variable”?

Le compilateur n’effectue pas de vérification de type à la compilation, mais la vérification à l’exécution a lieu comme elle le fait toujours pour toutes les instances.

Qu’entendez-vous par “vérification au moment de l’exécution, comme c’est toujours le cas”? Quel contrôle d’exécution aviez-vous en tête? Pensez-vous à la vérification effectuée par le vérificateur d’IL , ou pensez-vous à des vérifications de type à l’exécution causées par des conversions ou quoi?

Peut-être serait-il préférable d’expliquer simplement ce que fait “dynamic”.

Tout d’abord, dynamic est un type du sharepoint vue du compilateur . Du sharepoint vue de la CLR , la dynamic n’existe pas; au moment où le code est réellement exécuté, toutes les occurrences de “dynamic” ont été remplacées par “object” dans le code généré.

Le compilateur traite les expressions de type dynamic exactement comme des expressions de type object , à la différence que toutes les opérations sur la valeur de cette expression sont analysées, compilées et exécutées à l’exécution, en fonction du type d’exécution de l’instance. L’objective est que le code exécuté ait la même sémantique que si le compilateur connaissait les types d’exécution au moment de la compilation.

Votre question semble porter sur la performance.

La meilleure façon de répondre aux questions sur les performances est d’ essayer et de découvrir – ce que vous devriez faire si vous avez besoin de nombres durs est d’écrire le code dans les deux sens, en utilisant des types dynamics et connus, puis de sortir un chronomètre et de comparer les temps. C’est la seule façon de savoir.

Cependant, considérons les implications en termes de performances de certaines opérations à un niveau abstrait. Supposons que vous ayez:

int x = 123; int y = 456; int z = x + y; 

L’ajout de deux nombres entiers prend environ un milliardième de seconde sur la plupart des matériels de nos jours.

Que se passe-t-il si nous le rendons dynamic?

 dynamic x = 123; dynamic y = 456; dynamic z = x + y; 

Maintenant qu’est-ce que cela fait au moment de l’exécution? Cette boîte 123 et 456 dans les objects, ce qui alloue de la mémoire sur le tas et fait des copies.

Ensuite, il lance le DLR et demande au DLR “ce site de code a-t-il déjà été compilé avec les types pour x et y étant int et int?”

La réponse dans ce cas est non. Le DLR démarre ensuite une version spéciale du compilateur C # qui parsing l’expression d’addition, effectue une résolution de surcharge et crée une arborescence d’expression décrivant le lambda qui ajoute deux ints. Le DLR comstack ensuite ce lambda en IL généré dynamicment, que le compilateur Jit jits ensuite. Le DLR met alors en cache cet état compilé pour que le compilateur ne soit pas obligé de refaire tout ce travail à la seconde demande.

Cela prend plus d’une nanoseconde. Cela prend potentiellement plusieurs milliers de nanosecondes.

Cela répond-t-il à vos questions? Je ne comprends pas vraiment ce que vous demandez ici, mais je devine.

Pour autant que je sache, la réponse est 3.

Tu peux le faire:

 dynamic x = GetMysteriousObject(); x.DoLaundry(); 

Comme le compilateur ne vérifie pas le type sur x , il comstackra ce code, en supposant que vous sachiez ce que vous faites.

Mais cela signifie qu’une DoLaundry supplémentaire à l’exécution doit avoir lieu: à savoir, examiner le type de x , voir s’il a une méthode DoLaundry et ne pas l’exécuter, et l’exécuter.

En d’autres termes, le code ci-dessus est un peu comme faire ceci (je ne dis pas que c’est la même chose, juste faire une comparaison):

 object x = GetMysteriousObject(); MethodInfo doLaundry = x.GetType().GetMethod( "DoLaundry", BindingFlags.Instance | BindingFlags.Public ); doLaundry.Invoke(x, null); 

Ce n’est certainement pas anodin, même si cela ne veut pas dire que vous allez être capable de voir un problème de performance à l’œil nu.

Je pense que la mise en œuvre de dynamic implique une mise en cache en coulisse assez douce, qui est effectuée pour vous. Ainsi, si vous exécutez à nouveau ce code et que x est du même type, il sera beaucoup plus rapide.

Ne me retiens pas pour ça, cependant. Je n’ai pas beaucoup d’expérience en dynamic ; c’est simplement comme cela que je comprends que cela fonctionne.

Déclarer une variable comme dynamic revient à la déclarer comme object . Dynamic obtient simplement un autre indicateur indiquant que la résolution du membre est différée au moment de l’exécution .

En termes de pénalité de performance – cela dépend de l’object sous-jacent. C’est tout l’intérêt des objects dynamics, non? L’object sous-jacent peut être un object Ruby ou Python ou un object C #. Le DLR déterminera au moment de l’exécution comment résoudre les appels des membres sur cet object et cette méthode de résolution déterminera la pénalité de performance.

Cela dit, il y a certainement une pénalité de performance.

C’est pourquoi nous n’allons tout simplement pas commencer à utiliser des objects dynamics partout.

Eh bien, la variable est typée de manière statique pour être du type dynamic mais au-delà, le compilateur ne vérifie pas pour autant que je sache.

La liaison de type est faite au moment de l’exécution et oui, il y a une pénalité, mais si dynamic est la seule option, alors tant pis. Si vous pouvez résoudre le problème en utilisant le typage statique, faites-le. Cela étant dit, le DLR appelle la mise en cache du site, ce qui signifie qu’une partie des frais généraux est réduite car la plomberie peut être réutilisée dans certains cas.

Tant que je ne comprends pas dynamic il ne fait que contourner la vérification du temps de compilation. la résolution du type se produit au moment de l’exécution, comme pour tous les types. donc je ne pense pas qu’il y ait une pénalité de performance associée à cela.