速度之王 — LZ4压缩算法与其他算法的比较

LZ4 (Extremely Fast Compression algorithm)

项目:http://code.google.com/p/lz4/

作者:Yann Collet

本文作者:zhangskd @ csdn blog

 

简介
 

LZ4 is a very fast lossless compression algorithm, providing compression speed at 400MB/s per core,

scalable with multi-cores CPU. It also features an extremely fast decoder, with speed in multiple GB/s per core,

typically reaching RAM speed limits on multi-core systems.

A high compression derivative, called LZ4_HC, is also provided. It trades CPU time for compression ratio.

 

(1) 横向对比

Quick comparison: single thread, Core i5-3340M @2.7GHz, using the Open-Source Benchmark by m^2 (v0.14.2)

compiled with GCC v4.6.1 on Linux Ubuntu 64-bits v11.10, using the Silesia Corpus.

对比当前流行的压缩工具,可以看到LZ4具有最快的压缩和解压速度,尽管压缩比一般。

 

 

QuickLZ官网:http://www.quicklz.com/

QuickLZ is the world's fastest compression library, reaching 308MB/s per core.

QuickLZ自称是世界上最快的压缩算法,然而我们看到它和LZ4还是有差距的,特别是解压速度。

 

snappy项目:https://code.google.com/p/snappy/

snappy is developed by Google based on ideas from LZ77 and open-sourced in 2011.

It was designed to be very fast and stable, but not to achieve a high compression ratio.

Compression speed is 250MB/s and decompression speed is 500MB/s using a single threaded,

64-bit core i7 processor. The compression ratio is 20-100% lower than gzip.

snappy追求的是速度,压缩比并不高。

 

(2) 纵向对比

LZ4能很好的支持多线程环境,获得更高的压缩和解压速度。

 

(3) 技术背景

多媒体技术 -> 无损压缩 -> 词典编码 -> LZ77算法 -> LZ4

词典编码(Dictionary Encoding),根据的是数据本身包含有重复代码序列这个特性。

主要分为两类:

1. 查找正在压缩的字符序列是否在前面输入数据中出现过,如果是,则用指向早期出现过的字符串的“指针”替代

    重复的字符串。这里的“词典”是指以前处理过的数据。(LZ77、LZSS)。

2. 从输入的数据中创建一个“短语词典”,编码数据过程中当遇到已经在词典中出现过的“短语”时,编码器就输

    出这个词典中的短语的“索引号”,而不是短语本身。(LZ78、LZW)

 

(4) 其它格式

以下是一些常用的压缩格式。

1. zip

    zlib库,可通过包含zlib.h使用。

    zip原名为Deflate,仅支持一个LZ77的变种算法Deflate。

    zip/unzip,后缀为.zip。zip也是Windows下常见的压缩格式。

2. gzip

    gzip/gunzip是GNU程序,后缀为.gz。Web也常用GZIP压缩技术。

    首先使用LZ77算法进行压缩,对结果再使用huffman编码进行压缩。

    tar中用-z来调用:

         tar -czf pic.tar.gz *.jpg

         tar -xzf pic.tar.gz

3. bzip2

    bzip2/bunzip2,后缀为.bz2。

    相比于gzip,压缩比更高,压缩效果比传统的LZ77/LZ78更好,但压缩速度较慢。

    首先使用Burrows-Wheeler变换(BWT,块排序文本压缩),然后使用哈夫曼编码进行压缩。

    tar中使用-j来调用:

        tar -cjf pic.tar.bz2 *.jpg

        tar -xjf pic.tar.bz2

4. compress

    compress/uncompress,后缀为.Z,现在已经不再流行了。

    使用LZ78算法的变种LZW。

    tar中使用-Z来调用。

6. rar

    rar/unrar,后缀为.rar。

    rar格式较zip格式的压缩比高。

    注意RAR非免费,是Windows下常见压缩格式,也有RAR for Linux。

        rar a pic *.jpg // pic.rar

        rar e pic.rar // pic

7. 7z

    7-Zip,后缀为.7z。

    和rar、zip一样,7z也是Windows下常见的压缩格式。

    使用改良与优化后的LZ77算法LZMA、LZMA2,压缩比高于zip。

8. xz

    xz,后缀为.xz。

    如果说LZ4是压缩速度之王,xz则是压缩比之王。

    一般来说,用xz压缩后的文件,能比用gzip压缩的小30%,比用bzip2压缩的小15%。

    主要使用LZMA2压缩算法。

    tar不支持xz格式,xz / xz -d。

 

LZ77
 

我们看到很多压缩格式都是基于LZ77的,所以先来了解下LZ77算法,这里引用了较多的网上资料:)

1977年,Jacob Ziv和Abraham Lempel描述了一种基于滑动窗口缓存的技术,该缓存用于保存最近刚刚处理的文本。

LZ77编码的核心是查找从前向缓冲器开始的最长的匹配串。

 

压缩算法使用了两个缓存:

1. 滑动历史缓存,包含了前面处理过的N个源字符。

2. 前向缓存,包含了将要处理的下面L个字符。

 

压缩过程

算法尝试将前向缓存开始的两个或多个字符与滑动历史缓存中的字符串相匹配。

如果没有发现匹配,前向缓存的第一个字符作为9bit的字符输出并且移入滑动窗口,滑动窗口中最久的字符被移除。

如果找到匹配,算法继续扫描以找到最长的匹配。然后匹配字符串作为三元组输出(选项、指针和长度)。对于K个字符

的字符串,滑动窗口中最久的K个字符被移出,并且被编码的K个字符被移入窗口。

 

更具体来说:

1. 从当前压缩位置开始,查看未编码的数据,并试图在滑动窗口中找出最长的匹配字符串,如果找到,则进行步骤2,否则进行步骤3。

2. 输出三元符号组(off, len, c)。其中off为窗口中匹配字符串相对窗口边界的偏移,len为可匹配的长度,c为下一个字符。

    然后将窗口向后滑动len + 1个字符,继续步骤1。

3. 输出三元符合组(0, 0, c)。其中c为下一个字符。然后将窗口向后滑动len + 1个字符,继续步骤1。

 

实例

假设窗口大小为10个字符,我们刚编码过的字符(滑动窗口)是:abcdbbccaa,即将编码的字符(前向缓存)是:abaeaaabaee。

1. 和编码字符匹配的最长串为ab,下一个字符为a,输出三元组(0, 2, a)。

    窗口向后滑动3个字符为:dbbccaaaba,前向缓存为:eaaabaee。

2. 字符e在窗口中无匹配,输出三元组(0, 0, e),窗口向后滑动1个字符为:bbccaaabae,前向缓存为:aaabaee。

3. 前向缓存的最长匹配串为aaabae,下一个字符为e,输出三元组(4, 6, e),完成编码。

 

解压过程

解压算法必须保存解压输出的最后N个字符(滑动窗口)。

当碰到编码字符串时,使用指针和长度字段,将编码替换成实际的正文字符串。

 

评价

算法使用了有限的窗口在以前的文本中查找匹配,对于相对于窗口大小来说非常长的文本块,很多可能的匹配就会被丢掉。

窗口大小可以增加,但这会带来两个损失:

1. 算法的处理时间会增加,因为它必须为滑动窗口的每个位置进行一次与前向缓存的字符串匹配的工作。

2. 指针字段必须更长,以允许更长的跳转。

 

在多数情况下,lz77拥有较高的压缩效率。而在待压缩文件中绝大多数是些超长匹配,并且相同的超长匹配高频率地反复

出现时,lzw更具优势。GIF就是采用了lzw算法来压缩背景单一、图形简单的图片。zip是用来压缩通用文件的,这就是它

采用对大多数文件有更高压缩率的lz77算法的原因。

 

优化

精心设计三元组(off, len, c)中每个分量的表示方法,才能达到较好的效果。

(1) off

off为窗口内的偏移,通常的经验是,偏移接近窗口尾部的情况要多于接近窗口头部的情况,这是因为字符串在与其接近的

位置容易找到匹配串,但对于普通的窗口大小(如4096字节)来说,偏移值基本还是均匀分布的,我们完全可以用固定的位

数来表示它。

(2) len

len为字符串长度,它在大多数时候不会太大,少数情况下才会发生大字符串的匹配。显然可以使用一种变长编码方式来表

示该长度值。要输出变长的编码,该编码必须满足前缀码的条件。Huffman编码可以用于此处,但不是最好的选择。

Golomb编码应用比较广泛,对于较小的数用较短的编码,对较大的数用较大的编码表示。

(3) c

c为前向缓存中的不匹配字符。直接用8个二进制位编码。

(4) 输出格式

LZ77的原始算法采用三元组输出每一个匹配串及其后续字符,即使没有匹配,仍需要输出一个len=0的三元组来表示单个字符。

实验表明,这种方式对于某些特殊情况(例如同一字符不断重复的情形)有着较好的适应能力。

对一般数据,有一种更有效的输出方式。

将每一个输出分成匹配串和单个字符两种类型,并首先输出一个二进制位对其加以区分。例如,输出0表示下面是一个匹配串,

输出1表示下面是一个单个字符。之后,如果要输出的是单个字符,我们直接输出该字符的字节值,需要8个二进制位。

也就是说,输出一个单个的字符共需要9个二进制位。

如果要输出的是匹配串,则输出off和len。off可以用定长编码,也可以用变长前缀码。len用变长前缀码。有时候我们可以对匹配

长度加以限制,例如,限制最少匹配3个字符。因为对于2个字符的匹配串,我们使用匹配串的输出方式不一定比我们直接输出2

个单个字符(共需18位)节省空间。

这种输出方式的优点是:输出单个字符的时候比较节省空间。另外,因为不强求每次都外带一个后续字符,可以适应一些较长

匹配的情况。

(5) 查找匹配串

在滑动窗口中查找最长的匹配串,是LZ77算法中的核心问题,关系着空间和时间复杂度。

 

golomb
 

哥伦布编码。主要针对整数进行编码,对较小的数用较短的编码,对较大的数用较大的编码表示。

假设x为要进行编码的整数,当x趋于较小的取值时候,此时的Golomb编码较短,可以有效的节省空间。

 

压缩算法:

1. 选定参数m,b = 2^m,注意m是要在压缩前指定的。

2. q = <int> ((x - 1) / b),<int>表示取整。

3. r = x - qb - 1,所以x = qb + r + 1。(注意这个1不用存储,只要默认恢复出来的数据加1即可)

4. 这样要编码的x由两部分组成:

    a. 第一部分由q个1加上一个0组成,表示q。

    b. 第二部分由m个位组成,表示r。

 

恢复算法:

如果读入1,则继续往后读,直到读入0,此时读入的1的个数就是q。

之后的m位(m事先约定了)为r。

所以可以计算出x = qb + 1 + r = q * 2^m + r + 1。

 

Reference
 

[1]. http://fastcompression.blogspot.com/p/lz4.html

[2]. http://jpkc.zust.edu.cn/2007/dmt/course/MMT03_05_1.htm

[3]. http://jpkc.zust.edu.cn/2007/dmt/course/MMT03_05_2.htm

[4]. http://hi.baidu.com/guoliqiang2006/item/127c8f989b494b4ef14215db

[5]. http://blog.chinaunix.net/uid-17240700-id-3347894.html

[6]. http://jpkc.zust.edu.cn/2007/dmt/course/Mmt03_02_2.htm

[7]. http://tukaani.org/xz/
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我用过的DOS命令

我用过的DOS命令 1、进入当前目录的子目录&#xff1a;cd xxx 2、放回到当前目录的上一子目录&#xff1a;cd.. 3、返回到根目录&#xff1a;cd/ 5、进入到指定目录&#xff1a;先键入指定目录的本目录如D盘&#xff1a;D: 然后回车键入cd xxx\xxx\xxx\xxx\xxx 如图&#xf…

XAMPP 无法启动解决

当安装完XAMPP后&#xff0c;在XAMPP Control Panel 里面无法启动apache,网上找了很多都是关于apache端口冲突问题&#xff0c;但我的不是&#xff0c;解决步骤如下&#xff1a;1&#xff1a;进入apache目录 conf/httpd.conf 改变监听端口&#xff1a;Listen 8080--启动任然失败…

lz4压缩算法--速度之王

简介 lz4是目前综合来看效率最高的压缩算法&#xff0c;更加侧重压缩解压速度&#xff0c;压缩比并不是第一。在当前的安卓和苹果操作系统中&#xff0c;内存压缩技术就使用的是lz4算法&#xff0c;及时压缩手机内存以带来更多的内存空间。本质上是时间换空间。 压缩原理 lz…

Mac OS defaults命令(Access the Mac OS user defaults system)

defaults命令: 用于访问和修改Mac 上一些系统的默认设置&#xff08;Access the Mac OS user defaults system&#xff09; 仅修改当前用户设置&#xff0c;所以不应加sudo。 用法&#xff1a; 读取所有默认配置&#xff1a; defaults read 读取某项配置&#xff1a; defaults …

推荐12个绚丽的CSS3图片悬停效果

CSS3为我们开发提供了很多特效&#xff0c;如鼠标悬停&#xff0c;线性渐变&#xff0c;在web开发早期常用的是鼠标悬停&#xff0c;他是网页制作的常用特效之一&#xff0c;早期使用Flash可以制作非常炫的效果&#xff0c;后来慢慢演变成现在的是图片悬停效果&#xff0c;现在…

SAP和ABAP内存的区别

1、读取哈使用方法不同SAP内存使用SET/GET parameters方法&#xff1b;ABAP内存使用 EXPORT 和 IMPORT 方法&#xff1b;2、共享范围不同SAP内存可以被所有的主session访问&#xff0c;内存数据可以同一个session中不同程序之间&#xff0c;或者不同session之间&#xff1b;AB…

RocksDB事务实现TransactionDB分析

基本概念 1. LSN (log sequence number) RocksDB中的每一条记录(KeyValue)都有一个LogSequenceNumber(后面统称lsn)&#xff0c;从最初的0开始&#xff0c;每次写入加1。该值为逻辑量&#xff0c;区别于InnoDB的lsn为redo log物理写入字节量。 我有几张阿里云幸运券分享给你&…

Leetcode 771. Jewels and Stones

class Solution(object):def numJewelsInStones(self, J, S):""":type J: str:type S: str:rtype: int"""countcollections.Counter(S)ans0for j in J:anscount.get(j,0)return ans 转载于:https://www.cnblogs.com/zywscq/p/10562590.html

iptables规则的增删改查

1、查看 iptables -nvL --line-number -L 查看当前表的所有规则&#xff0c;默认查看的是filter表&#xff0c;如果要查看NAT表&#xff0c;可以加上-t NAT参数 -n 不对ip地址进行反查&#xff0c;加上这个参数显示速度会快很多 -v 输出详细信息&#xff0c;包含通过该规则的数…

2010.3.13郊野公园小记,以及参观托驼峰航线纪念碑

今天是周末&#xff0c;也是个晴好的天气(罪过&#xff0c;今年云南大旱&#xff0c;希望早点下雨吧&#xff09;。去了趟昆明西北郊的郊野公园&#xff0c;09年的时候成龙的<大兵小将>也曾经在此公园取景。 首先上图的是公园里的驼峰航线纪念碑&#xff0c;也差不多到清…

HDFS的读/写流程

1.HDFS读流程 HDFS读流程 1.1 、Client通过FileSystem.open(filePath)方法,与NN节点进行【rpc】协议通信&#xff0c;校验是否有权限是否存在&#xff0c;假如都ok&#xff0c;返回该文件的部分或全部的block的列表(包含各个block块的分布在DN地址的列表)&#xff0c;也就是返…

VS Code设置中文插件

Vscode是一款开源的跨平台编辑器。默认情况下&#xff0c;vscode使用的语言为英文(en) 1&#xff09;打开vscode工具&#xff1b; 2&#xff09;使用快捷键组合【CtrlShiftp】&#xff0c;在搜索框中输入“configure display language”&#xff0c;点击确定后&#xff1b; 3&a…

1.4 CDA扩展

本地定义的标记可能被使用当本地的语义在CDA规范中没有相应的表述。当为不共享的标签的含义提供一个简洁、标准的机制时&#xff0c;CDA力求在最高的层次上共享的语义上进行标准化。为了支持本地扩展的需求&#xff0c;包含CDA架构之外的XML节点和属性是允许的。这些扩展不应该…

如何:将 TraceSource 和筛选器与跟踪侦听器一起使用(转载)

本文转载&#xff1a;http://msdn.microsoft.com/zh-cn/library/ms228993.aspx .NET Framework 2.0 版中的新功能之一就是增强的跟踪系统。基本的前提并未改变&#xff1a;跟踪消息通过开关发送到侦听器&#xff0c;侦听器则向关联的输出介质报告数据。2.0 版的一个主要区别在于…

C++排序之stable_sort()的方法

stable_sort()可以对vector的某个成员进行排序&#xff0c;而且可保证相等元素的原本相对次序在排序后保持不变。 下面是该函数的实现方法代码&#xff1a; #include <iostream> #include<math.h> #include <string> #include <vector> #include <…

linhaifeng fullstack

fullstack day02: 数据类型、字符编码、文件处理 http://www.cnblogs.com/linhaifeng/articles/7133357.html 转载于:https://www.cnblogs.com/marcoxu/p/10564094.html

javascript校验2

* 判断字符串是否符合指定的正则表达式 */ Java代码 function f_check_formatStr(obj) { var str obj.value; var dtype obj.eos_datatype; var regu dtype.substring(dtype.indexOf("(")1,dtype.indexOf(")")); //指定的正则表…

抓取qq邮箱联系人

今天是:2010-03-14 &#xff0c;纪念昨晚熬到3点! 题外话&#xff1a;模拟登陆请求页面这次我用了httpclient4.0&#xff0c;也顺便学习一下&#xff0c;4.0跟以前的版本用法上有很大的不同&#xff0c;具体情况Google一下就知道了&#xff0c;个人觉得知道原理就行了&#xff…

HDFS的Block size的默认大小

今天无意中听到了同事说关于HDFS中每个block的大小&#xff0c;特意查了下&#xff1a; 从Hadoop的官网上看了各个版本的说明文档中关于 Data Blocks 的说明&#xff0c;发现是从2.7.3版本开始&#xff0c;官方关于Data Blocks 的说明中&#xff0c;block size由64 MB变成了12…

Jconsole查看Weblogic自定义MBean

简单的Jconsole连接到weblogic进程&#xff0c;只能连接Platform MBean server,看不到自定义MBean。 这时我们需要连接到 WebLogic MBean server&#xff0c;通过如下方式&#xff1a; 1. 创建wlfulclient.jar 1) cd %WL_HOME%/server/lib 2) java -jar wljarbuilder.jar 2. 启…