1P by neo 3달전 | favorite | 댓글 1개

vmsplice너무 빠름

  • 일부 프로그램은 데이터를 파이프를 통해 더 빠르게 이동시키기 위해 vmsplice라는 시스템 호출을 사용함
  • vmsplice를 사용하지 않을 때 Linux 파이프가 예상보다 느리다는 것을 발견함
  • Morse 코드를 빠르게 인코딩/디코딩하는 프로그램을 작성 중이며, 이를 위해 파이프를 사용하고 있음

이상적인 환경에서 데이터 쓰기

  • 아래 프로그램은 시스템 호출 없이 데이터를 복사함
  • AVX-512를 사용하여 167 GB/s의 속도로 실행됨
  • AVX-512를 비활성화하고 AVX2 및 SSE2로 테스트했을 때도 동일한 속도(167 GB/s)를 기록함
  • 벡터화가 사용되는 한 167 GB/s의 속도를 달성할 수 있음

실제로 파이프에 데이터 쓰기

  • 파이프에 데이터를 쓰는 프로그램을 작성하고 측정한 결과, 17 GB/s의 속도를 기록함
  • 이는 버퍼에 쓰는 것보다 10배 느림
  • 프로파일링 결과, 대부분의 시간이 write 호출에 소비됨
  • pipe_write 함수에서 메모리 페이지를 할당하는 데 많은 시간이 소요됨
  • 데이터 복사 자체는 CPU 시간의 20%만 차지하지만, 여전히 __memset_avx512_unaligned_erms보다 두 배 느림

vmsplice의 도움

  • vmsplice는 사용자 공간에서 커널로 버퍼를 복사하지 않고 이동시킴
  • vmsplice를 사용하면 210 GB/s의 속도를 달성할 수 있음
  • vmsplicewrite 시스템 호출의 비싼 부분을 우회함

마무리

  • 파이프에 쓰는 것은 원시 메모리에 쓰는 것보다 10배 느림
  • 이는 버퍼를 잠그는 비용과 SIMD 컨텍스트를 저장하고 복원하는 비용 때문임
  • splicevmsplice는 이러한 비용을 피하고 데이터를 효율적으로 이동시킴

GN⁺의 정리

  • 이 글은 vmsplice를 사용하여 Linux 파이프의 성능을 극대화하는 방법을 설명함
  • vmsplice는 데이터를 커널 공간으로 복사하지 않고 직접 이동시켜 성능을 크게 향상시킴
  • Morse 코드 인코딩/디코딩과 같은 고속 데이터 처리 프로그램에 유용함
  • 비슷한 기능을 가진 다른 프로젝트로는 splicesendfile 등이 있음
Hacker News 의견
  • JMPRET로 대체되지 않는 이유는 CONFIG_RETHUNK 옵션 때문임

    • objdump의 디스어셈블리에서 RETJMP __x86_return_thunk로 대체된 결과를 볼 수 있음
    • 관련 링크: 링크1, 링크2
  • 함수의 시작과 끝에 있는 NOP 명령어는 ftrace가 추적 명령어를 삽입할 수 있게 함

    • ASM_CLAC와 ASM_STAC 매크로에서 나옴
    • X86_FEATURE_SMAP이 감지되면 런타임에 CLAC와 STAC 명령어로 채워짐
    • 관련 링크: 링크3, 링크4, 링크5
  • 한 사용자의 사이드 프로젝트는 파일 디스크립터를 위한 링버퍼를 제공하는 시스템 호출을 제안함

    • 파이프의 양쪽 끝이 링버퍼를 지원하면 동일한 링버퍼를 매핑하여 커널 호출 없이 제로 카피 IO를 가능하게 함
    • 협력자를 찾고 있음
    • 관련 링크: 링크6
  • Linux 파이프를 "느리다"고 부르는 것은 Toyota Corolla를 "느리다"고 부르는 것과 같음

    • 대부분의 경우 충분히 빠름
    • 극단적인 경우가 아니라면 더 빠른 것을 찾을 필요 없음
  • 현대 CPU에서는 rep movsb가 가장 빠른 벡터화된 버전만큼 빠름

    • 커널 함수 이름 "copy_user_enhanced_fast_string"이 이를 암시함
    • CPU 기능인 ERMS와 FSRM이 이를 가능하게 함
  • AVX512는 전력 소모가 많고 CPU 주파수 스케일링을 유발함

  • Hacker News의 "hug of death"를 다시 경험 중임

    • 캐싱된 WordPress 페이지 덕분에 상황이 나아졌지만 여전히 몇 초가 걸림
  • io_uring을 사용한 버전을 보는 것이 흥미로울 것임

    • 커널과 사전 공유 버퍼를 사용하여 복사를 피하고 시스템 호출 오버헤드를 줄일 수 있음
  • 블로그 로딩 시간이 약 20초 걸리는 것은 대담한 주장임

  • 거의 모든 형태의 IPC는 "느림"

    • 안전을 위해 성능 비용을 지불하기로 결정한 것임
  • 원래 splice가 왜 그렇게 느린지 이해하지 못했음

    • vmsplice보다 느린 이유를 지적했지만, 왜 그런지 명확하지 않음
    • vmsplice로 재구현할 수 없는 이유가 있을 것임