단일파일압축 기반 고성능 압축 알고리즘, zstd

단일파일압축 기반 고성능 압축 알고리즘, zstd
Photo by Tim Mossholder / Unsplash

zstd (Zstandard)

  • 페이스북에서 개발한 빠르고 효율적인 압축 알고리즘입니다.
  • 높은 압축률과 빠른 압축 및 해제 속도를 제공합니다.

Motivation

  • zstd는 높은 압축률과 빠른 속도를 모두 제공하기 위해 개발되었습니다. 많은 데이터 처리와 전송이 필요한 환경에서 효율성을 높이기 위함입니다.
    • 스트리밍 지원: zstandard는 스트리밍 압축 및 해제를 지원합니다. 이는 실시간 데이터 처리나 네트워크 전송 시 매우 유용합니다. 단일 파일을 압축하는 방식은 이러한 스트리밍 지원을 더 쉽게 구현할 수 있게 합니다.
    • 단일 파일 압축에 집중함으로써 구현과 사용의 단순성을 유지할 수 있습니다. 이는 개발 및 유지보수 측면에서 장점을 제공합니다.
  • 알고리즘 유형: LZ77 알고리즘을 기반으로 하며, 압축 속도와 해제 속도 모두를 최적화한 방식입니다.

Pros

  • 빠른 속도: 압축과 해제 속도가 매우 빠릅니다.
    • 압축 속도: zstd > gzip
    • 실시간 스트리밍 데이터 압축이 필요한 경우 zstandard가 적합합니다. 예를 들어, 로그 파일을 실시간으로 압축하여 전송하거나 저장할 때 유용합니다.
    • 대용량 로그 파일, 데이터 백업, 데이터베이스 덤프 등의 작업에서 매우 유용합니다.
    • 해제 속도: zstd > gzip
    • 압축률: zstd > gzip
  • 높은 압축률: 데이터 손실 없이 높은 압축률을 제공합니다.
    • 네트워크 대역폭을 절약하거나 저장 공간을 줄여야 할 때 zstandard가 좋은 선택입니다.
  • 효율성: CPU와 메모리 사용이 효율적입니다.

Cons

  • 호환성: 일부 시스템에서는 기본적으로 지원되지 않을 수 있습니다.
  • 복잡성: 다양한 옵션이 있어 설정이 복잡할 수 있습니다.

Alternative

  • lz4: 매우 빠른 압축 및 해제 속도를 제공하는 또 다른 알고리즘입니다.
  • brotli: 구글에서 개발한 압축 알고리즘으로, 웹 전송에 최적화되어 있습니다.

Sample

import zstandard as zstd

# 파일 압축
def compress_file(input_file, output_file):
    with open(input_file, 'rb') as f_in, open(output_file, 'wb') as f_out:
        compressor = zstd.ZstdCompressor()
        f_out.write(compressor.compress(f_in.read()))

# 파일 압축 해제
def decompress_file(input_file, output_file):
    with open(input_file, 'rb') as f_in, open(output_file, 'wb') as f_out:
        decompressor = zstd.ZstdDecompressor()
        f_out.write(decompressor.decompress(f_in.read()))

compress_file('example.txt', 'example.txt.zst')
decompress_file('example.txt.zst', 'example_decompressed.txt')

  • 속도 비교를 위한 코드

import os
import time
import subprocess

# 테스트할 디렉토리 이름
directory_name = "test_directory"

# 압축 및 압축 해제 함수
def measure_time(command):
    start_time = time.time()
    subprocess.run(command, shell=True)
    end_time = time.time()
    return end_time - start_time

# tar.gz 압축 및 압축 해제 시간 측정
tar_gz_compress_command = f"tar -czvf {directory_name}.tar.gz {directory_name}"
tar_gz_decompress_command = f"tar -xzvf {directory_name}.tar.gz"
tar_gz_compress_time = measure_time(tar_gz_compress_command)
tar_gz_decompress_time = measure_time(tar_gz_decompress_command)

# zstd 압축 및 압축 해제 시간 측정
tar_zstd_compress_command = f"tar -I zstd -cvf {directory_name}.tar.zst {directory_name}"
tar_zstd_decompress_command = f"tar -I zstd -xvf {directory_name}.tar.zst"
tar_zstd_compress_time = measure_time(tar_zstd_compress_command)
tar_zstd_decompress_time = measure_time(tar_zstd_decompress_command)

# 결과 출력
print(f"tar.gz 압축 시간: {tar_gz_compress_time:.2f} 초")
print(f"tar.gz 압축 해제 시간: {tar_gz_decompress_time:.2f} 초")
print(f"zstd 압축 시간: {tar_zstd_compress_time:.2f} 초")
print(f"zstd 압축 해제 시간: {tar_zstd_decompress_time:.2f} 초")

Shell

  • 기본 압축
    • 압축된 파일명까지 지정한 경우
zstd example.txt -o example_compressed.zst
  • 압축수준 설정
    • -19가 최대압축, 기본 압축 수준을 -3
zstd -19 example.txt
  • 압축 해제
zstd -d example.txt.zst
  • 디렉토리 압축
    • zstd는 단일 파일만 압축할 수 있습니다. 디렉토리를 압축하려면 tar와 함께 사용해야 합니다.
tar -I zstd -cvf archive.tar.zst directory_name/

  • 디렉토리 압축 해제(tar와 함께 사용)
tar -I zstd -xvf archive.tar.zst
  • 속도 비교를 위한 스크립트
#!/bin/bash

# 테스트할 디렉토리 이름
DIRECTORY_NAME="test_directory"
TAR_GZ_FILE="${DIRECTORY_NAME}.tar.gz"
ZSTD_FILE="${DIRECTORY_NAME}.tar.zst"

# tar.gz 압축 및 압축 해제 시간 측정
echo "Measuring tar.gz compression and decompression time..."

START_TIME=$(date +%s%N)
tar -czvf $TAR_GZ_FILE $DIRECTORY_NAME
END_TIME=$(date +%s%N)
TAR_GZ_COMPRESS_TIME=$(( ($END_TIME - $START_TIME) / 1000000 ))

START_TIME=$(date +%s%N)
tar -xzvf $TAR_GZ_FILE
END_TIME=$(date +%s%N)
TAR_GZ_DECOMPRESS_TIME=$(( ($END_TIME - $START_TIME) / 1000000 ))

# zstd 압축 및 압축 해제 시간 측정
echo "Measuring zstd compression and decompression time..."

START_TIME=$(date +%s%N)
tar -I zstd -cvf $ZSTD_FILE $DIRECTORY_NAME
END_TIME=$(date +%s%N)
TAR_ZSTD_COMPRESS_TIME=$(( ($END_TIME - $START_TIME) / 1000000 ))

START_TIME=$(date +%s%N)
tar -I zstd -xvf $ZSTD_FILE
END_TIME=$(date +%s%N)
TAR_ZSTD_DECOMPRESS_TIME=$(( ($END_TIME - $START_TIME) / 1000000 ))

# 결과 출력
echo "tar.gz 압축 시간: $TAR_GZ_COMPRESS_TIME ms"
echo "tar.gz 압축 해제 시간: $TAR_GZ_DECOMPRESS_TIME ms"
echo "zstd 압축 시간: $TAR_ZSTD_COMPRESS_TIME ms"
echo "zstd 압축 해제 시간: $TAR_ZSTD_DECOMPRESS_TIME ms"

💬 Own Summary