Ma question est la suivante:DynamicMethod pour ConstructorInfo.Invoke, que dois-je prendre en compte?
Si je vais construire un quels types d'IL faire l'objet DynamicMethod, ce qui correspond à un appel ConstructorInfo.Invoke, je dois mettre en œuvre pour faire face à tous (ou la plupart) types des arguments, quand je peux garantir que le bon type et le nombre d'arguments va être passé avant que je fasse l'appel?
Contexte
Je suis sur ma 3ème itération de mon conteneur IoC, et fait actuellement un certain profilage pour savoir s'il y a des domaines où je peux facilement raser de grandes quantités de temps utilisé. Une chose que j'ai remarquée est que lors de la résolution d'un type concret, finalement je me retrouve avec un constructeur appelé, en utilisant ConstructorInfo.Invoke, passant dans un tableau d'arguments que j'ai travaillé. Ce que j'ai remarqué est que la méthode invoke a un peu de surcharge, et je me demande si la plupart de ceci est juste des implémentations différentes des mêmes contrôles que je fais. Par exemple, en raison du code correspondant du constructeur, pour trouver un constructeur correspondant pour les noms de paramètres prédéfinis, les types et les valeurs que j'ai passés, il est impossible que cet appel d'invocation particulier ne finisse pas avec quelque chose il devrait être capable de faire face, comme le nombre correct d'arguments, dans le bon ordre, du bon type, et avec des valeurs appropriées.
Lors d'une session de profilage contenant un million d'appels à ma méthode de détermination, puis la remplacer par une mise en œuvre DynamicMethod qui imite l'appel Invoke, les horaires de profilage était comme ceci:
- ConstructorInfo.Invoke: 1973ms
- DynamicMethod: 93ms
cela représente environ 20% de la durée totale de cette application de profilage. En d'autres termes, en remplaçant l'appel ConstructorInfo.Invoke par un DynamicMethod qui fait de même, je suis capable de réduire de 20% le temps d'exécution des services de base en usine (tous les appels de résolution se terminent par un appel constructeur).
Je pense que c'est assez important, et justifie un examen plus approfondi de combien de travail serait de construire un générateur DynamicMethod stable pour les constructeurs dans ce contexte. Ainsi, la méthode dynamique prendrait un tableau d'objets et renverrait l'objet construit, et je connais déjà l'objet ConstructorInfo en question.
Par conséquent, il semble que la méthode dynamique serait composée des éléments suivants IL:
l001: ldarg.0 ; the object array containing the arguments
l002: ldc.i4.0 ; the index of the first argument
l003: ldelem.ref ; get the value of the first argument
l004: castclass T ; cast to the right type of argument (only if not "Object")
(repeat l001-l004 for all parameters, l004 only for non-Object types,
varying l002 constant from 0 and up for each index)
l005: newobj ci ; call the constructor
l006: ret
Y at-il autre chose que je dois considérer?Notez que je suis conscient que la création de méthodes dynamiques ne sera probablement pas disponible lors de l'exécution de l'application en "mode d'accès réduit" (parfois le cerveau n'abandonnera pas ces termes), mais dans ce cas, je peux facilement détecter cela et appeler simplement le constructeur d'origine comme précédemment, avec le surcoût et tout.
Donc, fondamentalement, puisque j'ai l'objet Type pour chaque paramètre, si le Type.IsValueType renvoie true, au lieu de TYPE castclass, j'utilise unbox.any TYPE à la place? –
Oui, cela devrait suffire à couvrir tous les types de paramètres. –
Merci, je vais ajouter un tas de tests unitaires pour vérifier toutes les combinaisons que je peux penser, mais cela semble que ça pourrait juste fonctionner :) –