이론

메모리 단편화

TIN9 2023. 4. 18.
반응형

메모리 단편화

메모리 단편화란

C++및 기타 프로그래밍 언어에서 발생할 수 있는 문제입니다.

프로그램에서 사용하는 메모리가 작은 블록으로 분할되어 새로운 개체나 데이터 구조에 할당할 대규모 연속 메모리 영역을 찾기 어려울때 발생하는 문제입니다.

(쉽게 말해 new와 delete를 많이 발생하면 생기는 문제)

 

이 문제로 인해 사용 가능한 총 메모리가 충분하더라도 프로그램이 새 개체 또는 데이터 구조에 충분한 메모리를 할당할 수 없는 상황이 발생할 수 있습니다. 이는 사용 가능한 메모리가 작은 조각으로 조각나고 요청을 충족할 만큼 충분히 큰 단일 메모리 블록이 없기 때문입니다.

 

메모리 단편화 해결방법

 

메모리 풀링

메모리 단편화에 대한 한 가지 해결방법은 메모리 풀링이라는 메모리 관리 기술을 사용하는 것입니다.

 

메모리 풀링은 프로그램 실행 시작 시 고정된 양의 메모리를 미리 할당하고 이를 고정된 크기의 청크로 나누는 것입니다

개체 또는 데이터 구조를 할당해야 하는 경우 풀에서 미리 할당된 청크를 할당할 수 있습니다. 개체 또는 데이터 구조가 더 이상 필요하지 않으면 재사용을 위해 청크를 풀로 반환할 수 있습니다.

 

메모리 풀링은 메모리가 효율적으로 관리되고 재사용될 수 있는 고정 크기 청크에 할당되도록 하기 때문에 메모리 단편화를 줄이는 데 도움이 될 수 있습니다.

그리고 더 효율적인 메모리 사용과 더 적은 단편화로 이어질 수 있습니다.

또한 메모리 풀링은 기본 메모리 할당 함수에 대한 호출 수를 줄여 성능을 향상시킬 수도 있습니다.

 

메모리 풀링 장점

  1. 메모리 단편화 감소 : 메모리 풀링은 고정 크기의 메모리 블록을 할당 및 할당 해제하여 메모리 조각화를 줄입니다. 이렇게 하면 시간이 지남에 따라 누적되어 성능 문제를 일으킬 수 있는 작고 사용할 수 없는 메모리 조각의 가능성이 줄어듭니다.
  2. 성능 향상 : 메모리 할당 및 할당 해제는 비용이 많이 드는 작업이며 메모리 풀링을 사용하면 이러한 작업을 수행해야 하는 횟수를 줄일 수 있습니다. 미리 할당된 메모리 블록을 재사용함으로써 메모리 풀링은 메모리 집약적인 애플리케이션의 성능을 향상시킬 수 있습니다.
  3. 예측 가능한 메모리 사용량 : 메모리 풀링을 사용하면 애플리케이션에서 사용하는 메모리 양을 더 예측 가능합니다. 메모리가 고정 크기 블록에 할당되기 때문에 응용 프로그램은 메모리 요구 사항을 보다 정확하게 예측하고 예기치 않은 메모리 급증을 방지할 수 있습니다.
  4. 맞춤형 메모리 관리 : 메모리 풀링을 통해 애플리케이션의 특정 요구 사항에 맞출 수 있는 맞춤형 메모리 관리 전략이 가능합니다. 예를 들어, 다양한 유형의 데이터 구조 또는 객체에 대한 메모리 사용을 최적화하기 위해 다양한 블록 크기로 메모리 풀을 생성할 수 있습니다.

메모리 풀링 예제

#include <iostream>
#include <vector>

class MemoryPool 
{
public:
    MemoryPool(size_t blockSize, size_t numBlocks) :
        m_blockSize(blockSize),
        m_numBlocks(numBlocks)
    {
        m_data = new char[blockSize * numBlocks];
        for (size_t i = 0; i < numBlocks; ++i) 
        {
            m_freeList.push_back(m_data + i * blockSize);
        }
    }

    ~MemoryPool() 
    {
        delete[] m_data;
    }

    void* allocate(size_t size)
    {
        if (size > m_blockSize) 
        {
            return nullptr; // 할당량이 너무 큽니다.
        }
        if (m_freeList.empty()) 
        {
            return nullptr; // 메모리 부족입니다.
        }
        void* ptr = m_freeList.back();
        m_freeList.pop_back();
        return ptr;
    }

    void deallocate(void* ptr)
    {
        m_freeList.push_back(ptr);
    }

private:
    char* m_data;
    size_t m_blockSize;
    size_t m_numBlocks;
    std::vector<void*> m_freeList;
};

int main()
{
    const size_t blockSize = 64;
    const size_t numBlocks = 100;
    MemoryPool pool(blockSize, numBlocks);

    // 메모리 풀에서 메모리 할당
    void* ptr1 = pool.allocate(32);
    void* ptr2 = pool.allocate(64);
    void* ptr3 = pool.allocate(128); // nullptr 반환
    if (ptr1 && ptr2)
    {
        std::cout << "메모리 풀에서 메모리 할당\n";
    }

    // 메모리 풀로 메모리 반환
    pool.deallocate(ptr1);
    pool.deallocate(ptr2);

    // 메모리 풀에서 더 많은 메모리 할당
    void* ptr4 = pool.allocate(32);
    void* ptr5 = pool.allocate(64);
    if (ptr4 && ptr5) 
    {
        std::cout << "메모리 풀에서 재사용된 메모리\n";
    }

    return 0;
}
반응형

'이론' 카테고리의 다른 글

STL 컨테이너  (0) 2023.04.21
얕은 복사와 깊은 복사의 차이  (1) 2023.04.18
오버로딩과 오버라이딩의 차이  (0) 2023.04.18
램버트 조명 공식  (0) 2022.08.09
렌더링 파이프라인 구조  (0) 2022.08.09

댓글