TCP 서버 및 MemoryStreams/Bytearrays
-
18-09-2019 - |
문제
C#로 작성된 TCP 서버가 게시되어 게시물 데이터를 게시합니다. 현재 많은 양의 데이터 (예 : 1GB보다 큰)가 전송되지 않는 한 잘 작동합니다. 메모리가 부족합니다 (메모리에 모든 것을 바이트 배열로 저장합니다 (목록 DTO의 중개자). 큰 파일의 경우 이제 디스크로 스트리밍 한 다음 디스크에서 스트리밍 할 의도로 파일 이름을 전달합니다.
현재 내 모든 루틴은 바이트 어레이를 기대하기 위해 작성되었습니다. 바이트 레이를 메모리 스트림으로 변환하면 메모리 사용이 두 배가됩니까? 메모리 스트림에서 작동하기 위해 코드를 다시 작성하는 것이 디스크에서 스트림을 읽을 때 재사용 할 수 있다고 생각합니까?
어리석은 질문에 대해 죄송합니다. C#이 데이터의 사본을 가져 오거나 참조 할 때 확실하지 않습니다.
해결책
당신이 통과하는 경우 byte[]
a MemoryStream
, 그러면 처음에 데이터를 (생성자에서) 복사하지만 릴리스하는 한 byte[]
쓰레기를 수집 할 수 있습니다. 본질적으로 "두 배가"가 없습니다 (특히 크기를 올바르게 설정하여 시작하여 직접 작성할 수있는 경우 Stream
대신 byte[]
).
나는 전적으로 전환한다고 말할 것이다 Stream
(하지만 뿐 사용 Stream
API에서 - Moer 특이한 것은 없습니다. 소비 코드는 어떤 유형을 알 필요가 없습니다). 가장 중요한 것은 사용하도록 선택할 수 있습니다 NetworkStream
(소켓에서 직접 읽기) 또는 FileStream
(디스크에 버퍼링하려면) 또는 MemoryStream
프로세스를 버퍼하려면. 또한 스트림 기반 코드를 통해 해당 데이터의 양을 읽어야합니다. 반복자 블록 (yield return
) LINQ와 마찬가지로 여기에서 매우 도움이 될 수 있습니다. Enumerable
방법 (제외 OrderBy
, GroupBy
, 등, 어떤 버퍼).
둘 다 지나가지 않습니다 byte[]
전달 a Stream
참조 유형이므로 복사 할 수 있습니다. 복사 한 유일한 것은 참조입니다 (x86/x64에 따라 4 또는 8 바이트).
다른 팁
MemoryStream은 바이트 어레이 주변의 스트림 래퍼이므로 사용하여 아무것도 얻지 못합니다.
최소한 큰 파일의 경우해야 할 일은 파일 스트림을 열고 데이터를 덤프하는 것입니다. 더 낮은 레벨에서 연결에서 x 바이트를 읽은 다음 즉시 파일 스트림에 기록해야합니다. 이런 식으로 당신은 전체 공연을 메모리로 끌어 당기지 않고 한 번에 몇 바이트 만 당기지 않습니다.
이것이 쉽게 수행 할 수 있는지 여부는 TCP 서버가 코딩되는 방식에 따라 다릅니다.
바이트는 값 유형이므로 Ref 키워드없이 함수로 전달하면 매번 사본을 처리하게됩니다. Ref 키워드로 전달하면 원래 바이트 배열을 참조합니다.
MemoryStream은 참조 유형이므로 데이터를 복사하지는 않지만 해당 데이터에 대한 참조를 전달하므로 메모리 사용이 사용시 두 배가되지 않습니다.