• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

센드 리시브 버퍼를 살리고 싶어서 몇가지 물어봅니다.

23.05.24 13:34 작성 23.05.24 13:50 수정 조회수 300

0

강사님 께서는:

SendBufferHelper(버퍼)가 세션 외부에 있는 상황은 바람직 하지만

플레이어 세션중(PacketSession)하나가 send() 처리를 못하고 이런 일회용 버퍼를 계속 물고 있을 수 있다.

(ex 사용자가 엘리베이터를 타서 통신이 안되는 경우)

그럼 참조정리를 못하니 GC가 수거를 안해간다.

 

이 버퍼 릭킹 문제를 처리하기 위해 레퍼런스 카운트를 적용할수도 있다 라고 말씀하셨는데. C#에서 이를 구현하는데 난관이 있어서요(그점도 이미 말씀하셨었죠), 아래와 같습니다.

 

레퍼런스 카운트 사용 방식 (예상)

만약 100명의 사용자에게 브로드 캐스팅 할경우 이 버퍼에 대한 레퍼런스 카운트를 100으로 세팅한다.

각 세션에서(100개) 각각 send에 성공해서 버퍼에 대한 참조가 끝날 때마다 1씩 감소시킨다.

이 카운트 감소 처리를 할때 쓰레드 동기화에 신경써야 한다.

문제 1 ) 이런 동기화 처리도 성능에 영향을 준다. 레퍼런스 카운트 처리 때문에 샌드함수는 결국 지연되는 것.

문제 2) 매번 다 쓰인 버퍼의 레퍼런스 카운트가 0이 되었다 한들, 그것을 GC가 "항상" "확실히" 수거해가는지 테스트할 방법을 모른다.

문제 3) 레퍼런스 카운트가 0이 안되고 1이 유지되어서 어딘가에서 send가 막혀있는걸 확인 했을때 그 세션을 Disconnect()한다고 해도 GC가 이 버퍼를 "항상", "확실히"수거해 갈지 알 수 없다 (테스트 방법의 부재)

 

그래서 아래와 같은 질문을 드립니다.

!! 질문 0 !!) 강사님께서 메모리 릭에 대한 우려가 있다고 말씀하셨는데, 그게 순전히 우려인지, 혹시 테스트를 해보신건지 궁금합니다.

다시 말해서 C#에서 샌드 리시브 버퍼를 그냥 쓰기로 강행하면 나중에 낭패 볼까요?

 

질문 1 ) 위의 2,3번 문제를 체크할 수 있는 방법이 있을까요?

 

질문 2 ) 요즘 C#서버가 많이 보입니다. 모두 이런 문제를 고려했을텐데요, 그냥 매 순간 지금처럼 조각조각 패킷을 만들어 보내는게 대세인가요? 아니면 다른 방법이 있나요?

 

질문 3) 위의 1번 문제의 성능 감소가 클까요?

 

질문 4) 혹시 버퍼 크기를 4096 * 100 이 아니라 250, 300 등 작게 잡으면 이문제를 무시해도 될까요?

 

P.S 이 강의 시리즈가 매우 큰 도움이 되고 있습니다. 감사합니다.

답변 1

답변을 작성해보세요.

1

네 간단히 질문4처럼 버퍼를 작게 잡아 사용하면 됩니다.
지금은 큰 조각을 잘라서 쓰니 어려운 것이죠.
메모리 릭에 대한 단순한 '우려'가 아니라 정말로 특정 클라에 전송이 밀리면 당연히 회수가 안됩니다.
그리고 엄밀히 말해 C# 참조는 refCount 방식이 아니라서
억지로 refCount를 사용하는 것은 포기하는게 정신 건강에 좋습니다.
굳이 SessionBuffer 풀링을 한다면 최대 크기에 해당하는 버퍼를 여러개 준비해놓고
그걸 돌려 쓰는게 가장 나을 것 같네요. (Chunk는 포기하고)