一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - 通過(guò)Java測(cè)試幾種壓縮算法的性能(附測(cè)試代碼下載)

通過(guò)Java測(cè)試幾種壓縮算法的性能(附測(cè)試代碼下載)

2020-03-14 15:20goldensun JAVA教程

這篇文章主要介紹了通過(guò)Java測(cè)試幾種壓縮算法的實(shí)際性能的一個(gè)實(shí)驗(yàn),包括Java自帶的deflate與GZIP壓縮方式,還是有一定借鑒意義的,需要的朋友可以參考下

本文將會(huì)對(duì)常用的幾個(gè)壓縮算法的性能作一下比較。結(jié)果表明,某些算法在極端苛刻的CPU限制下仍能正常工作。

文中進(jìn)行比較的算有:

JDK GZIP ——這是一個(gè)壓縮比高的慢速算法,壓縮后的數(shù)據(jù)適合長(zhǎng)期使用。JDK中的java.util.zip.GZIPInputStream / GZIPOutputStream便是這個(gè)算法的實(shí)現(xiàn)。
JDK deflate ——這是JDK中的又一個(gè)算法(zip文件用的就是這一算法)。它與gzip的不同之處在于,你可以指定算法的壓縮級(jí)別,這樣你可以在壓縮時(shí)間和輸出文件大小上進(jìn)行平衡。可選的級(jí)別有0(不壓縮),以及1(快速壓縮)到9(慢速壓縮)。它的實(shí)現(xiàn)是java.util.zip.DeflaterOutputStream / InflaterInputStream。
LZ4壓縮算法的Java實(shí)現(xiàn)——這是本文介紹的算法中壓縮速度最快的一個(gè),與最快速的deflate相比,它的壓縮的結(jié)果要略微差一點(diǎn)。
Snappy——這是Google開(kāi)發(fā)的一個(gè)非常流行的壓縮算法,它旨在提供速度與壓縮比都相對(duì)較優(yōu)的壓縮算法。
壓縮測(cè)試

要找出哪些既適合進(jìn)行數(shù)據(jù)壓縮測(cè)試又存在于大多數(shù)Java開(kāi)發(fā)人員的電腦中(我可不希望你為了運(yùn)行這個(gè)測(cè)試還得個(gè)幾百兆的文件)的文件也著實(shí)費(fèi)了我不少工夫。最后我想到,大多數(shù)人應(yīng)該都會(huì)在本地安裝有JDK的文檔。因此我決定將javadoc的目錄整個(gè)合并成一個(gè)文件——拼接所有文件。這個(gè)通過(guò)tar命令可以很容易完成,但并非所有人都是Linux用戶(hù),因此我寫(xiě)了個(gè)程序來(lái)生成這個(gè)文件:

?
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 class InputGenerator {
  private static final String JAVADOC_PATH = "your_path_to_JDK/docs";
  public static final File FILE_PATH = new File( "your_output_file_path" );
 
  static
  {
    try {
      if ( !FILE_PATH.exists() )
        makeJavadocFile();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  private static void makeJavadocFile() throws IOException {
    try( OutputStream os = new BufferedOutputStream( new FileOutputStream( FILE_PATH ), 65536 ) )
    {
      appendDir(os, new File( JAVADOC_PATH ));
    }
    System.out.println( "Javadoc file created" );
  }
 
  private static void appendDir( final OutputStream os, final File root ) throws IOException {
    for ( File f : root.listFiles() )
    {
      if ( f.isDirectory() )
        appendDir( os, f );
      else
        Files.copy(f.toPath(), os);
    }
  }
}

在我的機(jī)器上整個(gè)文件的大小是354,509,602字節(jié)(338MB)。

測(cè)試

一開(kāi)始我想把整個(gè)文件讀進(jìn)內(nèi)存里,然后再進(jìn)行壓縮。不過(guò)結(jié)果表明這么做的話(huà)即便是4G的機(jī)器上也很容易把堆內(nèi)存空間耗盡。

于是我決定使用操作系統(tǒng)的文件緩存。這里我們用的測(cè)試框架是JMH。這個(gè)文件在預(yù)熱階段會(huì)被操作系統(tǒng)加載到緩存中(在預(yù)熱階段會(huì)先壓縮兩次)。我會(huì)將內(nèi)容壓縮到ByteArrayOutputStream流中(我知道這并不是最快的方法,但是對(duì)于各個(gè)測(cè)試而言它的性能是比較穩(wěn)定的,并且不需要花費(fèi)時(shí)間將壓縮后的數(shù)據(jù)寫(xiě)入到磁盤(pán)里),因此還需要一些內(nèi)存空間來(lái)存儲(chǔ)這個(gè)輸出結(jié)果。

下面是測(cè)試類(lèi)的基類(lèi)。所有的測(cè)試不同的地方都只在于壓縮的輸出流的實(shí)現(xiàn)不同,因此可以復(fù)用這個(gè)測(cè)試基類(lèi),只需從StreamFactory實(shí)現(xiàn)中生成一個(gè)流就好了:

?
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
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 2)
@Measurement(iterations = 3)
@BenchmarkMode(Mode.SingleShotTime)
public class TestParent {
  protected Path m_inputFile;
 
  @Setup
  public void setup()
  {
    m_inputFile = InputGenerator.FILE_PATH.toPath();
  }
 
  interface StreamFactory
  {
    public OutputStream getStream( final OutputStream underlyingStream ) throws IOException;
  }
 
  public int baseBenchmark( final StreamFactory factory ) throws IOException
  {
    try ( ByteArrayOutputStream bos = new ByteArrayOutputStream((int) m_inputFile.toFile().length());
       OutputStream os = factory.getStream( bos ) )
    {
      Files.copy(m_inputFile, os);
      os.flush();
      return bos.size();
    }
  }
}

這些測(cè)試用例都非常相似(在文末有它們的源代碼),這里只列出了其中的一個(gè)例子——JDK deflate的測(cè)試類(lèi);

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class JdkDeflateTest extends TestParent {
  @Param({"1", "2", "3", "4", "5", "6", "7", "8", "9"})
  public int m_lvl;
 
  @Benchmark
  public int deflate() throws IOException
  {
    return baseBenchmark(new StreamFactory() {
      @Override
      public OutputStream getStream(OutputStream underlyingStream) throws IOException {
        final Deflater deflater = new Deflater( m_lvl, true );
        return new DeflaterOutputStream( underlyingStream, deflater, 512 );
      }
    });
  }
}

測(cè)試結(jié)果

輸出文件的大小
首先我們來(lái)看下輸出文件的大小:

?
1
||實(shí)現(xiàn)||文件大小(字節(jié))|| ||GZIP||64,200,201|| ||Snappy (normal)||138,250,196|| ||Snappy (framed)|| 101,470,113|| ||LZ4 (fast)|| 98,316,501|| ||LZ4 (high) ||82,076,909|| ||Deflate (lvl=1) ||78,369,711|| ||Deflate (lvl=2) ||75,261,711|| ||Deflate (lvl=3) ||73,240,781|| ||Deflate (lvl=4) ||68,090,059|| ||Deflate (lvl=5) ||65,699,810|| ||Deflate (lvl=6) ||64,200,191|| ||Deflate (lvl=7) ||64,013,638|| ||Deflate (lvl=8) ||63,845,758|| ||Deflate (lvl=9) ||63,839,200||

通過(guò)Java測(cè)試幾種壓縮算法的性能(附測(cè)試代碼下載)

可以看出文件的大小相差懸殊(從60Mb到131Mb)。我們?cè)賮?lái)看下不同的壓縮方法需要的時(shí)間是多少。

壓縮時(shí)間

?
1
||實(shí)現(xiàn)||壓縮時(shí)間(ms)|| ||Snappy.framedOutput ||2264.700|| ||Snappy.normalOutput ||2201.120|| ||Lz4.testFastNative ||1056.326|| ||Lz4.testFastUnsafe ||1346.835|| ||Lz4.testFastSafe ||1917.929|| ||Lz4.testHighNative ||7489.958|| ||Lz4.testHighUnsafe ||10306.973|| ||Lz4.testHighSafe ||14413.622|| ||deflate (lvl=1) ||4522.644|| ||deflate (lvl=2) ||4726.477|| ||deflate (lvl=3) ||5081.934|| ||deflate (lvl=4) ||6739.450|| ||deflate (lvl=5) ||7896.572|| ||deflate (lvl=6) ||9783.701|| ||deflate (lvl=7) ||10731.761|| ||deflate (lvl=8) ||14760.361|| ||deflate (lvl=9) ||14878.364|| ||GZIP ||10351.887||

通過(guò)Java測(cè)試幾種壓縮算法的性能(附測(cè)試代碼下載)

我們?cè)賹嚎s時(shí)間和文件大小合并到一個(gè)表中來(lái)統(tǒng)計(jì)下算法的吞吐量,看看能得出什么結(jié)論。

吞吐量及效率

?
1
||實(shí)現(xiàn)||時(shí)間(ms)||未壓縮文件大小||吞吐量(Mb/秒)||壓縮后文件大小(Mb)|| ||Snappy.normalOutput ||2201.12 ||338 ||153.5581885586 ||131.8454742432|| ||Snappy.framedOutput ||2264.7 ||338 ||149.2471409017 ||96.7693328857|| ||Lz4.testFastNative ||1056.326 ||338 ||319.9769768045 ||93.7557220459|| ||Lz4.testFastSafe ||1917.929 ||338 ||176.2317583185 ||93.7557220459|| ||Lz4.testFastUnsafe ||1346.835 ||338 ||250.9587291688 ||93.7557220459|| ||Lz4.testHighNative ||7489.958 ||338 ||45.1270888301 ||78.2680511475|| ||Lz4.testHighSafe ||14413.622 ||338 ||23.4500391366 ||78.2680511475|| ||Lz4.testHighUnsafe ||10306.973 ||338 ||32.7933332124 ||78.2680511475|| ||deflate (lvl=1) ||4522.644 ||338 ||74.7350443679 ||74.7394561768|| ||deflate (lvl=2) ||4726.477 ||338 ||71.5120374012 ||71.7735290527|| ||deflate (lvl=3) ||5081.934 ||338 ||66.5101120951 ||69.8471069336|| ||deflate (lvl=4) ||6739.45 ||338 ||50.1524605124 ||64.9452209473|| ||deflate (lvl=5) ||7896.572 ||338 ||42.8033835442 ||62.6564025879|| ||deflate (lvl=6) ||9783.701 ||338 ||34.5472536415 ||61.2258911133|| ||deflate (lvl=7) ||10731.761 ||338 ||31.4952969974 ||61.0446929932|| ||deflate (lvl=8) ||14760.361 ||338 ||22.8991689295 ||60.8825683594|| ||deflate (lvl=9) ||14878.364 ||338 ||22.7175514727 ||60.8730316162|| ||GZIP ||10351.887 ||338 ||32.651051929 ||61.2258911133||

通過(guò)Java測(cè)試幾種壓縮算法的性能(附測(cè)試代碼下載)

可以看到,其中大多數(shù)實(shí)現(xiàn)的效率是非常低的:在Xeon E5-2650處理器上,高級(jí)別的deflate大約是23Mb/秒,即使是GZIP也就只有33Mb/秒,這大概很難令人滿(mǎn)意。同時(shí),最快的defalte算法大概能到75Mb/秒,Snappy是150Mb/秒,而LZ4(快速,JNI實(shí)現(xiàn))能達(dá)到難以置信的320Mb/秒!

從表中可以清晰地看出目前有兩種實(shí)現(xiàn)比較處于劣勢(shì):Snappy要慢于LZ4(快速壓縮),并且壓縮后的文件要更大。相反,LZ4(高壓縮比)要慢于級(jí)別1到4的deflate,而輸出文件的大小即便和級(jí)別1的deflate相比也要大上不少。

因此如果需要進(jìn)行“實(shí)時(shí)壓縮”的話(huà)我肯定會(huì)在LZ4(快速)的JNI實(shí)現(xiàn)或者是級(jí)別1的deflate中進(jìn)行選擇。當(dāng)然如果你的公司不允許使用第三方庫(kù)的話(huà)你也只能使用deflate了。你還要綜合考慮有多少空閑的CPU資源以及壓縮后的數(shù)據(jù)要存儲(chǔ)到哪里。比方說(shuō),如果你要將壓縮后的數(shù)據(jù)存儲(chǔ)到HDD的話(huà),那么上述100Mb/秒的性能對(duì)你而言是毫無(wú)幫助的(假設(shè)你的文件足夠大的話(huà))——HDD的速度會(huì)成為瓶頸。同樣的文件如果輸出到SSD硬盤(pán)的話(huà)——即便是LZ4在它面前也顯得太慢了。如果你是要先壓縮數(shù)據(jù)再發(fā)送到網(wǎng)絡(luò)上的話(huà),最好選擇LZ4,因?yàn)閐eflate75Mb/秒的壓縮性能跟網(wǎng)絡(luò)125Mb/秒的吞吐量相比真是小巫見(jiàn)大巫了(當(dāng)然,我知道網(wǎng)絡(luò)流量還有包頭,不過(guò)即使算上了它這個(gè)差距也是相當(dāng)可觀的)。

總結(jié)

如果你認(rèn)為數(shù)據(jù)壓縮非常慢的話(huà),可以考慮下LZ4(快速)實(shí)現(xiàn),它進(jìn)行文本壓縮能達(dá)到大約320Mb/秒的速度——這樣的壓縮速度對(duì)大多數(shù)應(yīng)用而言應(yīng)該都感知不到。
如果你受限于無(wú)法使用第三方庫(kù)或者只希望有一個(gè)稍微好一點(diǎn)的壓縮方案的話(huà),可以考慮下使用JDK deflate(lvl=1)進(jìn)行編解碼——同樣的文件它的壓縮速度能達(dá)到75Mb/秒。
源代碼

Java壓縮測(cè)試源碼

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲国产综合网 | yellow视频在线观看 | 国产精品亚洲精品日韩已方 | 免费观看网站 | 波多野结中文字幕在线69视频 | 欧美一级久久久久久久大片 | 麻生希无码 | 2019天天干夜夜操 | 猥琐对着美女飞机喷到脸上 | 日本加勒比一区 | 成人黄色a级片 | 亚洲网红精品大秀在线观看 | 精品网站一区二区三区网站 | 亚洲欧美日韩另类在线 | 国产精品日本一区二区不卡视频 | 日韩一二三| 岛国片免费观看 | 精品久久久久中文字幕日本 | 国产精品精品 | 大伊人青草狠狠久久 | 日韩久久综合 | 亚洲妇熟xxxxx妇色黄 | 星空无限传媒xk8129 | 国产高清一区二区三区免费视频 | 草留色区| 日韩成人在线免费视频 | 免费看国产精品麻豆 | 色97色| 日韩丝袜在线观看 | 精品AV综合导航 | 肥胖女人一级毛片 | 国产不卡视频一区二区在线观看 | 免费精品国产在线观看 | 亚洲四虎影院 | 国产91免费 | 黑人同学征服教师麻麻 | 亚洲va久久久久综合 | 精品久久久久久亚洲精品 | 成人毛片高清视频观看 | 奇米影视999 | 水蜜桃一二二区视在线 |