고성능 서버 블로그 포스팅
C# 게임 서버를 프로파일링하고 성능을 개선하는데 아래 블로그가 많이 도움이 되었다.
C# 고성능 서버 - 메모리 단편화 | leafbird/devnote
위 글의 내용에는 WeakReference가 메모리 pinning을 만든다는 부분이 있었는데,
메모리가 pinned 된다면 WeakReference가 가리키는 메모리를 강한 참조하는 것이 되므로
WeakReference가 의미가 없어지게 되는 게 아닌가 하는 의문이 들었다.
`System.WeakReference`도 pinning handle을 사용하고 있어, 단편화 유발의 원인이 된다.
WeakReference는 메모리를 pin하지 않는다
결론부터 말하자면 WeakReference가 메모리를 pin하지 않는다.
구글과 ChatGPT에서 찾아봤지만 WeakReference가 pinned handle과 연관이 있다는 내용을 찾지 못했다.
그래서 직접 블로그 글에서 언급한대로 덤프를 남겨 .NET handle을 확인해보았다.
WeakReference를 1만개 만든 뒤 덤프를 남겨 핸들을 확인해보니,
pinned 핸들이 아니라 Weak Short 핸들이 10000개 남은 것을 알 수 있었다.
참고로 Weak Short, Weak Long과 같은 타입은 C++로 작성된 .NET runtime에서 내부적으로 사용하는 타입이고
runtime/src/coreclr/gc/gcinterface.h at main · dotnet/runtime · GitHub
.NET 접근가능한 핸들 타입은 아래와 같이 4개이며, WeakReference는 생성 옵션에 따라 Weak또는 WeakTrackResurrection 타입을 사용한다
public enum GCHandleType
{
Weak,
WeakTrackResurrection,
Normal,
Pinned,
}
어쨌거나 WeakReference는 메모리를 pin하지 않으며, 따라서 메모리 파편화에 기여하지는 않는다.
물론 .NET runtime에서 handle 테이블을 관리하는 비용과 GC가 돌 때 핸들의 포인터를 수정하는 비용이 있기 때문에
너무 많은 핸들을 만드는 것은 좋지 않을 것이다.