2012-11-22 14 views
12

Biorąc pod uwagę możliwość przepisywania, chciałbym, ale w każdym razie, jak to stoi kod:Uderzyłem w OutOfMemoryException z listą <string> - czy to jest limit czy coś mi brakuje?

List<string> foobar; 

Następnie dodać kilka ciągów foobar.

Przy liczbie = 16777216, osiągnęliśmy limit pamięci.

Rozumiem, że każdy ciąg będzie różnej wielkości. Rzeczywiście patrząc na dane (nie moje dane), większość z nich składa się z 2 lub 3 znaków.

what is the max limit of data into list in c#? wskazuje, że maksymalna granica wynosi:

Maksymalna liczba elementów, które mogą być przechowywane w bieżącym realizacji lista jest teoretycznie Int32.MaxValue - tylko ponad 2 mld.

Jednakże:

W obecnej implementacji Microsoft CLR istnieje 2GB maksymalny limit rozmiaru obiektu. (Jest to możliwe, że inne implementacje, np Mono, nie mają tego ograniczenia.)

W moim przykładzie mam, co, 16 milionów wyników * kilka bajtów? Menedżer zadań pokazuje, że używany jest gig, ale mam 8 gigabajtów pamięci RAM.

16777216 (2^24) wydaje się dość konkretną wartością - podejrzanie przypomina limit, ale nie mogę znaleźć żadnej dokumentacji do a) z powrotem to lub b) znaleźć sposób obejścia go?

Każda pomoc zostanie doceniona.


Niektóre kodu:

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()); 
     } 
    } 

To uproszczona forma, Mam teraz trochę try/catch dla wyjątku OOM, ale jest to rzeczywisty kod, który dając mi żal.

+0

Czy możesz pokazać nam swój kod? –

+0

Wielkość sterty różni się od rozmiaru pamięci RAM, część pamięci RAM jest używana jako sterty, która służy do przechowywania obiektów. http://stackoverflow.com/questions/2325370/c-sharp-increase-heap-size-is-it-possible – CjCoax

+0

@JonSkeet - zaktualizowany o kilka fragmentów, daj mi znać, czy jest coś jeszcze. –

Odpowiedz

7

Jeśli próbujesz użyć bardzo dużych list w środowiskach 64-bitowych, musisz włączyć duże obiekty w konfiguracji aplikacji.

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

OOM jest prawdopodobne, ze względu na sposób Listy/ArrayLists przydzielić pamięci, która moim zdaniem jest za każdym razem ich granica zostanie osiągnięta, starają się podwoić wielkość. Lista nie może podwoić się z 2^24. Teoretycznie możesz zmaksymalizować rozmiar listy, wstępnie określając rozmiar. (Tj. 2 GB)

+0

To była poprawka, która zrobiła to za mnie! Dzięki :) –

1

Opublikowalem to, co tutaj zrobilem, warto to zrobic. kroki są ponownie:

  1. w każdej iteracji części zapytania danych za pomocą przechowywanego proc
  2. przenieść je
  3. przejścia do następnej części

    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++; 
    } 
    

i przechowywanej proc powinno być coś takiego:

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

Z pewnością zadziała, bez względu na to, ile płyt masz, tylko im więcej posiadanych danych, tym więcej czasu zajmie ukończenie.

1

Jeśli liczba jest mniejsza niż 2^24, gdy ręcznie ustawisz prawidłowy rozmiar listy, prawdopodobnie jest to prawidłowe. Zamiast uzyskać 16 milionów, a następnie spróbować podwoić rozmiar listy, spowoduje to, że lista będzie naprawdę duża i na tym skończy się pamięć.

To wyjaśnia, dlaczego otrzymujesz okrągły numer - osiągnął 2^24, a następnie próbował zwiększyć rozmiar, co spowodowało, że zużywa on zbyt dużo pamięci.

Brzmi tak, jakby to był jakiś "naturalny" limit wielkości obiektu, w przeciwieństwie do jednego w implementacji listy.

Powiązane problemy