고속 압축 알고리즘 비교 테스트: LZO/Snappy/SynLZ/LZ4/QuickLZ/Zlib

통상적인 시각으로는 파일 압축이란 가급적 작은 크기로 줄이는 압축률을 우선으로 따지지만, 그런 용도 외에 아주 빠른 압축 알고리즘이 필요할 때가 있습니다. 그런 경우는 주로, 전체 프로세싱 작업 구간들중에서 메모리 속도보다 훨씬 느릴 수밖에 없는 네트워크 전송 구간이나 디스크 저장 구간의 속도가 주요 이슈가 될 때입니다.

로직 흐름상으로는 그냥 그대로 전송 혹은 저장해도 될 파일을 압축해서 전체적인 효율을 높이려면, 당연히 네트워크나 디스크의 처리 속도보다 압축 및 압축해제 속도가 훨씬 빨라야만 합니다. 네트워크 혹은 디스크에서 절약되는 시간이 압축 및 압축해제에 추가로 들어가는 시간보다 훨씬 커야만 실용성이 있는 거죠.

이를 위해서는 일반적인 압축 알고리즘인 Zip/GZip/BZip2 등에 비해 압축 및 압축해제 속도가 압도적으로 빠른 고속 압축 알고리즘이 필요합니다. 이런 목적으로 가장 오래전부터 쓰여온 대표적인 알고리즘으로는 LZO가 있으며, 이 LZO에 대항하는 목적으로 비교적 최근인 2011년에 구글이 발표한 Snappy도 비교적 잘 알려져 있습니다. 일반적으로 LZO와 Snappy는 전반적으로 비슷하지만, 압축률은 근소하게 LZO가 더 높고 압축 속도는 근소하게 Snappy가 더 빠른 것 같습니다.

하지만 세상에는 이 두가지 알고리즘 외에도 이들과 경쟁하는 수없이 많은 다른 알고리즘들도 나와있습니다. 그 많은 알고리즘들 중에 LZO와 Snappy보다 월등하다고 주장하는 대표적인 알고리즘으로는 QuickLZ와 LZ4가 있고, 델파이 전용으로도 SynLZ라는 코드도 이들보다 훨씬 빠르다고 주장합니다. 어떤 알고리즘은 대놓고 world’s fastest라고 주장하기도 하며, 경쟁 알고리즘에 비해 속도 우위를 주장하는 각자의 벤치마크 테스트 결과를 내놓기도 합니다.

저는 개인적으로 지난해부터 SynLZ를 사용해오고 있는데, 오직 델파이용이라는 상대적 불리도 있습니다만 LZO와 Snappy 양쪽 모두에 비해 더 높은 압축률과 더 높은 속도를 보여주기 때문입니다. 저는 이 SynLZ를 기업용 모바일앱과 애플리케이션 서버 사이의 데이터 통신 구간 및 모바일앱측 로컬 데이터 저장에 사용하고 있습니다.

그런데 최근 들어 나머지 조금 덜 알려진(사실 속도가 중요한 개발자들에게는 아주 유명한 것들이지만) QuickLZ와 LZ4에 대해서도 테스트를 해보고 싶어졌습니다. 모바일 앱과 윈도우를 포괄하는 엔터프라이즈 비즈니스 프레임워크를 준비하고 있어서, 장기적으로 어떤 경우에든 속도와 압축률 면에서 최선이라고 믿을 수 있는 솔루션이 필요해서입니다.

그래서 직접 샘플 코드를 만들어 비교 테스트를 해봤습니다. 비교 대상은, LZO, Snappy, SynLZ, LZ4, QuickLZ, Zlib 이렇게 여섯가지입니다. (Zlib은 고속 압축용이 아니지만 고속압축 알고리즘에 익숙하지 않은 분들에게 참고가 될까 싶어 일부러 넣었습니다)

LzoSnappy

제가 테스트한 방법은 아주 단순합니다. 각 알고리즘별로 100kB 정도 되는 json 파일을 지정된 횟수만큼(기본으로 1000회) 압축하는 데 드는 시간과 동일한 횟수만큼 압축해제를 하는 데 드는 시간, 그 합산 시간, 그리고 마지막으로 압축된 크기 및 압축률을 표시했습니다. 여기서 시간은 ms 단위이며 압축률은 원본파일 대비 크기 비율입니다. (대체로 이런 고속 압축 알고리즘은 64비트에서 최고의 성능이 나온다고 하지만, 범용적인 목적으로 테스트를 하는 거라서 32비트로 빌드했습니다)

먼저 고속압축 알고리즘이 아닌 ZLib부터 잠깐만 따져봅시다. 당연히 압축률은 원본파일 대비 22%로 가장 높은 압축률을 보이지만, 속도가 정말 안습입니다. 다른 알고리즘이 1천회의 압축 및 압축해제를 최대 0.5초 이내에 끝냈는데 ZLib은 무려 2초가 넘어 비교의 대상 자체가 안됩니다. 이것만 봐도 네트워크/디스크 구간에서 전체 성능을 위한 압축 알고리즘으로 ZLib을 선택해서는 안되는 이유가 바로 보이실 겁니다.

이제부터 본격 비교입니다. 비교적 덜 중요한 압축률을 보면, SynLZ와 QuickLZ가 27%로 가장 높은 압축률을 보입니다. SynLZ가 조금 더 높습니다. 반면 LZ4가 30%로 가장 낮은 압축률을 보이는데, 그래봐야 1등인 SynLZ와의 차이는 3%에 불과하며, 압축된 크기 기준으로 보면 10%의 차이밖에 안됩니다. 눈깜짝할 사이에 압축 및 해제를 하는 고속 압축 알고리즘의 목적으로는 압축해서 30% 미만으로 줄여주는 정도면 다들 충분하고도 남습니다.

압축 속도의 면에서 보면, 단연 LZ4가 가장 앞섭니다. 압축과 해제 1천회씩을 반복하는 데에 0.268초밖에 안걸려서 타의 추종을 불허하는 수준입니다. 가장 느린 LZO의 경우 0.444초가 걸렸는데 이 정도면 정말 엄청난 차이입니다. 당연히, 절대적으로 빠른 속도가 필요하다면 닥치고 LZ4가 정답입니다.

한편 world’s fastest라고 주장하는 QuickLZ는 실제로는 LZ4보다 압축속도 면에서 한참 뒤쳐지며, SynLZ보다도 압축률 뿐만 아니라 속도 면에서도 약간씩 떨어집니다.

LZO와 Snappy는 속도와 압축률 양쪽 모두에서 그다지 크게 고려할 필요가 없을 것 같습니다. 다른 알고리즘들에 비해 대체로 속도 및 압축률 모두 좀 떨어지는 편입니다. LZO가 압축률은 조금 앞서고 압축속도는 Snappy가 조금 빠르지만, 다른 알고리즘들에 비하면 도토리 키재기입니다.

이게 끝이 아닙니다. 중요한 팩터 하나가 더 있죠. LZO는 가장 오랫동안 사용되어온만큼 가장 다양한 플랫폼으로 이식되어 있고, 하둡을 포함한 많은 상용/공개 패키지에서조차 옵션으로 채용되어 있을 정도입니다. 범용성에서는 절대 갑입니다. Snappy도 급속도로 사용 빈도가 높아지고 있어 뒤쫓아가고 있지만, LZO와 비교 대상이 아닙니다. 플랫폼 이식에서 아직 한참 멀었습니다. 다양한 플랫폼 이식이 필요하다면 LZO가 정답입니다.

반면 LZ4와 QuickLZ는 떨어지는 인지도만큼 이식된 범위가 Snappy보다도 더 좁습니다. 이 테스트에서도 Snappy와 QuickLZ 두 가지는 dll을 가져다 썼으며, LZ4는 win32 ming로 컴파일된 오브젝트 파일을 갖다썼습니다. 제가 주요하게 다루어야 하는 안드로이드 이식은 세가지 모두 안되어 있는 것으로 보입니다. 원본 코드들이 C, C++ 코드들이라 약간씩 수정해가며 포팅을 하면 되겠지만 아주 민감한 알고리즘들이라 그리 쉬운 일이 아닐 겁니다.

델파이 개발환경에만 국한된다면 여러가지 이유로 SynLZ가 가장 좋다고 보입니다. 압축률도 가장 높고 속도도 LZ4 다음으로는 가장 높습니다. SynLZ의 소스는 x86 어셈블리 코드로 수작업 최적화되어 있지만, 조건 컴파일로 pure pascal 기반 코드도 있기 때문에 안드로이드 이식도 어렵지 않습니다. (실제 제가 안드로이드-윈도우 사이에서 SynLZ를 사용중입니다) 안드로이드에서의 퓨어 파스칼 코드도 좋은 성능을 냅니다.

한가지 더 고려해야 할 것들. 이 알고리즘들은 텍스트와 바이너리 파일 사이에서 조금씩 다른 성향을 보이며, 압축 대상 파일의 크기 면에서는 더 큰 차이를 보입니다. 제가 100kB의 json 파일로 중점적으로 테스트한 것은 제가 다루는 패킷 크기가 그 정도이고 데이터가 json 포맷이기 때문입니다. 아래는 2.4MB의 json 파일로 100회 테스트했을 경우의 결과입니다.

100kB 파일의 경우와 결과가 조금 다르죠. LZ4가 압도적으로 빠르고 SynLZ와 QuickLZ가 가장 압축률이 높다는 점에는 것은 변함이 없지만, Snappy의 경우 완전히 다른 결과를 보여줍니다. 압축률이 크게 떨어져 꼴찌가 되면서 압축속도는 거꾸로 SynLZ 및 QuickLZ보다 빨라져 2등으로 올라섰습니다. 아마도 Snappy는 조금 특이하게, 일정 수준 이상의 크기에 대해서는 압축률을 상당부분 양보하면서 속도를 끌어올리려 애쓴 것 같은데, 좋은 결과 같지는 않습니다. 압축 속도에서 여전히 LZ4를 전혀 따라가지 못하면서 압축률은 LZ4보다 더 떨어졌으니까요.

이번에는 반대로 더 작은 파일로, 10kB짜리 json 파일로 테스트해보죠. 파일이 작아진만큼 반복횟수를 10000번으로 늘렸습니다.

역시 LZ4가 탁월하게 빠릅니다. 압축률 면에서 SynLZ와  QuickLZ가 가장 좋은 것도 동일하고요. 그런데 특이한 현상은, 이렇게 작은 크기의 파일에선 LZO의 속도가 거의 LZ4에 근접할만큼 빨라진 대신, Snappy의 속도는 거꾸로 크게 떨어져 꼴찌로 전락했습니다. 무려 4.5배나 차이가 나죠. Snappy가 MB 단위의 대형 패킷을 위주로 최적화하려 노력한 듯 싶은데 그 반대급부로 작은 파일에 대해서는 극단적으로 성능이 떨어지는군요. 반대로 LZO는 큰 파일에서는 큰 파일에서는 속도가 조금 떨어지는 대신 작은 파일에서 놀랍도록 빠릅니다.

총평입니다.

  1. 속도가 절대적으로 중요하다면 두말없이 LZ4가 답입니다. 호환성이 떨어지는 편이지만 속도가 그렇게 중요한 환경이라면 직접 포팅도 해볼만 합니다.
  2. 범용적인 목적으로는 Snappy를 쓸 이유가 없다고 봅니다. MB 단위의 비교적 큰 파일들에 특화되어있지만 큰 파일에서조차도 LZ4보다도 꽤 큰 격차로 느리고, 그렇다고 LZ4에 비해 딱히 호환성이 월등하지도 않습니다.
  3. 여러 플랫폼 및 언어 시스템과 상호운용이 가능해야 한다면 역시 LZO입니다. 가장 광범위하게 쓰여왔기에 다양한 언어와 플랫폼으로 포팅되어 있으니까요.
  4. QuickLZ는 world’s fastest라는 말과 정반대로 속도보다는 압축률 위주로 최적화된 알고리즘인 것 같습니다. 델파이가 아닌 환경에서 높은 압축률이 중요하다면 QuickLZ도 괜찮을 것 같습니다.
  5. SynLZ는 델파이 코드밖에 없어 다른 언어 개발자들에게는 사용이 제한되지만(dll로 빌드해서 다른 언어에서 호출할 수는 있죠) 델파이 언어 안에서는 안드로이드 등 모바일 포팅도 용이하고 속도와 압축률 양쪽 모두에서 좋은 선택입니다.

아래는 사족입니다.

  1. 가장 빠른 속도를 보여주는 LZ4는 더욱 빠른 모드도 있습니다. 최근에 개발중인 거라 정식 릴리즈는 안된 상태인데, fast 모드로 돌리면 기존 LZ4보다 1.8배 정도 더욱 빨라진다고 합니다. 당연히 그만큼 압축률은 꽤 떨어지게 됩니다.
  2. 이 테스트에 사용된 LZO 코드는 기본인 C 코드가 아닌 SynLZ의 개발자가 델파이 및 어셈블리로 더 최적화한 버전입니다. 아마도 기본 버전보다 조금 정도 더 빠르겠죠.
  3. 앞서도 썼지만, 고속 압축 알고리즘을 위해서는 일반적으로 32비트보다 64비트 빌드가 더 유리할 겁니다. 64비트 환경에서 운용할 목적이라면 직접 64비트로 빌드해서 테스트를 해보시길 권합니다.
  4. 역시 앞에서 썼지만, Snappy와 QuickLZ 두 가지는 컴파일된 dll을 가져다 썼으며, LZ4는 win32 ming로 컴파일된 오브젝트 파일을 링크했습니다.
  5. 제대로 된 정식 속도 벤치마크라면 더 작은 크기의 파일들로부터 시작해 순차적으로 여러 테스트를 진행해야 하겠지만, 귀찮아서 그렇게까지는 하지 않았습니다.
  6. 전문적인 벤치마크가 아닌만큼 제가 실수로 누락했거나 간과한 조건이 있을 수도 있습니다. 미리 양해 부탁드립니다.

아래는 이 테스트에 사용된 테스트 프로그램과 그 소스입니다. 다양한 파일들로 직접 테스트를 해보실 수 있습니다.

테스트 프로그램

테스트 프로그램 소스

5 comments for “고속 압축 알고리즘 비교 테스트: LZO/Snappy/SynLZ/LZ4/QuickLZ/Zlib

  1. 좋은 정보 감사합니다. ^^

    zlib 테스트 하고 있었는데 얼른 마무리 짓고 LZ4 해봐야겠네요..

    우선 상용개발 해도 괜찮은지 라이선스 문제 확인해봐야겠군요 -_ -ㅋ

     

  2. 라이센스 문제도 고려하면 선택이 달라질수 있겠네요

    LZO : GPL
    Snappy : BSD
    SynLZ : MPL/GPL/LGPL
    LZ4 : BSD
    QuickLZ : GPL, commercial

  3. 꼼꼼하게 잘 비교해 놓아서 도움이 많이 되었습니다.

    lz4 압축 알고리즘의 성능이 좋으네요.^^

답글 남기기

이메일 주소는 공개되지 않습니다.