在多个线程上并行调用 ICsharpCode.SharpZipLib 是否安全

2024-01-28

我们当前使用 ICsharpCode.SharpZipLib 库的 GZipOutputStream 类进行压缩。我们通过一个线程来完成它。

我想将输入数据流分割成块并并行压缩它们。 我担心这个库内部可能有一些静态数据,这些静态数据会被多个线程覆盖,从而损坏结果流。

任何想法将不胜感激。


这是一个非常有趣的问题。压缩是高度 CPU 密集型的,依赖于大量的搜索和比较。因此,当您拥有多个具有不受阻碍的内存访问的 CPU 时,想要并行化它是非常合适的。

有一个类叫做ParallelDeflateOutputStream在执行您所描述的操作的 DotNetZip 库中。该类已记录here http://cheeso.members.winisp.net/DotNetZipHelp/html/26cbdba2-021a-ccf1-a9c9-b7ae55f6ecb8.htm.

它只能用于压缩 - 不能解压缩。而且它严格来说是一个输出流 - 你不能read为了压缩。考虑到这些限制,它基本上是一个 DeflateOutputStream,内部使用多个线程。

它的工作方式:它将传入流分解为块,然后将每个块放入单独的工作线程中以进行单独压缩。然后,它最后将所有这些压缩流合并回一个有序流。

假设流维护的“块”大小是 N 字节。当调用者调用 Write() 时,数据被缓冲到存储桶或块中。在 - 的里面Stream.Write()方法,当第一个“桶”满时,它调用ThreadPool.QueueUserWorkItem,将存储桶分配给工作项。后续写入流开始填充下一个存储桶,当that已满,Stream.Write() calls QUWI再次。每个工作线程使用“刷新类型”压缩其存储桶Sync(请参阅 deflate 规范),然后将其压缩 blob 标记为准备输出。然后,这些不同的输出被重新排序(因为块 n 不一定在块 n+1 之前被压缩),并写入捕获输出流。当每个桶被写入时,它被标记为空,准备好由下一个桶重新填充Stream.Write()。每个块必须使用 Sync 的刷新类型进行压缩,以便允许它们通过简单的串联重新组合,使组合的字节流成为合法的 DEFLATE 流。最后的块需要齐平式= 完成。

该流的设计意味着调用者不需要使用多个线程编写。调用者只需像平常一样创建流,就像用于输出的普通 DeflateStream 一样,然后写入其中。流对象使用多个线程,但您的代码不直接与它们交互。 “用户”的代码ParallelDeflateOutputStream看起来像这样:

using (FileStream raw = new FileStream(CompressedFile, FileMode.Create))
{
    using (FileStream input = File.OpenRead(FileToCompress))
    {
        using (var compressor = new Ionic.Zlib.ParallelDeflateOutputStream(raw))
        {
            // could tweak params of parallel deflater here
            int n;
            var buffer = new byte[8192];
            while ((n = input.Read(buffer, 0, buffer.Length)) != 0)
            {
                compressor.Write(buffer, 0, n);
            }                    
        }
    }
}

它被设计为在 DotNetZip ZipFile 类中使用,但它作为独立的压缩输出流非常有用。生成的流可以用任何充气器去 DELFATED(充气?)。结果完全符合规范。

流是可调整的。您可以设置它使用的缓冲区的大小以及并行级别。它不会无限制地创建存储桶,因为对于大型流(GB 规模等),这会导致内存不足的情况。因此,存储桶的数量以及可支持的并行度都有固定的限制。

在我的双核机器上,与标准 DeflateStream 相比,该流类几乎使大型(100mb 及更大)文件的压缩速度提高了一倍。我没有更大的多核机器,所以我无法进一步测试它。代价是并行实现使用更多的 CPU 和更多的内存,并且由于我上面描述的同步帧,压缩效率也稍低(大文件减少 1%)。性能优势将根据输出流上的 I/O 吞吐量以及存储是否能跟上并行压缩器线程的速度而变化。


Caveat:
它是 DEFLATE 流,而不是 GZIP。对于差异,请阅读RFC 1951(放气) http://www.faqs.org/rfcs/rfc1951.html and RFC 1952 (GZIP) http://www.faqs.org/rfcs/rfc1952.html.

但如果您确实需要 gzip,可以使用此流的源代码,因此您可以查看它,也许可以为自己获得一些想法。 GZIP 实际上只是 DEFLATE 之上的一个包装器,带有一些附加元数据(如 Adler 校验和等 - 请参阅规范)。在我看来,建立一个ParallelGzipOutputStream,但这也可能不是微不足道的。

对我来说最棘手的部分是让 Flush() 和 Close() 的语义正常工作。


EDIT

只是为了好玩,我为 GZip 构建了一个 ParallelGZipOutputStream,它基本上执行我上面描述的操作。它使用.NET 4.0 的任务代替QUWI 来处理并行压缩。我刚刚在通过马尔可夫链引擎生成的 100mb 文本文件上进行了测试。我将该课程的结果与其他一些选项进行了比较。它看起来是这样的:

uncompressed: 104857600
running 2 cycles, 6 Flavors

System.IO.Compression.GZipStream:  .NET 2.0 builtin
  compressed: 47550941
  ratio     : 54.65%
  Elapsed   : 19.22s

ICSharpCode.SharpZipLib.GZip.GZipOutputStream:  0.86.0.518
  compressed: 37894303
  ratio     : 63.86%
  Elapsed   : 36.43s

Ionic.Zlib.GZipStream:  DotNetZip v1.9.1.5, CompLevel=Default
  compressed: 37896198
  ratio     : 63.86%
  Elapsed   : 39.12s

Ionic.Zlib.GZipStream:  DotNetZip v1.9.1.5, CompLevel=BestSpeed
  compressed: 47204891
  ratio     : 54.98%
  Elapsed   : 15.19s

Ionic.Exploration.ParallelGZipOutputStream: DotNetZip v1.9.1.5, CompLevel=Default
  compressed: 39524723
  ratio     : 62.31%
  Elapsed   : 20.98s

Ionic.Exploration.ParallelGZipOutputStream:DotNetZip v1.9.1.5, CompLevel=BestSpeed
  compressed: 47937903
  ratio     : 54.28%
  Elapsed   : 9.42s

结论:

  1. .NET 内置的 GZipStream 速度相当快。而且效率也不是很高,而且 它不可调。

  2. DotNetZip 中的普通(非并行化)GZipStream 上的“BestSpeed”比 .NET 内置流快大约 20%,并且提供大约相同的压缩。

  3. 将普通的 DotNetZip GZipStream 与并行的相比,使用多个任务进行压缩可以将我的双核笔记本电脑(3GB RAM)所需的时间减少大约 45%。我想对于具有更多内核的机器来说,节省的时间会更多。

  4. 并行 GZIP 是有代价的 - 分帧会使压缩文件的大小增加约 4%。这不会随着使用的核心数量而改变。

生成的 .gz 文件可以通过任何 GZIP 工具解压缩。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在多个线程上并行调用 ICsharpCode.SharpZipLib 是否安全 的相关文章

  • 即使在 GC Collect 和 WaitForPendingFinalizers 之后,窗口对象在关闭后也未释放?

    这是一个简单的测试应用程序 可帮助了解 WPF 内存使用情况 我想了解的关键是为什么MainWindow即使在关闭并等待 GC 完成之后 仍然被引用并且它的内存没有被释放 参见下面的代码清单 文本 MainWindow Finalizer
  • 字典 API(词汇)[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有人知道一个好的 NET 字典 API 吗 我对含义不感兴趣 而是我需要能够以多种不同的方式查询单词 返
  • 分层架构中的异常处理

    我们正在分层设计中重构 当然还有重新设计 我们的服务 我们有服务操作层 BLL 网络抽象层 gt 处理网络代理 数据抽象层 但我们对我们的异常处理策略有点困惑 我们不想向外界透露太多 BLL 的信息 从其他层到bll就可以了 我们不想让 t
  • 如何将智能感知添加到我的应用程序中?

    我们的一款产品拥有一种专有的宏语言 通过我们的 Windows 软件进行编辑 我想添加智能感知 但我不知道如何去做 至少不完全重新发明轮子 是否有任何示例代码或第 3 方包至少可以让我开始 它不一定是免费的 该应用程序使用 NET 用 C
  • 在压缩存档内的文本文件上运行“head”,而不解压存档

    问候 我接手了之前的团队并编写了处理 csv 文件的 ETL 作业 我在 ubuntu 上结合使用 shell 脚本和 perl csv 文件很大 它们以压缩档案形式到达 解压后 很多都超过 30Gb 是的 那是 G 旧进程是在 cron
  • 实用程序库中应包含哪些内容[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 随着我的项目越来越多 我发现我经常从一个项目到另一个项目 从一个客户到另一个客户重复许多常见的任务 因此 我开始组装一个 实用程序 库 这是这些
  • iPhone 相当于 Application.DoEvents();

    iPHone 我们使用 MonoTouch 但 Obj C 答案还可以 我的单例域对象需要一段时间才能获取所有数据 因此它在线程中内部运行部分获取数据 我需要通知 UI 域已完成 目前我正在这样做 有没有更好的办法 在 WinForms 中
  • EasyNetQ 模型关闭

    我使用 EasyNetQ 实现了一个简单的 RabbitMQ 客户端 连接后 我收到一条通知 队列模型关闭 这是我的代码 var bus RabbitHutch CreateBus String Format host 0 hostName
  • 如何从 Android 调用 RESTful 方法?

    我尝试了两种不同的方法来从 Android 调用简单的 REST 方法 所述 REST 方法 适用于其他客户端 仅返回一个 int val 例如 17 以下两次尝试都是基于我在网上找到的代码 有一种是这样的 公共无效onFetchBtnCl
  • 有谁知道一种更快的方法来执行 String.Split() 吗?

    我正在读取 CSV 文件的每一行 并且需要获取每一列中的各个值 所以现在我只是使用 values line Split delimiter where line是保存由分隔符分隔的值的字符串 衡量我的表现ReadNextRow我注意到它花费
  • C# - 方法必须有返回类型

    我在调用 C 中的方法时遇到问题 不断收到消息 方法 计算 必须有返回类型 using System Diagnostics namespace WindowsFormsApplication1 public partial class F
  • 为什么当要求修剪“PRN.NUL”时,TrimStart 会更多地修剪字符?

    这是代码 namespace TrimTest class Program static void Main string args string ToTrim PRN NUL Console WriteLine ToTrim string
  • MySQL PHP邮政编码比较具体距离

    我试图找出比较一个邮政编码 用户提供的 和一大堆其他邮政编码 现在大约有 200 个邮政编码 之间的距离的最有效方法 相对于加载时间 但它会随着时间的推移而增加 我不需要任何精确的东西 只是在球场上 我下载了整个美国的邮政编码 csv 文件
  • 在Spring中使用什么样的“EventBus”?内置、Reactor、Akka?

    我们将在几周后启动一个新的 Spring 4 应用程序 我们希望使用一些事件驱动的架构 今年 我到处读到有关 Reactor 的内容 在网上查找时 我偶然发现了 Akka 所以现在我们有3个选择 春天的ApplicationEvent ht
  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • “多级继承情况下的虚拟基类”有意义吗

    考虑以下显示多级继承的示例代码 案例1 这里是班级derived1是从类派生的base通过虚拟继承和类derived2是从类派生的derived1直接地 class base class derived1 virtual public ba
  • SQL 可移植性问题

    我的公司让我致力于为 Python ORM 完成 Oracle 后端 我很惊讶 RDBMS 做事的方式有多么不同 即使对于简单的事情也是如此 我了解了很多有关 Oracle 和其他 RDBMS 之间的差异的知识 纯粹出于好奇 我想了解更多
  • R Shiny:如何在 DT::renderDataTable 中添加分页

    我正在尝试在我的 R Shiny 应用程序中添加分页 搜索框和选择器 但它现在不起作用 我尝试了分页 TRUE 和搜索 TRUE 在选项中 如下所示 但它不起作用 你知道我应该添加什么吗 output mytable1 lt DT rend
  • 从短信打开应用程序并获取 iOS 中的短信内容

    我正在尝试构建一个 iOS 应用程序 基本前提是用户收到一条包含消息 应用程序链接和其他详细信息的短信 例如 该消息可能如下所示 Good morning Kindly open the application mylink here Ad
  • 等待进程完成以启动另一个进程

    当用户单击我的按钮时 它会执行两个功能 发送短信和发送电子邮件 当我单击此按钮时 正在发送短信 突然弹出电子邮件选择客户端窗口 我希望仅在完成短信发送功能后才显示电子邮件客户端选择器窗口 我应该如何更改我的代码 Button hi Butt
  • 如何从 SQL 结果中提取数值数据

    假设有一个表 A 有 2 列 ID INT DATA VARCHAR 100 执行 SELECT DATA FROM A 的结果如下所示 DATA Nowshak 7 485 m Maja e Korabit Golem Korab 2 7
  • 如何区分应用程序中的测试属性和生产属性?

    我们正在开发一个大型 J2ee 电子销售解决方案 它有很多集成 CMS ERP 邮件服务器等 所有这些系统都分为测试和生产环境 我们需要使用测试配置将应用程序部署到测试服务器 而当部署到生产服务器时 它应该使用生产配置 我们如何让我们的应用
  • Swift 的 UITableView 示例

    我使用 Swift 和 iOS 已有好几个月了 我熟悉许多做事的方法 但我还不够好 我不能不看就直接写下来 我过去很欣赏 Stack Overflow 提供的快速答案 让我回到对我已经生疏的主题的正轨 例如 AsyncTask Androi
  • 如何开始将 django-cms 集成到现有项目中

    我的目的是将现有项目中的静态页面 关于我们 联系我们等 转换为管理可编辑页面 我已按照以下说明进行操作tutorial http django cms readthedocs org en 3 0 12 how to integrate h
  • W1024 组合有符号和无符号类型 - 扩大两个操作数

    我怎样才能防止这个警告 DCC 警告 uFvSystem pas 293 W1024 组合有符号和无符号类型 扩大了两个操作数 function LinkerTimestamp TDateTime overload begin Result
  • 为什么我不应该#include

    我用我的代码发布了一个问题 其唯一的 include指令如下 include
  • Chrome Devtools 以搜索方式打开,而不是开发工具本身

    尝试运行 Nativescript 调试会话 每次我进入 chrome devtools devtools bundled inspector html experiments true ws localhost 41000 它会打开谷歌搜
  • 全卷积网络的每像素 softmax

    我正在尝试实现类似全卷积网络的东西 其中最后一个卷积层使用大小为 1x1 的滤波器并输出 分数 张量 分数张量的形状为 Batch height width num classes 我的问题是 张量流中的什么函数可以对每个像素应用 soft
  • UITextView 绘制不可见/空白字符

    我将如何做一个UITextView为制表符 空格和换行符结尾绘制不可见字符 我认为必须在drawRect CGRect 方法或通过 Text Kit 中的布局管理器 有什么简单和 或直观的解决方案吗 我只需要知道如何获得CGRect每个空白
  • 如何在 Windows 8 Metro 应用程序中的设备中存储缩略图图像#

    我正在使用此代码创建缩略图并在框架中显示 平台 gt 使用 C 的 Windows 8 Metro 应用程序 http code msdn microsoft com windowsapps File and folder thumbnai
  • 使用 TextArea 通过 JavaFX 编辑大型文本文件

    有没有一种方法可以在 TextArea 中相当快地编辑相对较大的文本文件 例如 10 25 MB 或者也许可以禁用某些功能以使其更快 有替代组件吗 我了解 RichTextFX 但我想它会更慢 因为它做得更多 而且我只需要一个基本的编辑器
  • 单击按钮时关闭 jQuery 厚盒

    这是我的 jQuery script gt Html
  • 不同饼图中每个标签保持相同的颜色

    我无法为从一个饼图到另一个饼图的每个标签保持相同的颜色 如下图所示 Matplotlib 反转了第二个饼图中的颜色 我希望 Frogs 标签保持红色 Hogs 标签保持绿色 我也尝试添加label参数 但它只是给出了错误的计数 我还尝试反转
  • PHP $_FILES 文件循环上传

    我想从 php 函数将文件插入到 mysql 中 需要上传的文件已经存在于服务器上 所以我不想使用上传表单 我想循环遍历目录并将文件信息放入 FILES 请让我知道如何获得 file into FILES然后调用上传 dir handle
  • 在多个线程上并行调用 ICsharpCode.SharpZipLib 是否安全

    我们当前使用 ICsharpCode SharpZipLib 库的 GZipOutputStream 类进行压缩 我们通过一个线程来完成它 我想将输入数据流分割成块并并行压缩它们 我担心这个库内部可能有一些静态数据 这些静态数据会被多个线程