6
votes

Coût de performance des comparaisons de type

Je suis décodé des messages de diffusion d'un flux binaire. Je crée des objets de message de types de variation en fonction des messages arrivés. Ils dérivent tous d'une base CommSMessage code> type. Tout va bien et dandy.

ailleurs dans mon code, j'ai besoin de réagir à ces messages, alors j'ai besoin de savoir quel type de message c'est. P>

actuellement je fais: p>

void ProcessIncomingMessage(CommsMessage msg)
{
    switch (msg.MessageType)
    {
         case MessageType.Type1:  return ProcessMessageType1(msg as MessageType1);
         case MessageType.Type2:  return ProcessMessageType2(msg as MessageType2);

         //etc
    }
}


1 commentaires

3 Réponses :


8
votes

Avez-vous envisagé d'éliminer les jeux de type?

Je suppose que vous avez considéré que vous avez considéré que la mise en place de la méthode virtuelle sur le type code> code> se casserait une abstraction de superposition (par exemple, vous voudrez peut-être une séparation propre du traitement du message du message du message. lui-même). Peut-être considérer peut-être le modèle de visiteur . Cela vous permettra de séparer la classe code> message code> à partir du traitement du message code> code> lui-même. P>

Si vous avez quelque chose de cette structure. p> xxx pré>

Vous pouvez refroidir sur p> xxx pré>

à ce stade, vous avez éliminé les coulées de type. Vous pouvez maintenant réécrire votre code comme P>

void ProcessIncomingMessage(CommsMessage msg) 
{
  new MyVisitor().Visit(msg);
}

class MyVisitor : CommsMessageVisitor
{
    void Accept(Message1 msg1) { ProcessMessageType1(msg1); }
    void Accept(Message1 msg2) { ProcessMessageType2(msg2); }
}


4 commentaires

+1 Pour votre explication / hypothèse Pourquoi le Visteur pouvait être nécessaire ici - sinon, cela semblerait trop tendre ;-)


Je suis d'accord, excédent définitivement à moins que ce soit le cas! Cela semble être un cas assez commun cependant. Vous avez des objets muettes (poco / entités) que vous souhaitez simplement transférer vers des endroits (peut-être partagés entre client / serveur ou juste à différents niveaux d'abstraction). Vous voulez souvent un traitement différent de celui-ci, mais la poussant dans des méthodes virtuelles expose trop. Le modèle de visiteur est génial pour quitter la mise en œuvre de ces méthodes.


Yup, et étant donné les noms des types et des méthodes concernés, le vôtre est une hypothèse raisonnable.


Une hypothèse correcte. C'est parfait, merci! Toute la chose des comparaisons de type se sentit tort pour moi, mais je ne pouvais pas voir un moyen propre pour les séparer. Il est temps de terminer les modèles de conception de lecture, je pense!



2
votes

Notez que votre code n'est pas syntaxiquement valide, car les types de retour sont void code>, mais de toute façon.

Eh bien, je ne suis pas trop sûr de la différence de performance des deux alternatives que vous montrez. . Cependant, au moins FXCOP serait " suggérer a > "Ce qui suit au lieu de votre première solution: P>

public class CommsMessage
{
    public virtual void ProcessMessage()
    {
       // Common stuff.
    }
}

public class MessageType1 : CommsMessage
{
   public override void ProcessMessage()
   {
      base.ProcessMessage();
      // type 1 specific stuff.
   }
}

// ...

void ProcessIncomingMessage(CommsMessage msg)
{
   msg.ProcessMessage();
}


1 commentaires

+1 de moi - comme suivi de NULL Vérifier les surperforms est puis comme



1
votes

Pour ajouter aux excellentes réponses ci-dessus:

Dans le profilage de la performance J'ai remarqué que l'utilisation d'utiliser est suivie de comme a effectivement une performance inférieure à un seul comme suivi d'une vérification null. Ne vous attendez pas à ce que le compilateur optimise automatiquement quoi que ce soit. Vous avez raison de supposer que dans le code de messagerie (ou autrement des sections critiques de performance) que la conception de la vitesse est d'une importance primordiale.

De loin la distribution la plus rapide est une distribution statique qui surperformez comme c.-à-d. Var Message = (SPÉCIFICTYTYPE) Basemessage surperformer var message = basemessage comme spécificype . Ceci est un point d'intérêt que comme une distribution statique ne peut pas vous aider dans votre cas.

Comme deux réponses ont déjà mentionné l'exécution ci-dessus de manière polymorphe à l'aide d'un motif de conception pourraient être la meilleure solution, car elle n'ajoute qu'un appel de méthode virtuelle. Extraire la méthode courante à une classe abstraite (ou la signature de méthode courante à l'interface) est de loin la solution la plus élégante. Il y a une surcharge d'appel d'une méthode virtuelle, mais cela peut être atténué en marquant les méthodes spécifiques sur des types dérivés à l'aide du mot clé scellé .

Utilisez enfin des génériques dans la mesure du possible pour éliminer les mises en tant que méthodes génériques constitue une optimisation du temps de compilation par opposition à la coulée de temps d'exécution.

meilleures salutations,


0 commentaires