2012-11-22 9 views
12

Data l'opportunità di riscrivere, vorrei, ma in ogni caso, il codice come si distingue:Ho colpito un OutOfMemoryException con l'elenco <string> - è questo il limite o mi manca qualcosa?

List<string> foobar; 

Poi aggiungiamo un po 'di stringhe da foobar.

Conteggio = 16777216, abbiamo raggiunto un limite di memoria esaurito.

La mia comprensione è che ogni stringa avrebbe una dimensione diversa. Effettivamente guardando i dati (non i miei dati), la maggior parte sono 2 o 3 caratteri.

what is the max limit of data into list in c#? indica che il limite massimo è:

Il numero massimo di elementi che possono essere immagazzinate nella corrente implementazione di List è, in teoria, Int32.MaxValue - solo più di 2 miliardi.

Tuttavia:

Nell'implementazione Microsoft corrente del CLR c'è un limite di dimensione massima di 2 GB oggetto . (E 'possibile che altre implementazioni, ad esempio Mono, non hanno questa limitazione.)

Nel mio esempio, ho, quello che, 16 milioni di risultati * alcuni byte? Task Manager mostra di un concerto in uso, ma ho 8 GB di RAM.

16777216 (2^24) sembra un valore piuttosto specifico - sospettosamente simile a un limite, ma non riesco a trovare alcuna documentazione da nessuna parte a) indietro in su o b) trovare un modo per aggirarlo?

Qualsiasi aiuto sarebbe apprezzato.


Alcuni codice:

List<string> returnList = new List<string>(); 
SqlDataReader dr; // executes a read on a database, have removed that part as that bit works fine 

    if (dr.HasRows) 
    { 
     while (dr.Read()) 
     { 
      returnList.Add(dr.GetString(0).Trim()); 
     } 
    } 

questa è la forma semplificata, ora ho un po 'di try/catch per l'eccezione OOM, ma questo è il codice vero e proprio che mi sta dando il dolore.

+0

Puoi mostrarci il tuo codice? –

+0

La dimensione dell'heap è diversa dalla dimensione della RAM, una porzione di RAM viene utilizzata come heap, che viene utilizzata per memorizzare gli oggetti. http://stackoverflow.com/questions/2325370/c-sharp-increase-heap-size-is-it-possible – CjCoax

+0

@JonSkeet - aggiornato con alcuni frammenti, fammi sapere se c'è qualcos'altro richiesto. –

risposta

7

Se si sta tentando di utilizzare elenchi molto grandi in ambienti a 64 bit è necessario abilitare oggetti di grandi dimensioni nella configurazione dell'applicazione.

http://msdn.microsoft.com/en-us/library/hh285054.aspx

L'OOM è probabilmente dovuto al modo in cui gli elenchi/ArrayLists allocano la memoria, che credo sia ogni volta che viene raggiunto il loro limite, tentano di raddoppiare le dimensioni. L'elenco non può raddoppiare da 2^24. Potresti teoricamente massimizzare la dimensione dell'elenco specificando una dimensione. (I.e 2 GB)

+0

Questa è stata la correzione che ha fatto per me! Grazie :) –

1

Ho pubblicato quello che ho fatto esattamente qui, vale la pena provarlo. passi Ancora sono:

  1. Su ciascuna porzione di query iterazione di dati utilizzando una stored
  2. trasferirli
  3. movimento alla porzione successiva

    List<string> returnList; 
    int index = 0; 
    SqlCommand cmd = new SqlCommand("ExampleStoredProc", conn); 
    cmd.CommandType = CommandType.StoredProcedure; 
    while (true) 
    { 
        cmd.Parameters.Add(
         new SqlParameter("@index", index)); 
        SqlDataReader dr = cmd.ExecuteReader(); 
        if (dr.HasRows) 
        { 
         returnList = new List<string>(); 
         returnList.Add(dr.GetString(0).Trim()); 
         //transfer data here 
        } 
        else 
        { 
         break; 
        } 
        index++; 
    } 
    

e proc memorizzato dovrebbe essere qualcosa del genere:

CREATE PROCEDURE ExampleStoredProc 
    @index INT 
AS 
BEGIN 
    SELECT * 
    FROM veryBigTable 
    WHERE Id >= (@index *1000) AND Id < ((@index + 1) * 1000) 
END 
GO 

Lavorerò sicuramente non importa quanti record hai, solo più dati hai, più tempo ci vorrà per finire.

1

Se sta ottenendo addirittura meno di 2^24 quando si imposta manualmente la dimensione dell'elenco corretta, probabilmente è sulla traccia corretta. Invece di arrivare a 16 milioni e poi provare a raddoppiare la dimensione della lista, renderà la lista davvero grande per cominciare e la memoria in esaurimento prima.

Questo spiega perché stavi ottenendo un numero tondo: ha raggiunto il 2^24, quindi ha cercato di aumentare le dimensioni, il che ha causato l'uso di troppa memoria.

Mi sembra che si tratti di una sorta di limite di dimensione dell'oggetto "naturale", a differenza di uno nell'implementazione dell'elenco.

Problemi correlati