2015-12-14 9 views
7

Ho due interfacce. ICacheHolder verrà implementato da una classe che implementa la logica di un oggetto di gioco e IVisualizer che sarà la rappresentazione visiva.Due elenchi contenenti un'interfaccia rispetto a una lista contenente una struttura con due interfacce

public interface ICacheHolder 
{ 
    void updateCacheWithCurrentState(int chachFrame); 

    void resizeCache(int newSize); 

    T getCacheFrame<T>(int cacheIndex, float interpolationToNext) where T : struct; 
} 

public interface IVisualizer 
{ 
    void updateVisualization(ICacheHolder cacheHolder, int cacheIndex, float interpolation); 
} 

Ogni ICacheHolder si collega ad uno IVisualizer oggetto il rapporto è di 1 a 1. Sto cercando di determinare se il suo migliore (prestazioni/memoria saggio) per conservarle in due liste separate o in una lista come struct . Farebbe una grande differenza? Ci sarebbe il pugilato se usassi la versione struct? Ho recon la dimensione della lista sarà da 100 a 1000.

Versione 1:

public class CacheFramework 
{ 
private List<ICacheHolder> cacheHolders = new List<ICacheHolder>(); 
private List<IVisualizer> visualizers = new List<IVisualizer>(); 
... 
} 

Versione 2:

struct SimulationObject 
{ 
    public ICacheHolder CacheHolder; 
    public IVisualizer Visualizer; 
} 
public class CacheFramework 
{ 
private List<SimulationObject> cacheHolder = new List<SimulationObject>(); 
... 
} 

operazioni come Add e Remove non sarà fatto molto frequentemente. Solo all'inizio del gioco potrebbero esserci molte chiamate aggiuntive.

Versione 1:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    if (!cacheHolders.Contains(cacheHolder) && !visualizers.Contains(visualizer)) 
    { 
     cacheHolders.Add(cacheHolder); 
     visualizers.Add(visualizer); 
     return true; 
    } 
    return false; 
} 

Versione 2:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    int index = simulationObjects.FindIndex(
     delegate (SimulationObject simulationObject) 
     { 
      return simulationObject.CacheHolder == cacheHolder || simulationObject.Visualizer == visualizer; 
     } 
     ); 

    if (index >= 0) 
    { 
     SimulationObject newObject; 
     newObject.CacheHolder = cacheHolder; 
     newObject.Visualizer = visualizer; 
     return true; 
    } 
    return false; 
} 

La lista sarà letta in almeno ogni frame attraverso il suo indice.

Ulteriori informazioni: Ogni classe che utilizza ICacheHolder conterrà un List<struct> con dati quali posizione, rotazione o stato. Ogni elemento dell'elenco sarà un'istantanea nel tempo. L'obiettivo è di muoversi nel tempo avanti e indietro.

Edit 1:

Corretto errore in AddSimulationObject Versione 2.

Come sottolineato AddSimulationObject Versione 2 potrebbe essere:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    SimulationObject newObject = new SimulationObject { CacheHolder = cacheHolder, Visualizer = visualizer }; 
    if (simulationObjects.Contains(newObject)) 
    { 
     simulationObjects.Add(newObject); 
     return true; 
    } 
    return false; 
} 

Ma in questo caso avrei bisogno di assicurarsi che cacheHolder e visualizzatore non compaiono in nessuna altra combinazione.

Edit 2:

sto usando Unity3D che supporta la maggior parte NET. 3.5

Come indicato, potrebbe essere preferibile utilizzare una raccolta .NET con una ricerca più rapida di Elenco. O se la lista è ordinabile usa List.BinarySearch.

Edit 3:

ho intenzione di utilizzare la versione struct. Non sono sicuro che quante occhiate ci saranno. Potrei passare a un'altra raccolta .NET se si tratta di un problema.

+4

Ogni volta che vedo una domanda sul rendimento, collego questo: http://ericlippert.com/2012/12/17/performance-rant/ – DavidG

+1

Hai mostrato entrambe le versioni come codice. Allora, dove sono i valori di tempo/memoria che hai misurato usando quel codice? Se lo hai misurato, puoi dire - a seconda dei tuoi criteri - quale versione soddisfa le tue esigenze. –

+1

Solo una FYI - non hai bisogno del tuo 'FindIndex' con un delegato. Le strutture restituiscono 'true' se confrontate con gli stessi campi. Cioè: 'new SimulationObject {CacheHolder = ch, Visualizer = v} .Equals (new SimulationObject {CacheHolder = ch, Visualizer = v})' restituirà true. Si può semplicemente usare 'var exists = simulationObjects.Contains (new SimulationObject {CacheHolder = cacheHolder, Visualizer = visualizer});' – Rob

risposta

1

ti consiglierei di utilizzare l'approccio struct, per due motivi:

  • In .NET, struct parametri di tipo generico sono trattati appositamente, e no boxing will occur.
  • Questo approccio garantirà per struttura di avere gli elementi corrispondenti. Per me sembra che sia più facile ragionare.

Così, quando si tratta di questione se utilizzare lista di struct o struct di liste, avrei certamente preferisce usare lista di struct, anche quando si fa un po 'di calo di prestazioni. Nel tuo caso, I si aspetta l'elenco di versioni di strutture per funzionare meglio, tuttavia non posso garantirlo. Puoi eseguire il profiling in qualsiasi momento. Ma una cosa è certa: la differenza di prestazioni è molto più piccola del costo della ricerca lineare in AddSimulationObject.

2

Il commento di Eric Lippert è molto vero. In questo caso non è necessario nemmeno provare a confrontare la differenza di prestazioni, dal momento che le raccolte sono così piccole, quindi non c'è bisogno di preoccuparsi del tempo di cpu.

Memory wise ... le strutture di lista utilizzano blocchi di memoria contigui e diventano un problema di memoria solo quando sono veramente grandi. (Intendo milioni.)

Solo altri suggerimenti: Se ogni ciclo di gioco si esegue una ricerca in tali elenchi, è sufficiente scegliere un'altra struttura ottimizzata per le ricerche. Il dizionario è molto più efficace nel recuperare gli oggetti in quanto il find esegue una ricerca da un indice, mentre l'elenco eseguirà un attraversamento degli elementi.

0

Stai parlando di elenchi di referenze, o una delle tue soluzioni andrà bene. Ma se i tuoi due interfacce sono destinate ad andare in coppia, si potrebbe usare List<Tuple<ICacheHolder, IVisualizer>>

+0

Grazie per il suggerimento. Appena provato. Sto lavorando con Unity3D Tuple è .NET Framework 4 e sfortunatamente non è supportato. Unity/Mono è in gran parte ancora su NET. 3.5. – Markus

+0

@Markus: varrebbe la pena di aggiornare la tua domanda per specificare che stai utilizzando Unity3D. Dato che .NET 4 ha ora più di 5 anni, ogni volta che stai ponendo un problema e * non puoi * usarlo, dovresti spiegare perché è così. –

Problemi correlati