Вопрос

У меня есть TCP-сервер, написанный на C#, который обрабатывает отправленные на него данные POST.В настоящее время он работает нормально, если только не большой объем данных (т.больше 1 ГБ) отправляется на него, а затем ему не хватает памяти (я храню все это в памяти как массив байтов (с посредником в виде List DTO)).Теперь для больших файлов я выполняю потоковую передачу на диск, а затем передаю имя файла с намерением передать его с диска.

В настоящее время все мои процедуры написаны с расчетом на байтовые массивы, что, оглядываясь назад, было немного недальновидным.Если я просто преобразую массив байтов в поток памяти, удвоится ли это использование памяти?Я думаю, что переписывание моего кода для работы с потоком памяти позволит мне повторно использовать его при чтении потока с диска?

Извините за глупые вопросы, я никогда не уверен, когда C# берет копию данных или когда он берет ссылку.

Это было полезно?

Решение

Если вы пройдете byte[] в MemoryStream, то он изначально скопирует данные (в конструкторе), но пока вы отпустите byte[] его можно собирать мусором.По своей сути никакого "удвоения" нет (особенно если можно изначально правильно задать размер и писать прямо в файл). Stream а не byte[]).

Я бы полностью сказал, переключитесь на Stream (но только использовать Stream в API - ничего более конкретного;вашему потребляющему коду не обязательно знать, какой тип).Самое главное, вы можете использовать NetworkStream (для чтения непосредственно из сокета) или FileStream (если вы хотите буферизовать на диск) или MemoryStream если вы хотите буферизовать процесс.Вам также необходимо убедиться, что вы читаете этот объем данных через потоковый код.Блоки итератора (yield return) может быть здесь очень полезным, как и LINQ Enumerable методы (кроме OrderBy, GroupBy, и т. д., какой буфер).

Ни прохождение byte[] ни прохождения Stream вызывает копирование чего-либо, поскольку они являются ссылочными типами - единственное, что копируется, - это ссылка (4 или 8 байтов, в зависимости от x86/x64).

Другие советы

MemoryStream — это просто потоковая оболочка вокруг байтового массива, поэтому вы ничего не получите, используя его.

Что вам нужно сделать (по крайней мере, для больших файлов), так это открыть FileStream и сбросить в него свои данные.На более низком уровне вам нужно прочитать X байтов из вашего соединения, а затем немедленно записать их в поток файлов.Таким образом, вы не будете загружать в память весь концерт, а только несколько байтов за раз.

Будет ли это легко сделать, зависит от того, как закодирован ваш TCP-сервер.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top