서버 프로그래밍

Overlapped I/O Note #1

하늘흐늘 2009. 5. 17. 01:02
반응형


accept
   1) backlog를 충분히 잡는다.
   2) Win32
      - AcceptEx 
       a. What
          a) accept(..)가 Pending되며 1byte이상이 수신되었을 때 완료된다.
          b) 성능상의 이유로 AcceptEx에 할당된 커널모드 구조체는
             소켓이 연결되었거나 listening socket이 닫히고 난후에 제거할 수 있다.
       b. How To Use
          a) 미리 생성된 socket을 accpet(..)에 걸어놓는다.
          b) 최대치의 개수를 정해놓고 일정수의 AcceptEx를 항상 걸어놓는다.
          c) 연결만을 걸어놓는 악의적인 접속이나 유효하지 않은 접속을 대비하기
             위하여 getsockopt(SO_CONNECT_TIME)을 이용하여 주기적으로 소켓을
             검사한다.
          d) AcceptEx호출이 값비싼 호출이기 떄문에 성능 향상을 위하여
             IOCP Work Thread와는 별도의 Thread로 처리한다.

소켓 버퍼
   0) size
      디폴트 사이즈는 8KB
   1) 소켓옵션
      a) SO_SNDBUF, SO_RCVBUF
   2) 버퍼복사 구조
      a) TCP <-> Socket Buffer <-> User Buffer
      b) 소켓옵션은 Socket Buffer의 크기를 설정하는 것이다.
      c) Socket Buffer의 크기가 0일 경우
         - send, recv는 TCP Buffer <-> User Buffer의 직접적인 데이터 교환을
           보장받게 되나 TCP Buffer에서 부터 User Buffer로의 Copy 속도가
           충분히 빠르지 않을 경우 recv시 TCP의 허용가능한 Window size를 줄이며,
           send시 TCP로 지속적으로 데이터를 주는데 제약을 가하여 
           TCP 통신 처리량을 줄이는 병목의 원인이 될 것이다.
      d) 일반적인 경우
         - Socket Buffer의 크기를 허용치만큼 키우는 것이 좋다.
   3) overlapped I/O의 동작특징
      a) recv
         - Socket Recv Buffer size == 0
           .TCP <-> Pending IO's User Buffer
           .overlapped I/O는 locked되어 데이터가 오기를 기다리다가
            TCP Window에서 부터 데이터를 직접 복사하여 리턴한다.
         - 0 < Socket Recv Buffer size <= full
           .TCP <-> Socket Buffer <-> overlapped I/O's User Buffer 
           .overlapped I/O는 Socket Buffer에서 부터 데이터를 복사하여 리턴한다.
         - Socket Recv Buffer size == full
           TCP와 Socket Buffer에 여유 공간이 없을 경우
           TCP는 Window Size 0을 연결된 호스트에 보내게 되며
           TCP통신은 User Buffer로 데이터가 이동되어 여유공간이 생긴 후
           연결된 호스트에 여유분의 Window Size를 advertise한 후
           상대편에서 새로운 데이터를 보내기 전까지 정지하게 된다. 
      c) send
         - Socket Send Buffer size == 0
           .TCP <-> overlapped I/O's User Buffer
           .overlapped I/O는 TCP에 직접 복사된 후 리턴된다.         
         - 0 < Socket Send Buffer size < full
           .TCP <-> Socket Buffer <-> overlapped I/O's User Buffer
           .overlapped I/O는 Socket Send Buffer에 데이터를 복사한 후 리턴한다.
         - Send Socket Buffer == full
           .TCP <-> overlapped I/O's User Buffer
           overlapped I/O's User Buffer는 locked되어 Socket Buffer가 비워질
           떄까지 locked되어 기다린다.(WSA_IO_PENDDING) Socket Buffer가 비워진 후
           TCP는 overlapped I/O's User Buffer의 내용을 직접 받아 보낸다.
           (TCP <-> overlapped I/O) 그리고 overlapped I/O는 리턴된다.
    d) 소켓 버퍼 사이즈 0
        - recv
          TCP 통신 속도가 overlapped I/O pending속도 보다 느릴 경우는 상관 없지만
          overlapped I/O pending속도 보다 빠를 경우에는 아래와 같은 문제가 발생한다.
          (이는 주로 상위에서의 연산 속도와 pending 전략과 관계있다.)
          .TCP Buffer가 Full인 경우 상위에서 Recv로 Buffer의 내용을 받아가기 전까지
           TCP Communication은 멈추게 된다.
          .TCP Buffer가 사용하는 non-paged pool 또한 recv로 buffer의 내용을 받아가기
           전까지 리소스가 제한된다.
        - send
          TCP Window가 다 찼을 경우 send(..)를 호출한 application은 기다려야 한다.
          사용자 프로그램에서 TCP로 복사하는 속도는 TCP간 전송속도 보다 빠르다.
          (메모리간 복사 속도와 네트워크 전송 속도간의 차이를 생각해 보라.)  
     e) 소켓 버퍼 사이즈 0을 이용한 overlapped I/O 적정 Pending 체크
        - 역자분의 아이디어로 데이터를 주기적으로 Send하면서 소스 호스트의 Send간격과
          목적 호스트의 Recv간격의 규칙성을 측정한다.
          통제변수는 원활한 폐쇄적 LAN환경,
          독립변수는 Send속도, 종속변수는 Recv속도의 규칙성이 된다.
          소켓 버퍼 0이라는 상황은  소켓 버퍼가 꽉 찼을 상황과 비슷하기 떄문에
          소켓 버퍼가 Full인 상황을 가정한 테스트인 듯 하다.   
           
TCP 버퍼
   1) 크기
      a. 17KB까지 증가될 수 있지만 평균적으로 이보다 작은 크기를 가지고 있다.
      b. TCP 수신 버퍼는 non-paged pool로 할당되어 있다.
         -non-paged pool은 서버가 연결별로 수신 함수를
          호출할 때까지 리소스를 제한하게 된다.
          따라서 소켓의 수신 버퍼는 손대지 않는 것이 좋다.
          (non-paged pool의 TCP수신버퍼의 내용이 소켓 버퍼에 복사되지 못하여
           낭비되는 상황을 만들지 마라)

overlapped I/O Resource Management
   1) locked pages(잠겨진 메모리 페이지)
      a. WSAENOBUF
         OS가 허용하는 잠겨질 수(locked) 있는 메모리의 한계를 넘었을 떄 일어난다.
         -해결법
          >> buffer size 0의 overlapped I/O를 이용한다. (locked되는 페이지가 없다.)
          a) size 0의 overlapped I/O 작업이 완료되면 넌블록킹 수신으로
             소켓이 WSAEWOULDBLOCK에러를(더 이상 읽을 데이터가 없음을 의미)
             낼 떄까지 데이터를 가져온다.
          b) size 0의 overlapped I/O 작업이 완료되고 클라이언트가 대량의
             데이터를 보낸다는 것을 알게 되었을 떄 여유가 있을 경우
             여러개의 overlapped I/O 수신함수를 호출하는 방법을 쓸 수도 있다.
         -해결법을 쓸 떄의 상황
          연결별 데이터 처리 능력을 희생시켜 서버의 연결 용량을 증가시키는 방법이다.
   2) non-paged pool(페이징되지 않는 메모리 풀)
      a. swap되지 않는 메모리
      b. 사용
         a) 소켓: 상태 정보, 로컬주소 정보,  리모트주소 정보
         b) connected 소켓: 2kb
            accept나 AcceptEx에 의해 리턴된 소켓: 1.5kb
            overlapped I/O별로 IRP(I/O request packet)을 발생시키면서 500bytes 
      c. 한계
         a) Win2K: 물리적 메모리의 1/4
         b) WinNT: 128MB
      d. 부족시 현상
         a) 운이 좋은 경우: WSAENOBUF 에러
         b) 운이 좋지 않은 경우: System Crash
      e. 기타
         a) thirty-party 드라이의 잘못된 메모리 할당 에러
         b) 사용 가능한 non-paged pool을 알아보는 방법은 없다.
       f. 해결책
         a) 서버의 연결 용량과 overlapped I/O작업의 용량을 테스트해봐야 한다.                     
         b) WSAENOBUF
            non-paged pool을 막았다면 locked page의 초과로 인해 발생됐다고 가정해야 한다.
            
API 특징
   1) overlapped I/O
      a. 호환성: All Windows except WinCE
      b. 주의점
         요청한 순서대로 작업이 완료되는 것을 보장 받지만
         요청한 순서대로 작업 완료통지를 받지는 않는다.
   2) Completion Port(IOCP)
      a. 호환성: over WinNT
      b. 원래 Windows I/O를 위하여 만들어진 것임
      c. 주의점
         요청한 순서대로 작업이 완료되는 것을 보장 받지만
         요청한 순서대로 작업 완료통지를 받지는 않는다.
      d. Tip
         a) Thread가 블록될 가능성이 있을 경우, 최대 동시수행 쓰레드 개수보다
            많은 수의 쓰레드를 생성시키는 것이 좋다.
            -> Thread가 블록 중일 경우 IOCP는 다른 쓰레드를 깨우며 일시적으로
                동시 쓰레드의 개수는 생성시 입력한 값보다 커질 것이나
                곧 다시 생성시 입력한 값으로 떨어질 것이다.
      e. Programming Tip
         a) OVERLLAPPED 구조체
            a. Buffer, OperationType등을 알아내기 위하여 사용한다.
               I/O작업별 데이터라고 불림
            b. struct의 첫멤버로 OVERLLAPPED를 갖고 구조체 캐스팅을 한다.  
            c. 클래스나 struct의 멤버 변수로 사용한다. [저자]
            d. struct로 상속받아 사용한다. [역자]
            e. 결과적으로 OVERLAPPED 구조체의 포인터의 주소를 입력하면 OVERLAPPED
               구조체를 상속했거나 첫번쨰 인자로 포함하는 구조체의 포인터도 캐스트하여
               입력할 수 있다.
         b) CompletionKey
            a. 소켓에 대한 Key
            b. 소켓 핸들을 넣을 것을 권장   
         c) Winsock에 해당하는 에러 얻기
            a. WSAGetOverlappedResult(..)-> WSAGetLastError(..)
               바로 WSAGetLastError(..)를 호출하면 윈도우즈 에러와 같은 형태의
               에러코드가 검출된다.
         d) 종료방법
            a. 직접 처리
               closesocket(..) 호출     
            b. 사용자 처리
               PostQueuedCompletionStatus(..) 호출-> 해당 쓰레드 종료
               1) CompletionKet 값을 0으로 설정 받을 떄 0이 나오면 특별 처리
                  그 후 마지막으로 completion port는 CloseHandle을 이용하여 종료

반응형