먼저 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 기능과 같은.. 여전히 최적화의 여지가 남아 있습니다. 더 이상 제가 갖고 있는 “자바는 느리다”라는 선입견이 상당 부분 깨진 느낌입니다.