我正在使用TPL數據流塊來實現基於數據包的網絡協議。這個協議是固定的,不能被我改變。主要是小的,但很多數據包。在TPL數據流中使用DeflateStream和/或CryptoStream數據流TransformBlock
我有一個客戶端組件連接到服務器並讀取原始數據包。然後這些原始數據包將作爲MemoryStreams發佈到BufferBlock,然後在TransformBlock中根據數據包類型/ ID解碼爲數據包結構。
要發送數據包,此過程與另一鏈數據流塊反向。就我所知,所有這些都很有效。
問題是,這些數據包可能會或可能不會被壓縮,可能會或可能不會被加密,基於服務器響應。我會提出新的插圖中TransformBlocks(使用解壓縮爲例)解決這個問題:
static TransformBlock<Stream, Stream> CreateDecompressorBlock(ProtocolContext context)
{
return new TransformBlock<Stream, Stream>(stream =>
{
if (!context.CompressionEnabled) return stream;
return new DeflateStream(stream, CompressionMode.Decompress);
}
}
然而,這在我看來就像是不正確的做法。據我瞭解,DeflateStream(和CryptoStream)在讀取數據時解碼數據。這意味着數據在我對數據包內容進行解碼時被解碼,而不是在TransformBlock本身內部進行解碼,其中只有包裝流被創建。這似乎會繞過數據流塊的優勢。
那麼另一種解決方案來我的心在那裏而不是返回DeflateStream/CryptoStream的,我讀通過它到另一個的MemoryStream:
static TransformBlock<Stream, Stream> CreateDecompressorBlock(ProtocolContext context)
{
return new TransformBlock<Stream, Stream>(stream =>
{
if (!context.CompressionEnabled) return stream;
using (var deflate = new DeflateStream(stream, CompressionMode.Decompress))
{
var ms = new MemoryStream();
deflate.CopyTo(ms);
return ms;
}
}
}
現在,這似乎是浪費內存。
所以我的問題是,是否足以包裝流,讓稍後解碼數據包內容的TransformBlock完成工作,還是應該使用更多內存,然後可能有更好的分離和可能的並行性? (雖然我不認爲解碼會成爲瓶頸,但這將是網絡)。
還是有一種模式,我可以使用TPL數據流,解決我的問題更好?
選擇相當直接。只有你可以判斷每種方法的優點。如果你想清楚解碼階段(也許你可以更好地管理資源/併發性),那麼解碼到MemoryStream似乎是一個好主意,但在內存方面會更昂貴。另一方面,如果您的數據包解析TransformBlock不受CPU額外解碼負載的限制,只需讓這些數據流執行其魔術...... – spender
這會成爲問題的唯一時間是當您處於負載繁重和隊列/端口(或任何他們在TPLDF中調用的名稱)時開始備份。當您遇到這種情況時,仔細測量可能會給您更好的答案。 – spender
爲什麼你甚至想把它放到一個單獨的塊?爲什麼不把它添加到其中一個現有的塊? – svick