포트폴리오

Select 모델 서버 프로젝트 10 - 동적할당 오브젝트 풀로 교체

묭묭.cpp 2024. 11. 1. 11:24

Select 모델 서버 프로젝트 10 - 동적할당 오브젝트 풀로 교체

new delete 할당 방식은 느릴수도?

일반적인 new delete 할당 방식은 느릴 것이라 예상

  • 커널 모드 진입이 빈번하지 않을까?
  • 이전 오브젝트 풀을 만들 시점에 테스트 결과도 오브젝트 풀이 더 성능이 좋았음

그럼 기대되는 효과

  • 성능 향상
    • 네트워크 루프 수 증가
  • 커널 CPU 사용률 하락
    • 내 코드가 유저에서 더 잘돌 수 있지 않을까?

FreeList 기반의 오브젝트 풀로 교체

오브젝트 풀 코드는 기존에 만들어둔 것을 사용

static 함수와 멤버 변수를 추가

  • CSession 클래스의 예시
  • #ifdef USE_OBJECT_POOL inline static CObjectPool<CSession> s_SessionPool = CObjectPool<CSession>(7500, false); #endif
  • 7000개를 접속시키는 더미 테스트를 진행할 것이므로 7500개의 객체를 생성
  • 뒤의 bool 타입 인자는 placement new 플래그
    • 객체 자체를 재사용할 것이므로 false

static 멤버 함수 Alloc과 Free를 추가

    inline static CSession *Alloc()
    {
        CSession *pSession = s_SessionPool.Alloc();
        // 나머지는 생성하는 측에서 세팅
        pSession->m_isVaild = TRUE;
        pSession->m_RecvBuffer.Clear();
        pSession->m_SendBuffer.Clear();
        return pSession;
    }

    inline static void Free(CSession *delSession)
    {
        s_SessionPool.Free(delSession);
    }

Alloc 함수

  • 오브젝트 풀에서 할당을 진행
  • 초기 정보를 세팅하고 반환
    • 필요한건 여기서 다 세팅하고 반환함
  • CSession::Alloc() 처럼 사용

Free 함수

  • 인자로 객체 포인터를 받아 Free

오브젝트 풀로 변경한 것들

  • CSession
    • 링 버퍼는 세션에서 관리되므로 오브젝트 풀로 관리하지 않음
  • CPlayer
  • CSerializableBuffer

그럼 성능이 나아졌는가?

네트워크 초당 루프수의 증가

  • 평균적으로 동적할당을 진행 시 60~80 루프
  • 오브젝트 풀로 변경하고 100~120 루프
  • 루프수가 증가함에 따라 Send TPS 또한 함께 증가
    • Recv, Accept TPS는 엄청 양이 많지는 않았기 때문에 증가하지 않았음
  • 변경함으로 네트워크 루프 수의 증가에 따른 확실한 성능 증가를 얻을 수 있었음

그럼 커널 CPU 사용률이 줄었는가?

  • 이건 큰 오산이었음.
  • 커널 CPU 사용률은 전혀 변화가 없었음

성능이 크게 나아지지 않은 이유

왜 그런가..?

  • new, delete, malloc, free 계열 함수의 동작
    • 사실은 커널 모드에 자주 진입하지 않음
    • 이미 이 녀석들도 내부적으로 메모리 풀링을 진행중임
  • 따라서 커널 CPU 사용률은 줄지 않음
  • 초반 할당에 따른 부하는 줄어들 수 있음

new, delete는 언제 커널 모드에 진입하는가?

  • 내부 함수 진행 순서
    • HeapAlloc -> VirtualAlloc
  • new에서 VirtualAlloc이 수행되는 상황
    • 이미 할당해둔 가상 메모리 페이지 영역이 부족할 때
  • delete에서도 마찬가지
    • 가상 메모리 페이지 영역이 더 이상 사용되지 않을 때 VirtualFree 발생 가능
  • 위 두 가지 상황에서만 이득을 볼 수 있음

위에서 언급한 오브젝트 풀 테스트 결과가 좋았다는 것

  • 이때 테스트 진행 방식이 큰 메모리(몇 KB)의 할당을 반복 진행함
  • 이에 따른 VirtualAlloc과 VirtualFree가 자주 진행되므로 성능이 배로 좋게 나온 것

현재의 내 네트워크 서버 프로세스에서는

  • 엄청나게 큰 변화는 없음
  • 비교적 작은 객체의 할당과 해제를 반복하므로
  • 직렬화 버퍼 크기의 할당 해제에서는 성능 향상이 있음
    • 네트워크 루프수의 향상이 여기서 비롯된 것
  • 커널 CPU 사용률의 감소를 기대한 것은 잘못생각한 것
반응형