76 votes

La lenteur est le reflet

J'ai récemment créé une couche d'interface pour distinguer le DataAccessProvider de notre couche de logique métier. Avec cette approche, nous pouvons modifier notre choix de DataAccessProvider à tout moment en modifiant les valeurs dans Web / App.Config. (plus de détails peuvent être donnés si nécessaire).

Quoi qu'il en soit, pour ce faire, nous utilisons la réflexion afin d'accomplir notre classe DataProvider sur laquelle nous pouvons travailler.

 /// <summary>
/// The constructor will create a new provider with the use of reflection.
/// If the assembly could not be loaded an AssemblyNotFoundException will be thrown.
/// </summary>
public DataAccessProviderFactory()
{
    string providerName = ConfigurationManager.AppSettings["DataProvider"];
    string providerFactoryName = ConfigurationManager.AppSettings["DataProviderFactory"];
    try
    {
    	activeProvider = Assembly.Load(providerName);
    	activeDataProviderFactory = (IDataProviderFactory)activeProvider.CreateInstance(providerFactoryName);
    }
    catch
    {
    	throw new AssemblyNotFoundException();
    }
}
 

Mais maintenant je me demande à quel point la réflexion est lente?

86voto

Marc Gravell Points 482669

Dans la plupart des cas: plus que assez rapide. Par exemple, si vous utilisez cette fonction pour créer un DAL objet wrapper, le temps pris pour créer l'objet par la réflexion sera minuscule par rapport au temps qu'il faut pour se connecter à un réseau. Ainsi, l'optimisation, ce serait une perte de temps.

Si vous êtes en utilisant la réflexion dans une boucle serrée, il y a des astuces pour l'améliorer:

  • les génériques (à l'aide d'un wrapper where T : new() et MakeGenericType)
  • Delegate.CreateDelegate (pour un typée délégué; ne fonctionne pas pour les constructeurs)
  • Reflection.Emit - hardcore
  • Expression (comme Delegate.CreateDelegate, mais plus souple, et travaille pour les constructeurs)

Mais pour vos besoins, CreateInstance est parfaitement bien. S'en tenir à cela, et de garder les choses simples.


Edit: alors que le point sur la performance relative reste, et bien que la chose la plus importante demeure: "mesurer", je me dois de préciser certains. Parfois... il n' importe. Mesurez d'abord. Toutefois, si vous trouvez qu'il est trop lent, vous pouvez jeter un oeil à quelque chose comme FastMember, qui fait tout l' Reflection.Emit code tranquillement dans le fond, pour vous donner une bonne API; par exemple:

var accessor = TypeAccessor.Create(type);
List<object> results = new List<object>();
foreach(var row in rows) {
    object obj = accessor.CreateNew();
    foreach(var col in cols) {
        accessor[obj, col.Name] = col.Value;
    }
    results.Add(obj);
}

ce qui est simple, mais sera très rapide. Dans l'exemple particulier-je mentionner à propos d'un DAL wrapper - si vous faites cela beaucoup, pensez à quelque chose comme dapper, ce qui fait tout l' Reflection.Emit code en arrière-plan pour vous donner le plus rapidement possible, mais facile à utiliser l'API:

int id = 12345;
var orders = connection.Query<Order>(
    "select top 10 * from Orders where CustomerId = @id order by Id desc",
    new { id }).ToList();

21voto

majkinetor Points 2375

Ses plus lent par rapport aux non-réfléchissant code. La chose importante n'est pas si lente, mais si son lent , là où il faut. Par exemple, si vous instancier des objets à l'aide de la réflexion dans l'environnement web devrait concurency peut s'élever jusqu'à 10K, ce sera lent.

De toute façon, il est bon de ne pas être préoccupé au sujet de la performance à l'avance. Si les choses s'avère être lent, vous pouvez toujours les accélérer si vous avez conçu les choses correctement, de sorte que les pièces que vous vous attendiez peut-être besoin d'optimisation dans le futur, sont localisées.

Vous pouvez le vérifier sur ce fameux article si vous avez besoin de vitesse:

Dynamique... Mais Rapide: Le Conte des Trois Singes, le Loup et l'DynamicMethod et à l'aide de la classe ilgenerator Classes

11voto

5voto

Enyra Points 3767

La réflexion n'est pas si lente. L'appel d'une méthode par réflexion est environ trois fois plus lent que la méthode normale. Ce n'est pas un problème si vous faites cela une seule fois ou dans des situations non critiques. Si vous l'utilisez 10 000 fois dans une méthode de temps critique, je considérerais de changer la mise en œuvre.

3voto

Martin Peck Points 8078

Autre que de suivre les liens donnés dans d'autres réponses et de s'assurer que vous n'êtes pas écrit "pathalogically mauvais" code alors pour moi, la meilleure réponse à cette question est pour tester vous-même.

Seulement, vous savez où vous les goulets d'étranglement sont, combien de fois votre code de réflexion sera de l'utilisateur, si le code de réflexion seront en boucles serrées etc. Vous connaissez votre entreprise, combien d'utilisateurs peuvent accéder à votre site, ce que la perf exigences.

Toutefois, compte tenu de l'extrait de code vous ai montré ici, alors j'imagine que les frais généraux de la réflexion ne va pas être un problème de masse.

VS.NET web tests et essais de performance des fonctionnalités de prendre la mesure de la performance de ce code assez simple.

Si vous n'utilisez pas la réflexion, ce que votre code ressemble? Quelles sont les limites? Il se peut que vous ne pouvez pas vivre avec les limites que vous vous retrouvez avec si vous supprimez le code de réflexion. Il pourrait être intéressant d'essayer de concevoir ce code sans la réflexion pour voir si c'est possible ou il l'alternative est souhaitable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X