Reference Pool
관련 소스 파일 (Relevant source files)
•
GameFramework/Base/EventPool/BaseEventArgs.cs
•
GameFramework/Base/GameFrameworkEventArgs.cs
•
GameFramework/Base/ReferencePool/IReference.cs
•
GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs
•
GameFramework/Base/ReferencePool/ReferencePool.cs
•
GameFramework/Base/ReferencePool/ReferencePoolInfo.cs
•
GameFramework/Sound/ResetSoundAgentEventArgs.cs
목적과 개요 (Purpose and Overview)
Reference Pool은 객체를 매번 새로 만들고 파괴하는 대신 재사용해서 가비지 컬렉션(GC) 부하를 줄이는 메모리 관리 시스템입니다. 이벤트 인자 같은 빈번히 생성되는 임시 객체에서 특히 효과적이며, 과도한 GC로 인한 성능 저하를 막아줍니다.
Reference Pool은 GameFramework의 코어 컴포넌트 중 하나이며, Object Pool Manager(오브젝트 풀)와 함께 쓰일 수 있지만 초점이 다릅니다(Reference Pool은 작고 짧게 사는 객체 위주).
핵심 구성요소 (Core Components)
ReferencePool
재사용 가능한 객체 모음을 관리하는 정적 클래스.
•
타입을 키로 하는 ReferenceCollection 사전을 유지
•
객체 획득/반납 및 풀 관리 API 제공
•
올바른 사용을 강제하는 엄격 검사(Strict Check) 모드 제공
IReference
풀에 넣을 수 있는 모든 객체가 구현해야 하는 인터페이스.
•
반납 시 상태를 초기화하기 위한 Clear() 메서드 정의
ReferenceCollection
특정 타입의 참조를 관리하는 내부 클래스.
•
미사용 참조들의 큐 보관
•
획득/반납/추가/제거 등 사용 통계 기록
•
풀이 비면 새 인스턴스 생성 처리
ReferencePoolInfo
특정 참조 풀의 정보를 담는 구조체.
•
모니터링/디버깅에 유용한 사용 통계 제공
GameFrameworkEventArgs
이벤트 인자의 추상 기본 클래스이자 IReference 구현체.
•
이벤트 인자는 자주 만들어졌다가 버려지므로 풀링의 대표적인 대상
동작 방식 (How Reference Pooling Works)
획득(Acquisition)
클라이언트가 참조가 필요하면 ReferencePool.Acquire<T>() 호출:
•
풀이 비어 있지 않으면 하나 꺼내 반환
•
비어 있으면 새 인스턴스 생성
•
통계 카운터 업데이트
사용(Usage)
반환받은 객체를 필요한 동안 사용.
반납(Release)
사용을 끝내면 ReferencePool.Release(reference) 호출:
•
객체의 Clear()를 호출하여 상태 초기화
•
해당 타입의 컬렉션 큐에 재등록
•
통계 카운터 업데이트
엄격 검사(Strict Checking)
개발 중 오남용을 잡기 위한 검사를 활성화할 수 있음:
•
유효한 타입인지(추상 X, IReference 구현) 확인
•
중복 반납 같은 오류 검사
GameFramework와의 연동 (Integration)
이벤트 시스템
•
대부분의 이벤트 인자 클래스는 GameFrameworkEventArgs를 상속(IReference 구현)
•
자주 생성·소멸되는 이벤트 인자가 풀링의 최적 대상
•
예: ResetSoundAgentEventArgs.Create() 내부에서 ReferencePool.Acquire<ResetSoundAgentEventArgs>() 사용
프레임워크 컴포넌트
•
Entity/UI/Sound/Network 등 여러 매니저가 이벤트 시스템을 광범위하게 사용
•
이로 인해 Reference Pool의 GC 절감 효과를 간접적으로 크게 얻음
코어 인프라
•
Reference Pool은 GameFrameworkEntry와 나란히 위치한 코어 인프라로,
모든 모듈과 게임 코드에서 공용으로 사용할 수 있음
사용 패턴 (Usage Patterns)
풀링 가능한 클래스 만들기
IReference를 구현(보통 GameFrameworkEventArgs 상속)하고 Clear()로 초기화:
public class MyCustomEventArgs : GameFrameworkEventArgs
{
private int m_Value;
public int Value => m_Value;
public static MyCustomEventArgs Create(int value)
{
MyCustomEventArgs eventArgs = ReferencePool.Acquire<MyCustomEventArgs>();
eventArgs.m_Value = value;
return eventArgs;
}
public override void Clear()
{
m_Value = 0;
}
}
C#
복사
전형적인 흐름
// 1) 획득
MyCustomEventArgs args = ReferencePool.Acquire<MyCustomEventArgs>();
// 또는 팩토리 메서드
MyCustomEventArgs args2 = MyCustomEventArgs.Create(42);
// 2) 사용
// ... args 사용 ...
// 3) 반납
ReferencePool.Release(args);
C#
복사
풀 관리 API (예시)
•
Add<T>(count) : 지정 개수만큼 미리 생성해 풀에 추가
•
Remove<T>(count) : 지정 개수만큼 제거
•
RemoveAll<T>() : 해당 타입 전부 제거
•
ClearAll() : 모든 참조 풀 초기화
•
GetAllReferencePoolInfos() : 모든 풀의 통계 정보 조회
성능 관점 (Performance Considerations)
이점
•
GC 감소: 재사용으로 GC 빈도/정지 시간을 줄임
•
메모리 효율: 자주 쓰는 임시 객체를 메모리에 유지하여 반복 할당 회피
•
성능 향상: 이벤트가 많거나 임시 객체가 많은 시스템에서 특히 효과적
베스트 프랙티스
•
완전 초기화: Clear()에서 모든 필드를 꼼꼼히 초기화
•
반납 철저: 사용 후 반드시 Release() 호출
•
엄격 검사 활성화(개발 중):
ReferencePool.EnableStrictCheck = true;
C#
복사
•
적합한 대상만 풀링: 짧게 자주 생성되는 객체에 적합(오래 사는/거의 안 만드는 객체는 X)
•
통계 모니터링: GetAllReferencePoolInfos()로 과다/누락 확인
◦
미사용 수가 비정상적으로 크면 과도한 사전 생성 의심
◦
획득/반납 불균형은 메모리 누수 신호
결론 (Conclusion)
Reference Pool은 GameFramework의 핵심 메모리 관리 시스템으로, 객체 재사용을 통해 GC 오버헤드를 줄이고 게임처럼 메모리에 민감한 환경에서 안정적인 성능을 유지하게 도와줍니다.
특히 이벤트 인자처럼 짧은 생명주기를 가진 객체에 효과가 크며, 올바르게 사용하면 GC 정지 시간을 눈에 띄게 줄여 전체 반응성을 높일 수 있습니다.