뒤로
한경민
한경민 ·

BrilliantServer 문제 해결 사례 - writev 사용하여 불필요한 복사 방지 및 시스템콜 호출 감소

0 문제 정의

  • HTTP 응답을 준비할 때, 파싱을 편리하게 하고, 불필요한 메모리 재할당 및 복사를 최소화하기 위해 header 버퍼와 body 버퍼를 별도로 저장하기로 결정.
  • send 시스템콜로 응답을 보내려면, header 와 body 를 모두 담을 수 있는 버퍼를 할당해서 복사하는 과정을 거치거나 send 를 두번 호출해야 한다.
  • 시스템콜 호출과 할당 및 복사 모두 서버의 성능을 저하시킬 수 있는 요인으로 판단.

1 해결책

  • writev 시스템콜 사용하여 한번의 시스템콜로 각기 다른 두 버퍼에 있는 header 와 body 순서대로 클라이언트에게 전송.
#include <sys/uio.h>
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
struct iovec {
   char   *iov_base;  /* Base address. */
   size_t iov_len;    /* Length. */
};
  • 함수 두번째 인자 struct iovec *iov 에 각 버퍼의 주소값과 길이가 순서대로 담긴 iovec 구조체 배열의 주소값을 넣어주고 호출하면, 한번의 시스템콜로 여러개의 버퍼에 담겨 있는 데이터 전송 가능.

2 검증

  • send 결과

  • writev 결과

  • 동일한 양의 데이터 전송 시 writev 를 사용했을 때, 더 나은 성능, 더 적은 시스템콜 호출 횟수 확인.

💡위 비교는 각기 다른 버전의 프로그램으로 테스트한 것이기 때문에 정확한 비교라고 할 수는 없다. 하지만 writev 버전이 상위 버전이고, 총 시스템콜 횟수 증가에서도 볼 수 있듯 timeout 처리 등 추가적인 기능들이 더해졌는데도 더 나은 성능을 보였기 때문에 유의미한 결과라고 볼 수 있다.

3

댓글

로그인 후 댓글을 남길 수 있습니다.

아직 댓글이 없습니다.