Question

Dans un projet sur lequel je travaille, il existe de très grandes collections (éléments 1M-1B), et les choses sont principalement modifiées en tant que collections.

C’est une application en temps réel et la performance est donc primordiale.

Certaines opérations, telles que Reverse, BinarySearch (possible?), etc., souffriront plus que d’autres comme Select, etc.

Est-il possible d'implémenter son propre IEnumerable avec d'éventuels MoveNext, MovePrev, etc. et ses propres extensions LINQ implémentées qui en tirent parti?

Si cela se produit, cela se produira à la fin du projet. Parce que nous devons d'abord le faire fonctionner, puis le rendre plus rapide.

Tout compte fait, cela ne devrait pas représenter trop de travail, non?

Était-ce utile?

La solution

Il est très certainement possible de créer votre propre implémentation de Enumerable , ce qui peut constituer un cas particulier dans certaines situations. Vous souhaitez en principe détecter vos propres types de collection (ou éventuellement simplement des collections telles que Liste < T > ) et utiliser une implémentation plus efficace, le cas échéant.

J'ai un exemple de projet que j'ai utilisé pour effectuer une démonstration et implémenter LINQ to Objects dans un heure " que vous voudrez peut-être regarder pour des exemples. Ce n'est pas une implémentation complète et en particulier c'est moins efficace que le vrai LINQ to Objects - mais vous pouvez toujours trouver cela intéressant.

Vous pouvez également vous rendre compte que i4o (LINQ indexée) fait tout ce dont vous avez besoin à la livraison - ou que vous feriez mieux de contribuer à cela que de partir de zéro. À voir.

Rappelez-vous qu’à la fin de la journée, LINQ est fondamentalement un joli design associé à du sucre syntaxique. Le compilateur C # ne connaît rien de spécial sur System.Linq.Enumerable , par exemple.

Autres conseils

Si vous voulez vraiment la performance, vous pouvez en faire beaucoup. Rappelez-vous que la sélection suivante:

var result = from element in collection
             where element.Id == id
             select element;

Compile en tant que:

var result = collection.Where(element => element.Id == id);

Si vous créez la méthode suivante pour le type de collection , vous pouvez exploiter le fait que l'action principale correspond à l'égalité du membre Id et gérer la demande de manière optimisée. L'important est d'identifier correctement les opérations critiques sur les performances de votre collection et de choisir les algorithmes appropriés (complexité) pour les exécuter.

public IEnumerable<TElement> Where(Expression<Func<TElement, bool>> selector)
{
    // detect equality of the Id member and return some special value
}

Envisagez System.Linq.Enumerable.Reverse () - cette méthode énumère entièrement le IEnumerable avant de renvoyer le premier résultat.

Si votre requête est myCollection.Reverse (). Take (10), et que votre collection contient des milliards d'éléments, c'est une idée horrible d'énumérer des milliards d'éléments pour en extraire 10.

Si vous avez fourni une méthode Reverse sur votre propre type, vous pouvez fournir une meilleure implémentation qui effectue simplement une boucle en arrière sur la collection (éventuellement par index).

La clé de ceci est de fournir votre propre type où vous contrôlez les implémentations. Vous ne pouvez pas utiliser les implémentations qui fonctionnent pour tous les IEnumerable < T > , car ces implémentations ne tireront pas pleinement parti des fonctionnalités de votre type de collection personnalisée.

  

Est-il possible de mettre en œuvre son propre   IEnumerable avec possible MoveNext,   MovePrev, etc. et LINQ implémenté   extensions qui tirent avantage de   ceux-ci?

IEnumerable (ou plus précisément, IEnumerator ) n'a pas de MovePrev . Vous pouvez définir une interface:

public interface IReversable<T> : IEnumerable<T>
{
    IEnumerator<T> GetReverseEnumerator();
}

Ceci peut être implémenté par n'importe quel conteneur prenant en charge une énumération inverse efficace.

Vous pourriez alors écrire une surcharge de Reverse (la méthode d'extension) pour travailler à partir de cette nouvelle interface, ainsi que des classes de collection qui implémentent l'interface, etc. Ensuite, vous devrez utiliser ces collections. classes au lieu de classes standard telles que List < T > .

Mais (je n'ai pas Reflector sous la main pour vérifier), il se peut que le Reverse intégré soit suffisamment intelligent pour faire les choses rapidement, s'il peut obtenir le IList de la collection, ce qui optimiserait de toute façon les cas les plus courants.

Il n’ya donc pas forcément d’intérêt dans ce type d’approche.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top