Java와 C의 zip 압축 연산에 대한 퍼포먼스 비교

먼저 C의 zip 압축은 Jean-loup Gailly님이 만들어 공개한 zlib 1.2.2를 사용했습니다. C/C++에서 데이터의 압축에서 사용하는 압축 라이브러리는 흔히 이 zlib를 사용합니다.  그리고 Java에서 압축은 기본적으로 제공하는 java.util.zip.Deflater 클래스를 사용했습니다. 테스트를 한 이유는 Java가 C/C++에 비해서 얼마나 느릴까… 하는 기대였습니다. =_=;

Java와 C/C++ 모두 사용한 압축 데이터는 0.2메가 정도되는 jpg 파일로 했습니다. 그리고 Java와 C/C++ 모두 결과는 압축 레벨을 3으로 했을때 동일한 결과와 크기였으며 원본 크기에 비해 75% 정도의 압축되었습니다. 결과는 다음 같습니다. 첫번째 이미지는 Java의 결과이고.. 두번째는 C/C++의 결과입니다.

사용자 삽입 이미지
와우!! Java가 C/C++에 비해 상당히 느릴것으로 기대했는데… 그렇지 않았습니다. C/C++와 성능은 거의 비슷한 것으로 생각됩니다. 두 경우 모두 최악의 경우 0.016초정도 소요됩니다. 다만…. Java의 경우 가끔씩 튀는 부분이 있었는데.. 0.031초 정도 소요되는 부분이 가끔 나옵니다. 아마도 Java의 gc기능 때문이 아닌가… 가볍게 짐작해봅니다. 하지만 이런 부분은 제외하면 정말 C/C++과 같은 Native 컴파일러 못지 않은 성능이라고 판단됩니다.

아래는 Java에서 퍼포먼스 테스트로 사용했던 코드입니다.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import java.io.*;

public class TestMain {
    public static void main(String[] args) 
        throws IOException, DataFormatException
    {
        FileInputStream fis = new FileInputStream("d:/a.jpg");
        ByteArrayOutputStream baos = new ByteArrayOutputStream(fis.available());
        byte [] buffer = new byte[512];
        int cntRead;
        while((cntRead=fis.read(buffer)) != -1) {
            baos.write(buffer, 0, cntRead);
        }

        byte[] compressedBytes = null;
        for(int i=0; i<20; i++) { // 20 times repeat..
            System.out.println("Performance Test Start...");
            long stime = System.currentTimeMillis();
 
            compressedBytes = Compress(baos.toByteArray());
   
            long etime = System.currentTimeMillis();
            System.out.println("Performance Test Result : " 
                + (etime-stime)+" MS.");
        }   
 
         FileOutputStream fos = new FileOutputStream("d:/a_java.jpg.zip");
         ByteArrayInputStream bais = new ByteArrayInputStream(compressedBytes);
         while((cntRead=bais.read(buffer)) != -1) {
             fos.write(buffer, 0, cntRead);
         }
    }

    private static byte[] Compress(byte[] bytesToCompress) throws IOException
    {
        Deflater compressor = new Deflater(3);
        compressor.setInput(bytesToCompress);
        compressor.finish();
 
        ByteArrayOutputStream bos = 
            new ByteArrayOutputStream(bytesToCompress.length);
 
        byte[] buf = new byte[bytesToCompress.length + 100];
        while (!compressor.finished())
        {
            bos.write(buf, 0, compressor.deflate(buf));
        }

        bos.close();
 
        return bos.toByteArray();
    }
}

대략 살펴보시면 위의 코드에는 IO에 대한 Buffer 기능과 같은.. 여전히 최적화의 여지가 남아 있습니다. 더 이상 제가 갖고 있는 “자바는 느리다”라는 선입견이 상당 부분 깨진 느낌입니다.

“Java와 C의 zip 압축 연산에 대한 퍼포먼스 비교”에 대한 9개의 댓글

  1. C/C++에서 zip으로 압축풀기를 하려고 검색을 하다보니 나왔네요… zip형태는 보이지 않는 곳에서 많이 있는 것 같아요. Office 2007의 xlsx, pptx, docx도 zip으로 압축이 되어 있는 형태이고, 국민은행에서 오래된 거래 내용을 조회할 때 다운받을 수 있는 kbz도 암호가 걸린 zip파일이네요..

    1. 네, jar도.. kml의 압축판인 kmz인가(?)도 모두 zip 방식의 압축으로 확장자만 바꾼 것이 많습니다.

  2. 주인장님 지나가다 끄적 거리고 갑니다.
    JDK 소스를 보시면 알수 있습니다만 자바의 압축 또한 zlib 을 사용하고 있죠…그래서 별반 차이 없습니다. 즉, 자바로 구현한다면 느리기 때문에 C의 Native Api를 사용하는 거죠~~

    1. 개발자마다 여러가지 의견이 있고.. 다소 주관적인 글이지만.. 코드만을 놓고 볼때 개발시 도움이 되셨으면 좋겠습니다.

  3. 이건 무의미한 속도비교입니다. 어차피 내부적으로 zlib 사용하는데 …
    이게 왜 c 와 java 의 속도비교가 될수있나요? Jni 로 call 했다는 자체가 그 순간부터는 자바가 아닌 네이티브 프로그램인거랍니다

  4. 자바코드 로 압축 알고리즘 구현해서 위처럼 돌리면 엄청난 속도차가 납니다 저건 단순히 자바에서 압축할때 c언어 프로그램 을 호출해서 돌려준거나 다름이 없습니다

    1. 님 말씀이 맞습니다. 이미 앞선 댓글도 비슷한 내용이 있는데…. 이 글을 쓴 요지는.. 서버를 개발할때 속도 문제로 C를 사용해야하지 않겠느냐라는 질문에 대해서.. 자바로도 C 못지 않는 속도를 낼수있다는 것이였습니다. 물론 자바가 내부적으로 C로 제작된 기능을 JNI를 사용하는 방식이지만 말입니다. 이 글을 쓴 이후로 저는 서버를 개발할때 예전에 그랬던 것처럼 C가 아닌 자바로 개발하고 있답니다. 속도나 이식성 면에서 C에 못지 않으니까요..

김형준에 답글 남기기 응답 취소

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다