Welcome

首页 / 软件开发 / .NET编程技术 / .NET相关问题:流管道

.NET相关问题:流管道2011-12-14 msdn Stephen Toub问:在我的应用程序中,我要对大量数据进行加密和压缩操作。由于这些属于计算密集型操作,我原以为“任务管理器”中 CPU 的使用率会高达 100%,但结果却发现在双核计算机上,CPU 的使用率最高才达到 50% 左右。我认为这是因为只使用了一个核心,使得执行任务时需要花费非平凡的时间,计算性能因此显得十分逊色。请问有没有办法使用两个核心处理加密和压缩这两项任务?我使用的是 Microsoft® .NET Framework 中提供的 CryptoStream 和 GzipStream。

问:在我的应用程序中,我要对大量数据进行加密和压缩操作。由于这些属于计算密集型操作,我原以为“任务管理器”中 CPU 的使用率会高达 100%,但结果却发现在双核计算机上,CPU 的使用率最高才达到 50% 左右。我认为这是因为只使用了一个核心,使得执行任务时需要花费非平凡的时间,计算性能因此显得十分逊色。请问有没有办法使用两个核心处理加密和压缩这两项任务?我使用的是 Microsoft® .NET Framework 中提供的 CryptoStream 和 GzipStream。

答:首先要确认一下,您是先进行压缩后进行加密吗?如果不是,请更改操作顺序。安全有效的加密会产生相对不可压缩的数据。如果您将操作顺序更改为先压缩后加密,不仅可以得到更小的文件,而且由于要加密的数据更少,加密时间也可以更短。为了举例说明,我从古登堡计划 (Gutenberg Project, http://www.gutenberg.org/) 下载了《战争与和平》的文本,然后按照两种顺序分别进行了操作。先加密(使用 RijndaelManaged 和默认密钥长度)后压缩生成的数据流要比与先压缩后加密的大 250%,而且执行时间也增加了 50%。

答:首先要确认一下,您是先进行压缩后进行加密吗?如果不是,请更改操作顺序。安全有效的加密会产生相对不可压缩的数据。如果您将操作顺序更改为先压缩后加密,不仅可以得到更小的文件,而且由于要加密的数据更少,加密时间也可以更短。为了举例说明,我从古登堡计划 (Gutenberg Project, http://www.gutenberg.org/) 下载了《战争与和平》的文本,然后按照两种顺序分别进行了操作。先加密(使用 RijndaelManaged 和默认密钥长度)后压缩生成的数据流要比与先压缩后加密的大 250%,而且执行时间也增加了 50%。

现在言归正题,我来回答您的实际问题:是的,解决这一问题的方法很多。第一种方法是并行执行实际的压缩和加密操作。您可能不希望(也不应该)重新实现 GZipStream 和 CryptoStream 中的功能,因此,在 .NET Framework 团队实现这两项任务的并行操作之前,您需要一套替代的解决方案。

如果您不在乎实际的输出格式(例如,只进行压缩,但并不关心压缩实际上是否符合 gzip 标准),可以将输入分块,然后并行处理每个块。例如,在双核计算机上,您可以将当前传送到 GzipStream 的输入字节数组分成两半,使用一个 GZipStream 处理其中一半,使用另一个 GzipStream 处理另一半。然后再将这些输出内容依次保存到输出文件。

但是请注意,您很可能需要在输出内容中包含某些标头信息,以便解压缩进程能够准确地确定一个 GZipStream 的结束位置和下一个 GzipStream 的开始位置。当前 GZipStream 在读取输入流中数据的同时会对数据进行缓存,因此,它最终从输入流获得的数据有时会超出其实际所需,这意味着,您需要在第一个 GZipStream 完成解压缩之后重置输入流中的位置标记。