Мне нужно извлечь большие текстовые строки Unicode (например, 200 МБ) из базы данных (nvarchar) и сохранить в памяти для обработки. т.е. мне нужен произвольный доступ ко всем частям строк.
Если посмотреть на это с точки зрения строго памяти, каковы плюсы и минусы использования System.IO.MemoryStream по сравнению с System.String в качестве моего представления в памяти.
Вот некоторые факторы, которые я пытаюсь исследовать:
Я ищу ясности и советов по этим вопросам, а также любых других соображений памяти, о которых я не думал?
Примечание. Возможно, существует лучший способ обработки этих строк, но на данный момент я действительно просто спрашиваю о соображениях памяти при хранении такого объекта.





Looking at this from strictly memory centric point of view, what are the pro’s and con’s of using a System.IO.MemoryStream versus a System.String as my in memory representation.
Some factors I am trying to research are:
- How these objects act in a [hypothetical] highly fragmented low memory environment
IMO, MemoryStream полезен только тогда, когда кодировка тривиальна (например, ASCII, ISO-8859-X и т. д.). Если кодировка UTF-8 а также, у вас есть символы, отличные от ASCII, тогда обработка станет более сложной. Конечно, MemoryStream почти наверняка будет потреблять меньше памяти, но в остальном особой разницы нет. Под капотом MemoryStream использует массив байтов, который также необходимо выделить в непрерывном блоке памяти.
- Actual size in memory (if stream is UTF8, have we nearly halved size)
Правильно, с чисто символами ASCII, MemoryStream будет потреблять половину того, что потребляет эквивалентная строка.
- Is there another object I have not thought about?
List<byte> // has a nicer interface for processing
Как строки хранятся в базе данных? варчар или нварчар?
С уважением,
Андреас
Спасибо Андреасу, строки выходят из базы данных как nvarchar.
Привет, Андреас. После некоторого дальнейшего чтения в MSDN я прочитал, что MemoryStream, созданный с помощью конструктора по умолчанию, имеет изменяемый размер, поэтому это означает, что он не требует непрерывного блока памяти. Это справедливое предположение?
см .: msdn.microsoft.com/en-us/library/…
В этом случае, если я не ошибаюсь, с помощью LINQ или ADO невозможно избежать System.String. Так что, по крайней мере, когда вы загружаете данные, вам нужно поместить всю строку в память. Преобразование этого в массив байтов перед дальнейшей обработкой потребует - до тех пор, пока сборщик мусора не соберет строку - потребуется еще больше памяти.
Теперь я пытаюсь перейти от DB -> IDataReader -> StreamWriter -> MemoryStream. Кажется, это работает, избегая любого System.String в памяти
Нет, изменение размера MemoryStream внутренне просто выделит массив байтов, вдвое превышающий текущий размер, а затем скопирует содержимое старого массива в новый массив, так что после изменения размера блок останется непрерывным. Вы можете использовать .NET Reflector для просмотра MemoryStream.SetLength.
Да, возможно, лучше всего использовать DataReader. Я предполагаю, что вы читаете строку БД в нескольких блоках и конвертируете их в UTF-8, прежде чем записывать их в MemoryStream, верно? Если это так, то вызов MemoryStream.SetSize раньше позволит избежать дополнительных выделений и копирования.
Память строки и потока довольно несущественна. Строки - это utf-16, поэтому май будет небольшим числом задействованных, но из-за задействованных томов вам, вероятно, будет лучше записывать данные в рабочий файл.
Чтобы прочитать данные из базы данных, используйте методы потоковой передачи; то есть использовать IDataReader (ExecuteReader) в последовательном режиме и читать блоки байтов / символов. Не пытайтесь прочитать всю колонку.
Кроме того, с SQL Server 2008 вам не захочется смотреть на тип файлового потока.
Примеры:
какие-нибудь хорошие образцы с исходным кодом ??