일반적으로 클라가 서버에게 정적 파일을 요청할 때 서버에서는 다음과 같은 프로세스를 탄다.

  1. 디스크에서 정적 파일 요청 (App -> Kernel)
    컨텍스트 스위칭: 1회
    데이터 복사: 0회
  2. 원본 데이터를 복사함. (Kernel)
    원본 파일을 커널의 ReadBuffer에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 1회
  3. 복사한 파일 데이터 반환 (Kernel -> App)
    ReadBuffer에 있는 데이터를 Application의 ReadBuffer에 복사
    컨텍스트 스위칭: 2회
    데이터 복사: 2회
  4. 반환된 데이터를 소켓에 담게 끔 요청 (App -> Kernel)
    Application의 ReadBuffer에 있는 데이터를 커널의 SocketBuffer에 복사
    컨텍스트 스위칭: 3회
    데이터 복사: 3회
  5. 소켓에 데이터를 담아서 클라에게 응답 (Kernel)
    커널의 SocketBuffer에 있는 데이터를 커널의 NIC Buffer(Network Interface Card)에 복사
    컨텍스트 스위칭: 3회
    데이터 복사: 4회
  6. 다시 제어권을 Application으로 전환
    컨텍스트 스위칭: 4회
    데이터 복사: 4회

아래 두 권한은 일반적인 어플리케이션의 권한이 아닌 운영체제(커널 단)의 권한 같다.

  1. 디스크에서 파일을 읽어오는 권한
  2. 소켓에 데이터를 담아서 전송하는 권한

컨텍스트 스위칭 및 데이터 복사로 인해 오버헤드가 많다.
제로카피를 쓰면 아래와 같이 줄일 수 있다.

  1. 디스크에서 정적 파일 요청 (App -> Kernel)
    컨텍스트 스위칭: 1회
    데이터 복사: 0회
  2. 원본 데이터를 복사함. (Kernel)
    원본 파일을 커널의 ReadBuffer에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 1회
  3. 복사한 파일 데이터를 소켓에 담음. (Kernel)
    ReadBuffer에 있는 데이터를 SocketBuffer에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 2회
  4. 소켓에 데이터를 담아서 클라에게 응답 (Kernel)
    커널의 SocketBuffer에 있는 데이터를 커널의 NIC Buffer(Network Interface Card)에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 3회
  5. 다시 제어권을 Application으로 전환
    컨텍스트 스위칭: 2회
    데이터 복사: 3회

컨텍스트 스위칭을 1회 줄이고, 데이터 복사도 1회 줄였다.
물론 커널이 업데이트 되면서(리눅스 커널 2.4 이후 커널 파일 디스크립터가 수정되어 네트워크 카드가 gather operation을 지원하면 커널이 중복으로 데이터를 처리하는 것을 줄일 수 있다고 한다.) 아래와 같이 더 개선되었다고 한다.

  1. 디스크에서 정적 파일 요청 (App -> Kernel)
    컨텍스트 스위칭: 1회
    데이터 복사: 0회
  2. 원본 데이터 복사. (Kernel)
    원본 파일을 커널의 ReadBuffer에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 1회
  3. 소켓에 데이터를 담아서 클라에게 응답 (Kernel)
    커널의 ReadBuffer에 있는 데이터를 커널의 NIC Buffer(Network Interface Card)에 복사
    컨텍스트 스위칭: 1회
    데이터 복사: 2회
  4. 다시 제어권을 Application으로 전환
    컨텍스트 스위칭: 2회
    데이터 복사: 2회

뭐 완전 제로 카피는 아니지만… 언젠가는 제로 카피…처럼 동작하는 날이 오길 바라며 이름을 그렇게 지은 게 아닐까…

카프카에서 이런 제로 카피 기술을 사용해서 성능을 높였다고 한다!