Completion Port모델은 모든 소켓 입출력 모델 중 가장 뛰어난 성능을 제공한다.
보통 입출력 완료포트( I/O Completion Port ) 를 줄여서 IOCP라 칭한다.
입출력 완료포트는 비동기 입출력 결과와 이 결과를 처리할 스레드에 대한 정보를 담고 있는 구조로 APC큐와 비슷한 개념이다.
APC : 비동기 함수를 호출하는 매커니즘
APC와 IOCP의 차이점
1, 생성과 파괴
-> APC큐는 각 스레드마다 자동으로 생성되고 파괴된다.
-> IOCP는 CreateIoCompletionPort() 함수를 호출하여 생성하고 CloseHandle() 함수를 호출하여 파괴한다.
2. 접근 제약
->APC큐는 저장된 결과는 APC큐를 소유한 스레드만 확인할수 있지만 IOCP에는 이런 제약이 없다.
-> 보통 입출력 완료 포트를 접근하는 스레드를 별도로 두는데 이를 작업스레드라 한다.
3. 비동기 입출력 처리 방법
->APC큐는 저장된 결과를 처리하려면 해당 스레드는 alertable wait 상태에 진입해야 한다.
-> IOCP에 저장된 결과를 처리하려면 작업자 스레그는 GetQueuedCompletionStatus() 함수를 호출해야 한다.
IOCP 소켓 입출력 절자
- CreateIocompletionPort() 함수를 호출하여 입출력 완료 포트를 생성
-
CPU 개수에 비례하여 작업자 스레드를 생성
모든 작업자 스레드는 GetQueuedCompletionStatus() 함수를 호출하여 대기 상태가 된다.
-
비동기 입출력을 지원하는 소켓을 생성한다.
이 소켓에 대한 비동기 입출력 결과가 입출력 완료 포트에 저장되려면
CreateIoCompletionPort() 함수를 호출하여 소켓과 입출력 완료 포트를 연결해야 한다.
-
비동기 입출력 함수를 호출한다.
비동기 입출력 작업이 곧바로 완료되지 않으면 소켓 함수는 오류를 리턴하고 오류코드는 WSA_IO_PENDING으로 설정된다.
-
비동기 입출력 작업이 완료되면 운영체제는 입출력 완료 포트에 결과를 저장하고
대기 중인 스레드 하나를 깨운다.
대기 상태에서 깨어난 작업자 스레드는 비동기 입출력 결과를 처리한다.
- 새로운 소켓을 생성하면 3~5를.. 그렇지 않으면 4~5를 반복한다.
여기서 ...
IOCP에서는 IO를 전담하는 쓰레드를 별도로 생성하고 이 쓰레드가 모든 클라이언트를 대상으로 IO를 진행하게 됨.
입출력 함수인 WSASend, WSARecv 함수를 호출하는 쓰레드는 우리가 직접 생성해야 한다.
다만 이 쓰레드가 입출력의 완료를 위해 GetQueuedCompletionStatus함수를 호출할뿐이다.
그리고 GetQueue....함수는 어떤 스레드든 호출 가능하지만 실제 IO의 완료에 대한 응답을 받는 쓰레드의 수는
CreateIoCompletionPort호출시 지정한 최대 쓰레드의 수를 넘지않는다.
적정수는 CPU에 존재하는 코어의 수로 이해하는것이 좋다.
워커쓰레드의 갯수가 cpu*2인 이유. MS의 표준임..
즉 IOCP란
Input Ouput Completion Port즉 인풋 아웃풋 작업이 완료 되었을때 포트를 통해서 일을 처리하는것을 말한다.
그 일이 워커쓰레드 에서 한다.
동기식 : send나 recv함수가 완료되기 전에는 실행 코드가 움직이지 않는다
비동기식 : send나 recv는 우선 운영체제에게 소켓 작업을 한다고 알려죽 ㅗ후에 완료 통지를 받는 방식이다.
중첩소켓 : 여러개의 소켓 입출력 작업이 운영체제로 들어가면 몇개는 입출력 시간이 겹쳐도 작업이 가능하다는 매우 획기적인 기술
중첩되는 시간만큼 속도가 빨라진다는 장점을 가직 ㅗ있다.
비동기 I/O가 완료되면 정보단위가 만들어지고 이것이 IOCP큐에 들어간다. 이때 작업 스레드는 IOCP의 통지를 받고 IOCP큐에서 정보 단위 하나를 가져와
작업을 수행하게 된다.
IOCP는 하나의 스레드가 하나 이상의 사용자로부터의 요구를 처리 할 수 있도록 해준다. 꼭 한개의 스레드를 사용하는 건 아니다.
상황에 맞게 스레드의 개수를 조절 할 수 있다.
작업 스레드가 많으면 좋지만. 스레드가 많아지게 되면 context switching이 많이 일어 나므로 적은 수으 ㅣ스레드를 사용.
context switching은 윈도우 2000, nt 이상에서 지원해준다( 자동으로 해줌..)
IOCP의 가장 큰 장점은 쓰레드 풀을 통한 context switching 비용이 줄어든다.