GN⁺: Linux 파이프 성능 저하
(qsantos.fr)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의 속도를 달성할 수 있음 -
vmsplice
는write
시스템 호출의 비싼 부분을 우회함
마무리
- 파이프에 쓰는 것은 원시 메모리에 쓰는 것보다 10배 느림
- 이는 버퍼를 잠그는 비용과 SIMD 컨텍스트를 저장하고 복원하는 비용 때문임
-
splice
와vmsplice
는 이러한 비용을 피하고 데이터를 효율적으로 이동시킴
GN⁺의 정리
- 이 글은
vmsplice
를 사용하여 Linux 파이프의 성능을 극대화하는 방법을 설명함 -
vmsplice
는 데이터를 커널 공간으로 복사하지 않고 직접 이동시켜 성능을 크게 향상시킴 - Morse 코드 인코딩/디코딩과 같은 고속 데이터 처리 프로그램에 유용함
- 비슷한 기능을 가진 다른 프로젝트로는
splice
와sendfile
등이 있음
Hacker News 의견
-
JMP
가RET
로 대체되지 않는 이유는 CONFIG_RETHUNK 옵션 때문임 -
함수의 시작과 끝에 있는 NOP 명령어는 ftrace가 추적 명령어를 삽입할 수 있게 함
-
한 사용자의 사이드 프로젝트는 파일 디스크립터를 위한 링버퍼를 제공하는 시스템 호출을 제안함
- 파이프의 양쪽 끝이 링버퍼를 지원하면 동일한 링버퍼를 매핑하여 커널 호출 없이 제로 카피 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로 재구현할 수 없는 이유가 있을 것임