乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java不同壓縮算法的性能比較

       codingparty 2015-01-04

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

      文中進行比較的算有:

    • JDK GZIP ——這是一個壓縮比高的慢速算法,壓縮后的數(shù)據(jù)適合長期使用。JDK中的java.util.zip.GZIPInputStream / GZIPOutputStream便是這個算法的實現(xiàn)。
    • LZ4壓縮算法[/url]的 Java實現(xiàn) ——這是本文介紹的算法中壓縮速度最快的一個,與最快速的deflate相比,它的壓縮的結果要略微差一點。如果想搞清楚它的工作原理,我建議你讀一下 這篇文章 。它是基于友好的Apache 2.0許可證發(fā)布的。

      壓縮測試

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

      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);
          }
        }
      }
      

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

      測試

      一開始我想把整個文件讀進內存里,然后再進行壓縮。不過結果表明這么做的話即便是4G的機器上也很容易把堆內存空間耗盡。

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

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

      @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();
          }
        }
      }
      

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

      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 );
            }
          });
        }
      }
      

      測試結果

      輸出文件的大小

      首先我們來看下輸出文件的大?。?/p>

      ||實現(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||

      可以看出文件的大小相差懸殊(從60Mb到131Mb)。我們再來看下不同的壓縮方法需要的時間是多少。

      壓縮時間

      ||實現(xiàn)||壓縮時間(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||

      我們再將壓縮時間和文件大小合并到一個表中來統(tǒng)計下算法的吞吐量,看看能得出什么結論。

      吞吐量及效率

      ||實現(xiàn)||時間(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||

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

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

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

      總結

      源代碼

      原創(chuàng)文章轉載請注明出處:

    • JDK deflate ——這是JDK中的又一個算法(zip文件用的就是這一算法)。它與gzip的不同之處在于,你可以指定算法的壓縮級別,這樣你可以在壓縮時間和輸出文件大小上進行平衡??蛇x的級別有0(不壓縮),以及1(快速壓縮)到9(慢速壓縮)。它的實現(xiàn)是java.util.zip.DeflaterOutputStream / InflaterInputStream。
    • [url=http://en./wiki/LZ4_%28compression_algorithm%29]
    • Snappy ——這是Google開發(fā)的一個非常流行的壓縮算法,它旨在提供速度與壓縮比都相對較優(yōu)的壓縮算法。我用來測試的是[這個實現(xiàn)[/url]。它也是遵循Apache 2.0許可證發(fā)布的。
    • 如果你認為數(shù)據(jù)壓縮非常慢的話,可以考慮下LZ4(快速)實現(xiàn),它進行文本壓縮能達到大約320Mb/秒的速度——這樣的壓縮速度對大多數(shù)應用而言應該都感知不到。
    • 如果你受限于無法使用第三方庫或者只希望有一個稍微好一點的壓縮方案的話,可以考慮下使用JDK deflate(lvl=1)進行編解碼——同樣的文件它的壓縮速度能達到75Mb/秒。
      • 本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多