TL;DR

  • NDJSON 파일을 256KiB 단위의 독립 프레임으로 나눈 zstd로 압축하면, 64개 스레드에서 초당 40GB를 파싱할 수 있음.
  • 5백만 레코드, 총 812MB의 합성 NDJSON 파일에서 활성 레코드 수와 특정 조건에 맞는 점수 합계를 계산하는 벤치마크임.
  • gzip은 이전 출력의 32KiB가 필요한 단일 스트림이므로 압축 해제는 한 스레드에서 순차 실행해야 하며, 파싱을 병렬화해도 속도는 초당 2.5GB에 그침.
  • zstd와 lz4는 독립 프레임을 스레드별로 처리할 수 있어, 64개 스레드에서 각각 초당 40GB, 초당 34GB를 기록함.
  • zstd 파일은 gzip보다 6% 크지만, JSON 파일 작성 방식을 제어할 수 있다면 다중 프레임 압축으로 훨씬 빠른 병렬 처리가 가능함.

NDJSON 파일 파싱

  • JSON 데이터를 문서 하나씩 한 줄에 저장하는 형식은 NDJSON(JSON Lines)이며, 로그 파일, 데이터베이스 내보내기, 머신러닝 데이터셋에서 자주 사용됨.
  • 대용량 파일은 압축할 수 있으며, 벤치마크에서는 812MB의 NDJSON 파일에 든 5백만 개 레코드를 처리함.
  • 각 레코드에서 일부 필드를 읽고, 활성 레코드 수를 세며, 사용자에게 admin 태그가 있는 활성 레코드의 점수를 합산함.

청크 단위 압축 해제와 파싱

  • 파일 전체를 먼저 압축 해제하는 대신, 압축된 파일에서 청크를 압축 해제하고 완전한 줄을 파싱한 뒤 마지막의 미완성 줄을 버퍼 앞쪽으로 옮기는 방식임.
  • NDJSON 문서 안에는 줄바꿈 문자가 그대로 들어갈 수 없으며, 문자열 안의 줄바꿈은 \\n으로 이스케이프됨. 따라서 버퍼의 마지막 줄바꿈 뒤에서 안전하게 자를 수 있음.
  • simdjson의 iterate_many 기능으로 버퍼에 담긴 여러 문서를 순회하고, 완전한 줄을 처리한 뒤 남은 바이트를 다음 청크와 이어 붙임.

압축 형식별 병렬 처리

  • 테스트 환경은 Intel Xeon Gold 6548N(Emerald Rapids) 서버로, 소켓 2개, 코어 64개, 스레드 128개를 갖추며 컴파일러는 GCC 14임.
  • gzip은 하나의 긴 압축 스트림이며, 다음 데이터를 해독할 때 이전 압축 해제 결과 중 32KiB가 필요함. 따라서 파일을 처음부터 한 스레드로 압축 해제해야 함.
  • 압축 해제 스레드 하나가 청크를 큐에 넣고 다른 스레드들이 파싱하는 방식으로 병렬화하면 gzip 처리량은 초당 2.5GB로 두 배가 됨.
  • zstd와 lz4는 서로 독립적인 프레임을 이어 붙여 파일을 구성할 수 있으며, 일반적인 .zst와 .lz4 파일 형식 및 명령줄 도구와도 호환됨.
  • 프로그램은 JSON 256KiB마다, 항상 줄바꿈 뒤에서 새 프레임을 생성함. 각 프레임에는 압축 해제 크기와 체크섬이 포함됨.
  • 프레임 경계는 일부 블록 헤더만 읽어 찾을 수 있어 전체 압축 해제가 필요하지 않으며, 각 스레드가 프레임을 가져와 압축 해제와 파싱을 모두 수행할 수 있음.

처리량과 파일 크기

  • 단일 스레드에서는 zstd와 lz4 모두 gzip과 비슷한 초당 약 1.1GB를 기록함.
  • 64개 스레드에서는 zstd가 초당 40GB, lz4가 초당 34GB를 기록하며, gzip에서 얻은 최고 속도보다 16배 빠름.
  • 벤치마크 파일 크기는 NDJSON 812.0MB, gzip 단일 스트림 56.9MB, zstd 256KiB 프레임 60.6MB, lz4 256KiB 프레임 108.5MB임.
  • 작은 프레임은 각 프레임이 처음부터 압축을 시작하므로 압축 효율이 다소 낮지만, zstd 파일은 gzip 파일보다 6% 더 큼.

결과 해석과 자료

  • 데이터는 합성 데이터이며 레코드가 매우 반복적이어서 압축 해제가 빠름. 실제 데이터에서는 압축 해제 속도가 더 느릴 수 있음.
  • JSON 파일을 작성하는 방식을 제어할 수 있다면 다중 프레임 zstd를 고려할 수 있으며, gzip과 비슷한 파일 크기로 여러 스레드에서 훨씬 빠르게 읽을 수 있음.
  • 소스 코드: https://github.com/simdjson/simdjson_compressed_demo
  • 벤치마크 수치와 그래프 작성 스크립트는 블로그 저장소에 있음.