Почему я не могу усилить 4 ГБ RAM в моем компьютере для обработки меньше чем 2 ГБ информации в C#?

3 ответа

Да, Строка. Разделение создает новый Строковый объект для каждой "части" - это - то, что это предназначено, чтобы сделать.

Теперь, примите во внимание, что строки в.NET являются Unicode (UTF-16 действительно), и с объектом наверху стоимость строки в байтах приблизительно 20 + 2*n где n количество символов.

Это означает, есть ли у Вас много маленьких строк, потребуется большая память по сравнению с размером текстовых включенных данных. Например, 80 символьных строк, разделенных на символьные строки 10 x 8, возьмут 80 байтов в файле, но 10 * (20 + 2*8) = 360 байтов в памяти - 4.5x взрыв!

Я сомневаюсь, что это - проблема GC - и я советовал бы Вам удалять дополнительные операторы, устанавливающие переменные в NULL, когда это не необходимо - просто проблема наличия слишком большого количества данных.

То, что я предложил бы, - то, что Вы читаете файл линию за линией (использование TextReader.ReadLine() вместо TextReader.ReadToEnd()). Очевидно наличие целого файла в памяти, если Вы не должны, расточительно.

14
ответ дан 8 December 2019 в 12:22
поделиться

Современные языки GC используют в своих интересах большой объем дешевой RAM для разгрузки memeory задач управления. Это налагает определенные издержки, но для Вашего типичного бизнес-приложения не действительно нужно так много информации так или иначе. Много программ обходятся меньше чем тысячей объектов. Вручную справление, что многие - тяжелая работа, bu даже тысячебайтовые издержки на объект, не имело бы значения.

В Вашем случае издержки на объект становятся проблемой. Можно, например, рассмотреть представление каждого столбца как один объект, реализованный с единственной Строкой и массивом целочисленных смещений. Для возврата единственного поля Вы возвращаете подстроку (возможно как контейнер)

2
ответ дан 8 December 2019 в 12:22
поделиться

Я предложил бы читать линию за линией вместо всего файла или блока до 1-2mb.

Обновление:
Из комментариев Jon я был любопытен и экспериментировал с 4 методами:

  • StreamReader. ReadLine (и пользовательский размер буфера по умолчанию),
  • StreamReader. ReadToEnd
  • Мой метод упоминается выше.

Чтение файла журнала 180 МБ:

  • Мс ReadLine: 1937
  • ReadLine более крупный буфер, мс ASCII: 1926
  • Мс ReadToEnd: 2151
  • Пользовательский мс: 1415

Пользовательский StreamReader был:

StreamReader streamReader = new StreamReader(fileStream, Encoding.Default, false, 16384)

Буфер StreamReader по умолчанию 1024.

Для потребления памяти (фактический вопрос!) - ~800mb используемый. И метод, я даю все еще использованию StringBuilder (который использует строку), так никакое меньше потребления памяти.

3
ответ дан 8 December 2019 в 12:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: