Domanda

In un progetto a cui sto lavorando, ci sono raccolte davvero enormi (elementi 1M-1B) e le cose sono modificate principalmente come raccolte.

È un'app in tempo reale, quindi le prestazioni sono fondamentali.

Per alcune operazioni, come Reverse, BinarySearch (possibile?), ecc. subiranno più di altre come Select, ecc.

È possibile implementare il proprio IEnumerable con possibili MoveNext, MovePrev, ecc. e le proprie estensioni LINQ implementate che ne traggono vantaggio?

Se questo accadrà, accadrà alla fine del progetto. Perché dobbiamo prima farlo funzionare, quindi renderlo più veloce.

Tutto sommato questo non dovrebbe essere troppo lavoro, giusto?

È stato utile?

Soluzione

È assolutamente possibile creare la propria implementazione di Enumerable che potrebbe in alcuni casi particolari. In pratica vorresti rilevare i tuoi tipi di raccolta (o eventualmente solo raccolte come List < T > ) e utilizzare un'implementazione più efficiente ove applicabile.

Ho un progetto di esempio che ho usato per demo " implementazione LINQ to Objects in un ora " che ti potrebbe piacere vedere esempi. Non è un'implementazione completa e in particolare è meno efficiente del vero LINQ to Objects - ma potresti ancora trovarlo interessante.

In alternativa, potresti scoprire che i4o (LINQ indicizzato) fa tutto ciò che ti serve immediatamente - o che sarebbe meglio contribuire a questo che a partire da zero. Vale la pena dare un'occhiata.

Ricorda solo che alla fine della giornata, LINQ è fondamentalmente un bel design abbinato allo zucchero sintattico. Il compilatore C # non conosce nulla speciale su System.Linq.Enumerable , per esempio.

Altri suggerimenti

Se vuoi davvero prestazioni, puoi fare abbastanza. Ricorda che la seguente selezione:

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

Compila come:

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

Se crei il seguente metodo per il tipo di collection , puoi sfruttare il fatto che l'azione primaria è l'uguaglianza del membro Id e gestire la richiesta in modo ottimizzato. L'importante è identificare correttamente le operazioni critiche per le prestazioni della tua collezione e scegliere gli algoritmi corretti (ovvero la complessità) per eseguirli.

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

Considerare System.Linq.Enumerable.Reverse () - questo metodo enumera completamente IEnumerable prima di restituire il primo risultato.

Se la tua query è myCollection.Reverse (). Take (10) e la tua raccolta ha miliardi di oggetti, è una brutta idea enumerare i miliardi di oggetti per ottenere 10.

Se hai fornito un metodo Reverse sul tuo tipo, potresti fornire un'implementazione migliore che si sposta semplicemente indietro sull'insieme (eventualmente tramite indice).

La chiave di ciò è fornire il tuo tipo in cui controlli le implementazioni. Non puoi utilizzare le implementazioni che funzionano per tutti IEnumerable < T > perché tali implementazioni non trarranno il massimo vantaggio dalle funzionalità del tuo tipo di raccolta personalizzato.

  

È possibile implementare il proprio   IEnumerable con possibile MoveNext,   MovePrev, ecc. E proprio LINQ implementato   estensioni che ne traggono vantaggio   questi?

IEnumerable (o più correttamente, IEnumerator ) non ha MovePrev . È possibile definire un'interfaccia:

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

Questo potrebbe essere implementato da qualsiasi contenitore che supporti una efficiente enumerazione inversa.

Potresti quindi scrivere un sovraccarico di Reverse (il metodo di estensione) per lavorare su questa nuova interfaccia e sulle classi di raccolta che implementano l'interfaccia, ecc. E poi dovresti usare quelle raccolte classi anziché standard come List < T > .

Ma (non ho Reflector a portata di mano per controllare) potrebbe essere che il Reverse integrato sia abbastanza intelligente da fare le cose nel modo più veloce se può ottenere IList dalla raccolta, che ottimizzerebbe comunque i casi più comuni.

Quindi potrebbe non esserci molto senso in questo tipo di approccio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top