CS

[CS]메모리 단편화

programmer-faust 2025. 8. 28. 01:34
  • 순서
    1. 메모리 단편화란?
    2. 메모리 단편화의 종류
    3. 메모리 단편화가 생기는 원인
    4. 메모리 단편화의 측정과 영향
    5. 메모리 단편화를 해결하기 위한 방법
    6. 정리
  • 메모리 단편화란?
    1. 메모리 할당.해제 과정에서 사용 가능한 메모리 블록이 조각나서 요구하는 메모리의 크기의 연속된 공간을 확보하기 어려운 현상.
  • 메모리 단편화의 종류
    1. 내부 단편화(Internal fragmentation)
      • 메모리 정렬이나 최소 블록 단위 때문에 실제 필요한 크기보다 더 많이 할당되는 현상
      • 예를 들어 3바이트가 필요해도 8바이트 단위로 맞춰서 할당되는 것
    2. 외부 단편화(External fragmentation)
      • 동적 메모리 할당과 해제가 반복되면서 힙 메모리가 잘게 조각나 큰 연속적인 공간을 할당하기 어려워지는 문제
      • 작은 객체를 반복적으로 생성/삭제하다가 큰 객체를 생성하려고 하면 실패하는 현
  • 메모리 단편화가 생기는 원인
    1. 다양한 크기의 할당/해제가 반복되어 자유 블록이 흩어짐.
    2. 할당 단위로 인한 내부 낭비
    3. 여러 스레드/아레나로 이한 분산된 프리 리스트
    4. 메타데이터(overhead)를 각 블록에 붙이는 방식
    5. 큰 객체와 작은 객체가 섞여 힙에 작은 구멍들이 많이 생김
  • 메모리 단편화의 측정과 영향
    1. 측정
      • C++
        1. 메모리 프로파일링 도구 사용
        2. 메모리 사용량 통계 출력
        3. malloc_info()같은 OS레벨 API로 heap 상태를 확인
      • 언리얼
        1. 자체 메모리 시스템인 FMemory, FMalloc, MemoryProfiler를 통해 단편화 모니터링을 지원함
        2. Stat Memory 콘솔 명령어 => 할당된 메모리, 누수, 힙 상태 표시
        3. MemReport => 특정 시점 메모리 사용량 리포트
        4. Memory Insights => 메모리 단편화 및 할당 패턴을 분석함
    2. 영향
      • C++에서 메모리 단편화의 영향
        1. 내부 단편화는 메모리가 낭비됨
        2. 외부 단편화로는 큰 배열/버퍼 할당 시 실패 가능성이 있음.
      • UE에서 메모리 단편화의 영향
        1. Actor/UObjeect 기반 메모리는 Unreal GC가 관리하여 단편화 직접 영향은 제한적임
        2. 버퍼/렌더링 리소스/네트워크 패킷 등의 Non-UObject 메모리에서는 외부 단편화 문제가 성능/안정성에 직격함
        3. 할당 실패로 인한 Crash 또는 Streaming hitch가 발생할 수 있음
  • 메모리 단편화를 해결하기 위한 방법
    1. C++
      • 메모리 풀/오브젝트 풀
        1. 미리 큰 메모리 블록을 할당해두고 필요할 때 나눠 쓰는 방식임
        2. C++17 이후 std::pmr::memory_resource와 같은 커스텀 allocator 사용 가능
        3. 게임 루프에서 자주 생성/삭제되는 객체에 유용함
      • 커스텀 Allocator
        1. STL컨테이너에 맞춤형 allocator를 제공해 단편화를 줄임
        2. 연속된 메모리 덩어리를 쓰도록 해서 캐시 효율도 높임
    2. 언리얼 엔진
      • GC
        1. UObject는 UE의 GC시스템이 관리함 => 엔진이 객체 메모리를 풀링/압축해서 외부 단편화를 줄여줌
        2. GC에 의존하면 타이밍 제어가 어렵기 때문에, 자주 생성되는 건 UObject보다 Non-UObject 구조체나 풀링 기법을 활용하는 게 나음.
      • FMemory/Fmalloc 커스텀 할당자
        1. UE는 자체 메모리 관리 레이어 FMemory::Malloc, FMemory::Free를 제공함 => 주로 UObject 이외 버퍼, 풀링, 고성능 메모리를 관리함
        2. 플랫폼별 최적화된 malloc/free를 사용하며, 필요하다면 커스텀 할당자인 FMalloc을 구현해 단편화 문제를 완화 가능함
      • 오브젝트 풀
        1. 탄환, 파편 UI 위젯 같은 반복적으로 생성/삭제되는 Actor는 풀링 시스템을 구현해 재사용하는 방법
      • 메모리 정렬
        1. UE는 SIMD 최적화를 위해 16바이트/32바이트 정렬을 많이 사용함
        2. alignas(16)또는 UE 매크로인 DECLARE_ALIGN으로 내부 단편화를 줄이고 캐시 효율도 올릴 수 있음.
  • 정리
    1. C++에서 외부 단편화는 ObjectPool, Cutom Allocator로 해결하고, 내부 단편화는 정렬과 블록 단위 관리로 완화
    2. 언리얼에서 GC와 자체 메모리 관리 시스템이 있지만, 실시간 성능을 위해서 Object Pool과 FMemory 활용을 통해 개선함.