2012-05-14 8 views
13

Sto creando una libreria di cui sono un test delle prestazioni. In esso generico una volta Dictionary<Type, X>. Gli articoli sono attualmente inseriti in un ordine casuale. Il dizionario rimane invariato durante la vita dell'applicazione.Alternativa più rapida del dizionario <Type, X>?

Viene quindi utilizzato frequentemente per cercare gli articoli. La ricerca è uno dei colli di bottiglia più grandi nella libreria.

Sì, sono microtimizzante, ma per imparare. Mi chiedo se ci sia un modo migliore per ottenere prestazioni di ricerca?

Aggiornamento

ho usato dotTrace per misurare le prestazioni. Il report + dotTrace si trova nel mio computer di casa, quindi non ho il rapporto qui (potrebbe averlo caricato da qualche altra parte).

ho usato le prove trovate qui: https://github.com/danielpalme/IocPerformance

La definizione del dizionario si trova qui: https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs

(ho creato il contenitore venerdì scorso, non aspettatevi troppo)

Update2

Performance breakdown

Dictionary.TryGetValue prende 101ms totali di Resolve (totale 251ms) che è il 40,2% se ho interpretato correttamente i numeri.

+4

a: Quanti tipi/coppie nei dati, b: cosa ti fa pensare che sia un collo di bottiglia? (come avete misurato? possiamo vedere uno qualsiasi del codice di ricerca?) –

+2

ec: i chiamanti utilizzano tipi statici (ad esempio 'int' ecc.) o stanno utilizzando oggetti di tipo" Tipo "a causa del riflesso? se i chiamanti conoscono i tipi staticamente, ci sono alcuni trucchi che potrebbero essere utilizzati –

+0

@MarcGravell: potresti estendere un po 'su questi trucchi (risposta o collegamento) in quanto è un argomento interessante. grazie – mathieu

risposta

1

Le prestazioni di riferimento per contenitori IoC da Daniel Palme (ma quelli di altri pure) è un po 'fuorviante, poiché il punto di riferimento risolve grafi di oggetti molto superficiale dal contenitore (sebbene esse indicano chiaramente che le prestazioni le differenze tra i contenitori sono grandi). Questo non è realistico, perché la maggior parte delle applicazioni (che usano correttamente DI) avrà grafici di oggetti che contengono dosens di oggetti. Quando si esegue questa operazione, è necessario risolvere solo l'oggetto radice e, quando il contenitore è scritto correttamente, significa che si avrà una sola chiamata a Dictionary<T,V>.TryGetValue per richiesta (web) nella maggior parte delle situazioni (o al massimo solo alcune). Per questo motivo, le prestazioni di Dictionary<T, V> non rappresentano un problema.

Credo che il più grande parte del costo delle prestazioni di Dictionary<T,V> dove TKey è System.Type, ha a che fare con il costo delle prestazioni di generare un codice hash per il dato Type. Ogni volta che si chiama TryGetValue, è necessario chiamare Type.GetHashCode(). GetHashCode è virtuale (non può essere inline) e quel metodo chiama altri 3 metodi virtuali. Alla fine viene effettuata una chiamata statica (esterna) a RuntimeHelpers.GetHashCode(key).

In altre parole, si sarebbe in grado di ottimizzare le prestazioni di scrivere una specifica (non generici) Classe di dizionario che utilizza Type come una chiave e invece di chiamare Type.GetHashCode() si dovrebbe chiamare RuntimeHelpers.GetHashCode(key).

UPDATE (2013/04/05):

Alcuni mesi fa ho cercato di migliorare le prestazioni del contenitore DI Io sostengo e ho giocato con l'ottimizzazione della parte dizionario. Ho scritto il mio dizionario che ha chiamato direttamente RuntimeHelpers.GetHashCode(key) (e ho saltato le chiamate virtuali) ma alla fine i guadagni di prestazioni erano così bassi (circa l'1% nei benchmark di Palme) che ho deciso di annullare queste modifiche al codice. Quindi la mia attuale comprensione è che il costo reale delle prestazioni con Dictionary<Type, X> è in realtà tutto ciò che accade all'interno di RuntimeHelpers.GetHashCode(key).

2

Se il tipo è in fase di compilazione definito, si può provare per la sua attuazione in questo modo:

static class ValueFor<T> 
{ 
    // you get another field per type T 
    public static X X { get; private set; } 

    internal static SetUpValue(X value) { X = value; } 
} 

Proprio accesso utilizzando questo.

var myIntX = ValueFor<int>.X; 
+0

Purtroppo no. I mapping sono creati dall'utente/dev in fase di esecuzione (come per tutti i contenitori IoC) – jgauffin

Problemi correlati