在TPL Dataflow TransformBlock中使用DeflateStream和/或CryptoStream

时间:2015-01-07 12:00:37

标签: c# stream compression tpl-dataflow

我使用TPL Dataflow块实现基于数据包的网络协议。该协议是固定的,不能由我改变。将会有很少但很多的数据包。

我有一个客户端组件连接到服务器并读取原始数据包。然后将这些原始数据包作为MemoryStream发布到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本身内解码,其中仅创建包装器Stream。这似乎会绕过数据流块的优势。

因此我想到另一个解决方案,而不是返回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 Dataflow的模式更好地解决我的问题吗?

1 个答案:

答案 0 :(得分:1)

与往常一样,这是一种权衡,只能由您决定。

我会选择最简单的解决方案来连接两个块,让写入块&#34;吸收&#34;增加的压缩复杂性,因为TDF块可以在需要时增加其并行性。 但是,如果该块没有有限的并行度(MaxDegreeOfParallelism),我只会这样做。

如果存在限制,那么我将按照您的描述处理压缩块中的实际压缩。这种行为可以在非常高的并行度下完成,并且这些内存缓冲似乎不是一个大问题。

如果是,则可以添加缓冲池,因此缓冲区数量将仅限于块MaxDegreeOfParallelism,并且您只需要在应用程序的生命周期中分配这些缓冲区一次。