Подтвердить что ты не робот

Я ударил OutOfMemoryException с помощью List <string> - это лимит, или я что-то упускаю?

Учитывая возможность переписать, я бы, но в любом случае, код в том виде, в каком он есть:

List<string> foobar;

Затем добавим связку строк в foobar.

В count = 16777216 мы попали в пределы памяти.

Я понимаю, что каждая строка будет другого размера. Действительно, глядя на данные (не мои данные), большинство из них - 2 или 3 символа.

Каков максимальный предел данных в список в С#?, указывает, что максимальный предел:

Максимальное количество элементов, которые могут быть сохранены в текущем реализация List - теоретически Int32.MaxValue - просто более 2 миллиардов.

Однако:

В текущей реализации Microsoft CLR есть 2 ГБ максимальный размер объекта. (Возможно, что другие реализации, например Mono, не имеют этого ограничения.)

В моем примере у меня есть, что, 16 миллионов результатов * несколько байтов? Диспетчер задач показывает, что используется гигабайт, но у меня есть 8 гигабайт оперативной памяти.

16777216 (2 ^ 24) кажется довольно специфическим значением - подозрительно, как предел, но я не могу найти какую-либо документацию в любом месте) назад или b) найти способ вокруг него?

Любая помощь будет оценена.


Некоторые коды:

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

Что упрощенная форма, теперь у меня есть попытка try/catch для исключения OOM, но это фактический код, который дает мне печаль.

4b9b3361

Ответ 1

Если вы пытаетесь использовать очень большие списки в 64-битных средах, вам нужно включить большие объекты в конфигурацию приложения.

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

OOM, вероятно, связано с тем, как списки/массивы распределяют память, и я считаю, что каждый раз, когда их граница достигнута, они пытаются удвоить размер. Список не может удваиваться от 2 ^ 24. Теоретически вы можете максимизировать свой размер списка, предварительно указав размер. (I.e. 2GB)

Ответ 2

Я опубликовал то, что я здесь сделал, стоит того, чтобы уйти. Снова шаги:

  • На каждой итерационной части запроса данных с использованием хранимой процедуры proc
  • Перенесите их
  • Переместитесь к следующей части

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

а хранимая процедура должна выглядеть примерно так:

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

Я определенно буду работать независимо от того, сколько записей у вас есть, просто чем больше данных у вас есть, тем больше времени потребуется.

Ответ 3

Если он получает даже меньше 2 ^ 24, когда вы вручную устанавливаете правильный размер списка, то это, вероятно, на правильном пути. Вместо того, чтобы доходить до 16 миллионов, а затем попытаться удвоить размер списка, это приведет к тому, что список будет действительно большим и начнется раньше.

Это объясняет, почему вы получили круглый номер - он достиг 2 ^ 24, а затем попытался увеличить размер, из-за чего он использовал слишком много памяти.

Мне кажется, что это какой-то "естественный" размер объекта, а не один в реализации списка.