Indy 서버 - IOCP Windows (2 / 3)

· 기능

sgcWebSockets 2022.9.0부터 Indy 서버 IOCP IOHandler가 처음부터 다시 작성되어 성능이 개선됐어요. IOCP IOHandler는 sgcWebSockets Enterprise 패키지에서만 사용할 수 있어요.

IOCP를 사용하면 서버가 더 많은 연결을 처리할수록 성능이 크게 저하되는 "1연결당 1스레드" 문제를 피할 수 있어요. IOCP는 여러 클라이언트를 처리하는 소수의 스레드를 제공해요. 처리할 것이 있을 때까지 스레드는 일시 중단되어 CPU 사이클을 사용하지 않아요.

설정 

Indy 서버에서 IOCP를 활성화하려면 IOHandlerOptions 속성으로 이동해 IOHandler 타입으로 iohIOCP를 선택하세요.

Server.IOHandlerOptions.IOHandlerType := iohIOCP;
Server.IOHandlerOptions.IOCP.IOCPThreads := 0; // the number of IOCP threads will be calculated automatically using the number of processors.
Server.IOHandlerOptions.IOCP.WorkOpThreads := 0; 

1. IOCPThreads는 IOCP 비동기 요청(오버랩 작업)에 사용되는 스레드예요. 기본적으로 값은 0이며, 이는 스레드 수가 프로세서 수를 사용해 계산된다는 것을 의미해요(cpucount 함수가 지원되지 않는 Delphi 7 및 2007은 스레드 수가 32로 설정됨).

2. WorkOpThreads는 연결이 항상 같은 스레드에서 처리되길 원할 때만 활성화해야 해요. IOCP를 사용하면 요청이 스레드 풀에 의해 처리되고, 같은 연결에 대한 각 요청이 다른 스레드에서 처리될 수 있어요. 모든 연결을 같은 스레드에서 처리하려면 WorkOpThreads에 이러한 요청을 처리하는 데 사용할 스레드 수를 설정하세요. 이는 서버 성능에 영향을 미치므로 이 기능이 필요한 경우에만 0보다 큰 값을 설정하는 것이 권장돼요.

Windows 서버에서 IOCP 활성화는 수천 개의 연결을 처리해야 할 때 권장돼요. 서버가 최대 100개의 동시 연결만 처리하는 경우 기본 Indy 스레드 모델을 유지할 수 있어요.

성능 테스트

간단한 테스트가 Indy 스레드 모델과 IOCP의 차이를 보여줄 거예요. WebSocket 프로토콜을 사용해 서버에 연결하고 CPU 사용률과 메모리 소비량이 다음 표에 표시돼요. CPU 사용률 %는 서버가 유휴 상태일 때예요.

연결 수 Indy 기본 IOHandler Indy IOCP IOHandler
100 0% (4.1MB) 0% (3.9MB)
5000% (17.1MB)0% (7.7MB)
10000% (32.2MB)0% (12.4MB)
15007.3% (46.8MB)0% (17.1MB)
200015.4% (61.6MB)0% (21.9MB)
250051.9% (76.5MB)0% (26.5MB)
300068.8% (91.7MB)0% (31.2MB)
350072.3% (106MB)0% (35.9MB)

Indy 서버는 3000개 이상의 동시 연결에서 속도 저하가 발생하기 시작했어요. 주로 스레드 컨텍스트 전환 때문으로, 서버가 유휴 상태일 때도 CPU 사용률이 매우 높았어요.

IOCP 서버는 유휴 상태에서 CPU를 사용하지 않았고 메모리 소비도 더 낮았어요.

다음 테스트는 3000개의 클라이언트를 연결하는 데 걸리는 시간을 측정해요. 각 클라이언트는 서버에 연결 시 메시지를 보내고 서버는 이 메시지를 에코해요.

Indy Default IOHandler Indy IOCP IOHandler
3000 클라이언트 연결 및 메시지 에코 15.32초 6.89초

성능 테스트는 16코어, RAM 32GB의 Windows Server 2022에서 수행됐어요.