`
fantaxy025025
  • 浏览: 1279154 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Java压缩算法性能比较

 
阅读更多

==

=

-

from:Java压缩算法性能比较 

https://my.oschina.net/OutOfMemory/blog/805427

https://blog.csdn.net/u013063153/article/details/53729047

真原文在这里:http://codingo.xyz/index.php/2016/12/13/java_compress/

 

前言
游戏开发中,经常在玩家进入游戏的时候进行必要的信息初始化,往往这个初始化信息数据包是相对来说还是比较大的,一般在30-40kb左右,还是有必要进行压缩一下再发送消息,刚好前段时间看过<hadoop权威指南 style="box-sizing: border-box;">,里面列举了一些常用的压缩算法,如下图所示:
1
是否可切分表示是否可以搜索数据流的任意位置并进一步往下读取数据,这项功能在Hadoop的MapReduce中尤其适合。
下面对这几种压缩格式进行简单的介绍,并进行压力测试,进行性能比较

DEFLATE
DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法,DEFLATE压缩与解压的源代码可以在自由、通用的压缩库zlib上找到,zlib官网:http://www.zlib.net/ 
jdk中对zlib压缩库提供了支持,压缩类Deflater和解压类Inflater,Deflater和Inflater都提供了native方法

1
2
private native int deflateBytes(long addr, byte[] b, int off, int len,
                                    int flush);
1
2
private native int inflateBytes(long addr, byte[] b, int off, int len)
           throws DataFormatException;

所有可以直接使用jdk提供的压缩类Deflater和解压类Inflater,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  public static byte[] compress(byte input[]) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    Deflater compressor = new Deflater(1);
    try {
        compressor.setInput(input);
        compressor.finish();
        final byte[] buf = new byte[2048];
        while (!compressor.finished()) {
            int count = compressor.deflate(buf);
            bos.write(buf, 0, count);
        }
    } finally {
        compressor.end();
    }
    return bos.toByteArray();
}
 
  public static byte[] uncompress(byte[] input) throws DataFormatException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    Inflater decompressor = new Inflater();
    try {
        decompressor.setInput(input);
        final byte[] buf = new byte[2048];
        while (!decompressor.finished()) {
            int count = decompressor.inflate(buf);
            bos.write(buf, 0, count);
        }
    } finally {
        decompressor.end();
    }
    return bos.toByteArray();
}

可以指定算法的压缩级别,这样你可以在压缩时间和输出文件大小上进行平衡。可选的级别有0(不压缩),以及1(快速压缩)到9(慢速压缩),这里使用的是以速度为优先。

gzip
gzip的实现算法还是deflate,只是在deflate格式上增加了文件头和文件尾,同样jdk也对gzip提供了支持,分别是GZIPOutputStream和GZIPInputStream类,同样可以发现GZIPOutputStream是继承于DeflaterOutputStream的,GZIPInputStream继承于InflaterInputStream,并且可以在源码中发现writeHeader和writeTrailer方法:

1
2
3
4
5
6
private void writeHeader() throws IOException {
     ......
}
private void writeTrailer(byte[] buf, int offset) throws IOException {
     ......
}

具体的代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static byte[] compress(byte srcBytes[]) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip;
        try {
            gzip = new GZIPOutputStream(out);
            gzip.write(srcBytes);
            gzip.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }
 
    public static byte[] uncompress(byte[] bytes) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        try {
            GZIPInputStream ungzip = new GZIPInputStream(in);
            byte[] buffer = new byte[2048];
            int n;
            while ((n = ungzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        return out.toByteArray();
    }

bzip2
bzip2是Julian Seward开发并按照自由软件/开源软件协议发布的数据压缩算法及程序。Seward在1996年7月第一次公开发布了bzip2 0.15版,在随后几年中这个压缩工具稳定性得到改善并且日渐流行,Seward在2000年晚些时候发布了1.0版。更多wikibzip2
bzip2比传统的gzip的压缩效率更高,但是它的压缩速度较慢。
jdk中没有对bzip2实现,但是在commons-compress中进行了实现,maven引入:

1
2
3
4
5
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.12</version>
</dependency>

具体的代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static byte[] compress(byte srcBytes[]) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    BZip2CompressorOutputStream bcos = new BZip2CompressorOutputStream(out);
    bcos.write(srcBytes);
    bcos.close();
    return out.toByteArray();
}
 
public static byte[] uncompress(byte[] bytes) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    try {
        BZip2CompressorInputStream ungzip = new BZip2CompressorInputStream(
                in);
        byte[] buffer = new byte[2048];
        int n;
        while ((n = ungzip.read(buffer)) >= 0) {
            out.write(buffer, 0, n);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
 
    return out.toByteArray();
}

下面的介绍的lzo,lz4以及snappy这3中压缩算法,均已压缩速度为优先,但压缩效率稍逊一筹。

lzo
LZO是致力于解压速度的一种数据压缩算法,LZO是Lempel-Ziv-Oberhumer的缩写。这个算法是无损算法,更多wikiLZO
需要引入第三方库,maven引入:

1
2
3
4
5
<dependency>
    <groupId>org.anarres.lzo</groupId>
    <artifactId>lzo-core</artifactId>
    <version>1.0.5</version>
</dependency>

具体实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static byte[] compress(byte srcBytes[]) throws IOException {
    LzoCompressor compressor = LzoLibrary.getInstance().newCompressor(
            LzoAlgorithm.LZO1X, null);
 
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    LzoOutputStream cs = new LzoOutputStream(os, compressor);
    cs.write(srcBytes);
    cs.close();
 
    return os.toByteArray();
}
 
public static byte[] uncompress(byte[] bytes) throws IOException {
    LzoDecompressor decompressor = LzoLibrary.getInstance()
            .newDecompressor(LzoAlgorithm.LZO1X, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ByteArrayInputStream is = new ByteArrayInputStream(bytes);
    LzoInputStream us = new LzoInputStream(is, decompressor);
    int count;
    byte[] buffer = new byte[2048];
    while ((count = us.read(buffer)) != -1) {
        baos.write(buffer, 0, count);
    }
    return baos.toByteArray();
}

lz4
LZ4是一种无损数据压缩算法,着重于压缩和解压缩速度更多wikilz4
maven引入第三方库:

1
2
3
4
5
<dependency>
    <groupId>net.jpountz.lz4</groupId>
    <artifactId>lz4</artifactId>
    <version>1.2.0</version>
</dependency>

具体代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static byte[] compress(byte srcBytes[]) throws IOException {
    LZ4Factory factory = LZ4Factory.fastestInstance();
    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
    LZ4Compressor compressor = factory.fastCompressor();
    LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(
            byteOutput, 2048, compressor);
    compressedOutput.write(srcBytes);
    compressedOutput.close();
    return byteOutput.toByteArray();
}
 
public static byte[] uncompress(byte[] bytes) throws IOException {
    LZ4Factory factory = LZ4Factory.fastestInstance();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    LZ4FastDecompressor decompresser = factory.fastDecompressor();
    LZ4BlockInputStream lzis = new LZ4BlockInputStream(
            new ByteArrayInputStream(bytes), decompresser);
    int count;
    byte[] buffer = new byte[2048];
    while ((count = lzis.read(buffer)) != -1) {
        baos.write(buffer, 0, count);
    }
    lzis.close();
    return baos.toByteArray();
}

snappy
Snappy(以前称Zippy)是Google基于LZ77的思路用C++语言编写的快速数据压缩与解压程序库,并在2011年开源。它的目标并非最大压缩率或与其他压缩程序库的兼容性,而是非常高的速度和合理的压缩率。更多wikisnappy
maven引入第三方库:

1
2
3
4
5
<dependency>
    <groupId>org.xerial.snappy</groupId>
    <artifactId>snappy-java</artifactId>
    <version>1.1.2.6</version>
</dependency>

具体代码实现:

1
2
3
4
5
6
7
public static byte[] compress(byte srcBytes[]) throws IOException {
    return  Snappy.compress(srcBytes);
}
 
public static byte[] uncompress(byte[] bytes) throws IOException {
    return Snappy.uncompress(bytes);
}

压力测试
以下对35kb玩家数据进行压缩和解压测试,相对来说35kb数据还是很小量的数据,所有以下测试结果只是针对指定的数据量区间进行测试的结果,并不能说明哪种压缩算法好与不好。
测试环境:
jdk:1.7.0_79
cpu:i5-4570@3.20GHz 4核
memory:4G

对35kb数据进行2000次压缩和解压缩测试,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void main(String[] args) throws Exception {
    FileInputStream fis = new FileInputStream(new File("player.dat"));
    FileChannel channel = fis.getChannel();
    ByteBuffer bb = ByteBuffer.allocate((int) channel.size());
    channel.read(bb);
    byte[] beforeBytes = bb.array();
 
    int times = 2000;
    System.out.println("压缩前大小:" + beforeBytes.length + " bytes");
    long startTime1 = System.currentTimeMillis();
    byte[] afterBytes = null;
    for (int i = 0; i < times; i++) {
        afterBytes = GZIPUtil.compress(beforeBytes);
    }
    long endTime1 = System.currentTimeMillis();
    System.out.println("压缩后大小:" + afterBytes.length + " bytes");
    System.out.println("压缩次数:" + times + ",时间:" + (endTime1 - startTime1)
            + "ms");
 
    byte[] resultBytes = null;
    long startTime2 = System.currentTimeMillis();
    for (int i = 0; i < times; i++) {
        resultBytes = GZIPUtil.uncompress(afterBytes);
    }
    System.out.println("解压缩后大小:" + resultBytes.length + " bytes");
    long endTime2 = System.currentTimeMillis();
    System.out.println("解压缩次数:" + times + ",时间:" + (endTime2 - startTime2)
            + "ms");
}

代码中的GZIPUtil根据不同的算法进行替换,测试结果如下图所示:
5
分别对压缩前大小、压缩后大小、压缩时间、解压缩时间、cpu高峰进行了统计

总结
从结果来看,deflate、gzip和bzip2更关注压缩率,压缩和解压缩时间会更长;lzo,lz4以及snappy这3中压缩算法,均已压缩速度为优先,压缩率会稍逊一筹;lzo,lz4以及snappy在cpu高峰更低一点。因为在容忍的压缩率之内,我们更加关注压缩和解压缩时间,以及cpu使用,所有最终使用了snappy,不难发现snappy在压缩和解压缩时间以及cpu高峰都是最低的,并且在压力率上也没有太多的劣势。

 

-

=

==

 

分享到:
评论

相关推荐

    java自带压缩方式的性能比较

    通过提供的代码文件`CompressTestMain.java`、`GzipUtils.java`和`ZipUtils.java`,我们可以推测作者可能构建了一个测试环境,比较了Gzip和Zip压缩算法在实际操作中的性能差异。 首先,让我们了解Gzip和Zip的基本...

    通过Java测试几种压缩算法的性能(附测试代码下载)

    在本文中,我们将探讨如何通过Java来测试不同的压缩算法,并分析它们的性能。实验中涉及了JDK内置的GZIP和Deflate算法,以及LZ4和Snappy这两种高效的第三方压缩算法。这些测试对于理解不同压缩算法在实际应用中的...

    java实现视频压缩

    在IT行业中,视频压缩是一项重要的技术,特别是在网络传输和存储大量视频内容时。Java作为一种广泛使用的编程语言,也提供...这需要开发者具备扎实的Java基础,熟悉多媒体处理和压缩算法,以及如何使用相关的第三方库。

    java算法,实现压缩及解压缩

    ### Java算法:实现压缩及解压缩 #### 一、压缩功能实现 在Java中实现文件压缩功能主要依赖于`java.util.zip`包中的类。以下是对压缩代码的详细解析: ##### 1. 导入所需类库 ```java import java.io....

    各类压缩算法聚合

    本文将深入探讨“压缩算法 集合 java”这一主题,结合Java编程语言,阐述压缩算法的基本原理、常用算法以及如何在Java环境中实现和应用。 首先,压缩算法是一种用于减小数据量的技术,通过消除数据中的冗余信息,...

    用Java实现的道格拉斯-普克压缩算法

    标签“Java”表明我们关注的是Java语言的实现,“道格拉斯”和“压缩算法”则是指具体的算法实现。在实现时,Java提供了丰富的数据结构(如ArrayList或LinkedList)来存储点序列,以及数学库(如java.awt.geom.Line...

    几种无损数据压缩算法的探讨及在java web程序中的应用.pdf

    本文主要探讨了几种常见的无损压缩算法,并分析了它们在Java Web程序中的应用。 一、Huffman编码(哈夫曼编码) Huffman编码是一种广泛使用的无损压缩算法,由David Huffman在1952年提出。其原理是根据字符在数据中...

    算术算法压缩实现Java

    以下是关于算术压缩算法及其Java实现的详细讲解。 算术编码的基本原理: 1. **概率模型**:在压缩前,对输入数据建立概率模型。每个可能的符号(例如,文本中的字符)被赋予一个概率,这个概率反映了该符号在数据流...

    压缩算法.docx

    压缩算法在IT行业中扮演着重要的角色,特别是在数据传输和存储方面。本文主要探讨了网络上主流的压缩算法,包括...在实际应用中,开发者需根据需求选择合适的压缩算法,同时考虑到性能、资源消耗和兼容性等因素。

    LZ78算法实现对任意字符串的压缩与解压

    LZ78压缩算法是一种基于字典的无损数据压缩方法,由Abraham Lempel、Jacob Ziv和Stu Arkin在1977年提出。它通过查找输入字符串中的最长匹配前缀来构建一个新的编码,从而实现数据的压缩。这种算法的主要思想是创建一...

    Burrows-Wheeler压缩算法JAVA实现

    Burrows-Wheeler转换(BWT)是一种数据预处理技术,常用于文本压缩算法,它由Michael Burrows和David Wheeler在1994年提出。这个算法的核心思想是通过重新排列输入字符串中的字符顺序,使其形成高度重复的模式,从而...

    Google新开源压缩算法Brotli

    标题和描述中提到的知识点包括了Brotli压缩算法及其与Deflate、Zopfli、LZMA、LZHAM和Bzip2压缩算法的比较。...同时,也提供了对其他几种主流压缩算法性能的评估,以及在不同应用场景下选择合适压缩算法的参考依据。

    LZ77压缩,js&java版本

    Java实现LZ77压缩算法的过程与JavaScript类似,但Java提供了更丰富的数据结构和优化的性能。主要步骤如下: 1. 使用`StringBuilder`或自定义的数据结构存储滑动窗口和压缩结果。 2. 利用`String`类的`indexOf()`方法...

    22、MapReduce使用Gzip压缩、Snappy压缩和Lzo压缩算法写文件和读取相应的文件

    在大数据处理领域,...同时,了解各种压缩算法的特点和性能,对于优化Hadoop集群的性能和资源利用率至关重要。在实际操作中,应根据具体的数据特性和业务需求,进行适当的测试和调优,以找到最适合的压缩策略。

    JavaCompressionAlgorithm:一个简单的Java压缩算法

    在这个"JavaCompressionAlgorithm:一个简单的Java压缩算法"项目中,我们可以期待看到如何利用这些Java内置的压缩和解压缩类进行实际操作,包括可能的性能优化和错误处理。这个项目可以帮助开发者深入理解Java中压缩...

    压缩算法及其代码实现

    在IT领域,压缩算法是数据处理和存储的关键技术之一,其主要目的是减小文件的大小,从而节省存储空间和提高传输效率。LZW(Lempel-Ziv-Welch)压缩算法是一种广泛应用的无损数据压缩方法,尤其在文本、图像和音频...

    Java压缩PNG图像文件.rar

    总结来说,Java压缩PNG图像文件是一个涉及图像处理和压缩算法的复杂过程。开发者需要理解图像的内部结构,选择合适的压缩策略,并可能需要编写自定义的压缩代码以实现最佳的文件大小与质量平衡。对于J2ME游戏开发,...

    Java经典算法源码实例(Java算法,源码)

    这个名为“Java经典算法源码实例”的资源集合提供了一系列用Java语言实现的常见算法,对于深入理解算法原理、提高编程技能以及优化代码性能具有极大的帮助。下面,我们将详细探讨这些算法及其应用。 1. **排序算法*...

    Java常用算法手册源代码

    算法基础篇 **章 算法和实现算法的Java语法 1.1 建立算法初步概念 1.1.1 什么是算法 1.1.2 算法的发展历史 1.1.3 算法的分类 ...**2章 压缩与解压缩算法 第3篇 算法面试篇 **3章 数学能力测试 **4章 算法面试题

Global site tag (gtag.js) - Google Analytics