인프런 커뮤니티 질문&답변

한종훈님의 프로필 이미지
한종훈

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

Listener

SocketAsyncEventArgs 의 EventHandler와 threadPool

작성

·

553

0

SocketAsyncEventArgs의 Completed eventHandler가 소켓의 AcceptAsync함수가 이후에 완료되면 (pending == true) threadPool에서 하나의 작업쓰레드를 가져와서 해당 이벤트를 처리하는것 같습니다. 

그래서 서버를 돌리다가 중단을 하면 작업쓰레드가 많이 생성되는것이 보입니다. 

그렇게 생성되는 작업쓰레드는 Session을 생성하고 거의 곧바로 완료가 되어서인지 중단을 해보면 쓰레드가 실행중인 코드를 찾을수가 없다고 나옵니다 (아마 해당 쓰레드는  제가 작성한 코드를 실행하고 있는것이 아니라 디버깅을 할 수 없는 부분의 더 낮은(?) 부분의 일을 하고 있거나 이미 자신의 일을 다 하고 다시 threadPool로 들어가고 있기 때문이라고 생각했습니다.) 

어찌되었든 소켓통신이 발생될때마다 쓰레드가 마구잡이로 동원되는것이 맘에 들지 않아서 socket 에 관한 async 함수의 완료 이벤트만 담당하여 수행하는 쓰레드를 만들어 따로 관리를 하려고 했습니다.

(궁극적인 목표는 서버나 클라이언트에서 코어 *2의 쓰레드를 미리 만들어놓고 해당쓰레드 이외의 다른 쓰레드는 생성하지 않는 것입니다.)

그러나 기존의 방법으로는 pending이 일어나고 나중에 이벤트가 호출이 될 때 호출되는 쓰레드를 미리 정하는 방법이 있는지 잘 모르겠습니다.

다른방법이 있는지 고민하고있는데 적절한 답이 떠오르지 않아 이렇게 질문드립니다.

감사합니다.

답변 2

6

한종훈님의 프로필 이미지
한종훈
질문자

혹시 저와같이 디버깅도 안되는 수많은 작업쓰레드의 정체에 대하여 궁금중을 가지고 계신분들에게 제 나름대로 찾은 답을 공유해봅니다. 

C#의 threadPool에는 2가지 thread가 있는데 하나는 일반적인 worker thread이고 또하나는 I/O작업이 완료되었을때의 작업을 담당하는 (I/O) completion port thread가 입니다. 소켓통신은 CPU가 아니라 I/O단에서 이루어지는 작업이기 때문에 SocketAsyncEventArgs의 Complete eventHandler는 completion port thread가 담당하여 invoke합니다 (Pending == true일때만 입니다). 

(해당 쓰레드가 디버깅이 안될때가 많은 이유는 complete이벤트를 다 끝내고 해당 쓰레드풀과 관련된 내부 로직을 실행하고있거나 waiting 상태이기 때문인것 같습니다.)

따라서 complete 이벤트에 무거운 작업을 연결해준다면 소켓통신이 완료될때마다 해당 I/O complete를 담당할 쓰레드가 부족하기 때문에 지속적으로 새로운 completion port thread가 생성되고 이는 리소스 낭비로 이어집니다. 제 실습 프로젝트의 경우에서는 completion port thread가  packet 역직렬화와 log를 찍는 작업을 포함하는 일련의 작업을 수행하고 그렇게 생성된 packet을 packet Handler담당 쓰레드에게 던져주고 있었기 때문에 client수가 많아질수록 스레드수가 급격하게 많아지는등 여러가지 문제가 발생했는데

위의 작업을 lambda로 묶어 통채로 packet handler에게 던져주기만을 하게 수정했더니 쓰레드 생성수가 눈에띄게 줄었고 어느정도 시간이 지나면 전체 쓰레드수도 어느정도 일정하게 유지됨을 확인했습니다.

공부하는데 가장 도움이 많이 된 자료는

Jeffrey Richter의 CLR via C#, 그리고

같은 저자의 C++ 관련 책입니다.

 

짧은 지식으로 찾은 정보이기 때문에 정확하지 않을수 있습니다. 잘못된 정보가 있다면 알려주세요.

감사합니다.

좋은 정보 감사합니다!

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

저도 해보지는 않았지만 ThreadPool의 SetMaxThreads 등의 함수를 이용해 
개수 조절이 가능하니 그런 방법으로 억제를 해보시면 될 것 같습니다.
다만 개인적인 생각으로 그 정도로 쓰레드 개수에 신경써서 
성능의 이점을 살릴 생각이라면, 애당초 C++ 서버로 가는게 훨 낫다고 봅니다.

한종훈님의 프로필 이미지
한종훈
질문자

네 감사합니다

 

한종훈님의 프로필 이미지
한종훈

작성한 질문수

질문하기