압축 알고리즘 성능 비교 실험 (Snappy / LZ4 / Gzip / Brotli / Zstd)
실험
- 테스트 데이터 : Lorem ipsum 텍스트를 100,000번 반복한 약 2.1MB 데이터를 사용했다. 압축 알고리즘이 패턴을 찾기 쉬운 반복적인 텍스트다.
- Snappy: Google의 빠른 압축
- LZ4: Fast, High, Level 1/3/6/9/12/17 총 8가지 변형
- Gzip: 전통적인 압축
- Brotli: Google의 웹 압축
- Zstd: Facebook의 최신 압축
- 각 사용한 라이브러리는 아래와 같다.
- Snappy:
org.xerial.snappy:snappy-java:1.1.10.8
- LZ4:
org.lz4:lz4-java:1.8.0
- Gzip: Java 표준 라이브러리 (
java.util.zip
) - Brotli:
com.aayushatharva.brotli4j:brotli4j:1.16.0
- Zstd:
com.github.luben:zstd-jni:1.5.7-4
- Snappy:
실험 방법
- 웜업: 각 알고리즘을 1,000번 실행해 JVM을 최적화했다.
- 측정: 10,000번씩 압축과 해제를 반복해 평균 시간을 계산했다.
- 메트릭: 압축 시간, 해제 시간, 압축 크기, 압축률을 측정.
웜업이 왜 필요한가?
JVM은 처음 실행되는 코드를 인터프리터로 실행하다가, 자주 호출되는 메서드는 JIT(Just-In-Time) 컴파일러가 최적화된 네이티브 코드로 컴파일한다. 따라서 첫 번째 실행과 수천 번째 실행의 성능이 크게 다를 수 있다. 웜업 과정을 거쳐야 진짜 성능을 측정할 수 있다.
결과
최종 벤치마크 결과는 다음과 같다:
Algorithm | Compress(ms) | Decompress(ms) | Size(bytes) | Ratio(%) |
---|---|---|---|---|
Snappy | 0.2533 | 0.3804 | 99557 | 4.74% |
LZ4-Fast | 0.1318 | 0.3358 | 8695 | 0.41% |
LZ4-High | 0.1328 | 0.3330 | 8663 | 0.41% |
LZ4-L1 | 0.1334 | 0.3338 | 8663 | 0.41% |
LZ4-L3 | 0.1314 | 0.3341 | 8663 | 0.41% |
LZ4-L6 | 0.1346 | 0.3344 | 8663 | 0.41% |
LZ4-L9 | 0.1401 | 0.3397 | 8663 | 0.41% |
LZ4-L12 | 0.1359 | 0.3383 | 8663 | 0.41% |
LZ4-L17 | 0.1355 | 0.3349 | 8663 | 0.41% |
Gzip | 6.6299 | 0.7781 | 5422 | 0.26% |
Brotli | 11.6460 | 1.0372 | 272 | 0.01% |
Zstd | 0.2413 | 0.3697 | 479 | 0.02% |
** 원본은 2MB 텍스트.
압축률 순위 (좋은 순)
- Brotli: 0.01% - 가장 뛰어난 압축률
- Zstd: 0.02%
- Gzip: 0.26%
- LZ4 변형들: 0.41%
- Snappy: 4.74% - 가장 나쁜 압축률
속도 순위 (빠른 순)
- LZ4 변형들: ~0.13ms - 가장 빠른 압축
- Zstd: 0.24ms
- Snappy: 0.25ms
- Gzip: 6.63ms
- Brotli: 11.65ms - 가장 느림
결론
- 속도가 중요하다면 LZ4가 최선의 선택이다.
- 압축률이 중요하다면 Brotli가 최고지만 매우 느리다.
- 균형을 원한다면 Zstd가 좋은 선택이다.
- Snappy는 빠르지만 압축률이 현저히 떨어진다.
- 반복적인 텍스트 데이터에서는 LZ4의 압축률이 생각보다 훌륭했다.
실제 사용시에는 데이터 특성과 요구사항에 따라 적절한 알고리즘을 선택해야 한다.
Furthermore…
https://github.com/byunjuneseok/lettuce-lz4-compression-codec
본인은 Lz4를 레디스에서 사용하고 싶기 때문에, 아래와 같은 패키지를 구현했다. Lettuce Redis LZ4 압축 코덱은 maven 저장소에서 사용할 수 있게 해두었다.