# Linux 파이프 성능 저하

> Clean Markdown view of GeekNews topic #16483. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=16483](https://news.hada.io/topic?id=16483)
- GeekNews Markdown: [https://news.hada.io/topic/16483.md](https://news.hada.io/topic/16483.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-08-27T09:57:42+09:00
- Updated: 2024-08-27T09:57:42+09:00
- Original source: [qsantos.fr](https://qsantos.fr/2024/08/25/linux-pipes-are-slow/)
- Points: 1
- Comments: 1

## Topic Body

#### `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` 등이 있음

## Comments



### Comment 28336

- Author: neo
- Created: 2024-08-27T09:57:42+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=41348844) 
- `JMP`가 `RET`로 대체되지 않는 이유는 CONFIG_RETHUNK 옵션 때문임
  - objdump의 디스어셈블리에서 `RET`가 `JMP __x86_return_thunk`로 대체된 결과를 볼 수 있음
  - 관련 링크: [링크1](https://github.com/torvalds/linux/blob/v6.1/arch/x86/include/asm/linkage.h#L23), [링크2](https://github.com/torvalds/linux/blob/v6.1/arch/x86/lib/retpoline.S#L121)

- 함수의 시작과 끝에 있는 NOP 명령어는 ftrace가 추적 명령어를 삽입할 수 있게 함
  - ASM_CLAC와 ASM_STAC 매크로에서 나옴
  - X86_FEATURE_SMAP이 감지되면 런타임에 CLAC와 STAC 명령어로 채워짐
  - 관련 링크: [링크3](https://github.com/torvalds/linux/blob/v6.1/arch/x86/include/asm/smap.h#L17-L26), [링크4](https://github.com/torvalds/linux/blob/v6.1/arch/x86/include/asm/cpufeatures.h#L264), [링크5](https://github.com/torvalds/linux/blob/v6.1/arch/x86/kernel/alternative.c#L265)

- 한 사용자의 사이드 프로젝트는 파일 디스크립터를 위한 링버퍼를 제공하는 시스템 호출을 제안함
  - 파이프의 양쪽 끝이 링버퍼를 지원하면 동일한 링버퍼를 매핑하여 커널 호출 없이 제로 카피 IO를 가능하게 함
  - 협력자를 찾고 있음
  - 관련 링크: [링크6](https://lwn.net/Articles/976836/)

- Linux 파이프를 "느리다"고 부르는 것은 Toyota Corolla를 "느리다"고 부르는 것과 같음
  - 대부분의 경우 충분히 빠름
  - 극단적인 경우가 아니라면 더 빠른 것을 찾을 필요 없음

- 현대 CPU에서는 `rep movsb`가 가장 빠른 벡터화된 버전만큼 빠름
  - 커널 함수 이름 "copy_user_enhanced_fast_string"이 이를 암시함
  - CPU 기능인 ERMS와 FSRM이 이를 가능하게 함

- AVX512는 전력 소모가 많고 CPU 주파수 스케일링을 유발함
  - 관련 링크: [링크7](https://www.intel.com/content/dam/www/central-libraries/us/en/documents/cryptography-processing-with-3rd-gen-intel-xeon-scalable-processors-19-may-2021.pdf), [링크8](https://www.intel.com/content/www/us/en/developer/articles/technical/accelerating-x265-with-intel-advanced-vector-extensions-512-intel-avx-512.html)

- Hacker News의 "hug of death"를 다시 경험 중임
  - 캐싱된 WordPress 페이지 덕분에 상황이 나아졌지만 여전히 몇 초가 걸림

- io_uring을 사용한 버전을 보는 것이 흥미로울 것임
  - 커널과 사전 공유 버퍼를 사용하여 복사를 피하고 시스템 호출 오버헤드를 줄일 수 있음

- 블로그 로딩 시간이 약 20초 걸리는 것은 대담한 주장임

- 거의 모든 형태의 IPC는 "느림"
  - 안전을 위해 성능 비용을 지불하기로 결정한 것임

- 원래 splice가 왜 그렇게 느린지 이해하지 못했음
  - vmsplice보다 느린 이유를 지적했지만, 왜 그런지 명확하지 않음
  - vmsplice로 재구현할 수 없는 이유가 있을 것임
