커스텀 힙 할당 자


9

함수형 프로그래밍 언어가 기존 객체를 수정하는 것보다 새로운 객체를 할당하는 것을 선호하고 가비지 수집기가 물건을 비우는 것에 대해 걱정하게 만드는 정도까지도 대부분의 프로그램은 힙 할당에 대해 매우 부담이 될 수 있습니다.

그러나 임베디드 프로그래밍, 사일런트 섹터에는 메모리 및 하드 실시간 제약으로 인해 힙 할당을 전혀 사용할 수없는 많은 애플리케이션이 있습니다. 처리 될 각 유형의 객체 수는 사양의 일부이며 모든 것이 정적으로 할당됩니다.

게임 프로그래밍 (적어도 하드웨어 푸시에 대한 야심 찬 게임에서)은 때때로 다음과 같은 사이에 속합니다. 동적 할당을 사용할 수 있지만 할당자를 블랙 박스로 취급 할 수없는 충분한 메모리와 부드러운 실시간 제약 조건이 있습니다. 가비지 수집을 사용하지 말고 사용자 지정 할당자를 사용해야합니다. 이것이 C ++이 여전히 게임 산업에서 널리 사용되는 이유 중 하나입니다. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html 과 같은 작업을 수행 할 수 있습니다 .

그 중간 영역에있는 다른 도메인은 무엇입니까? 게임과는 별도로 커스텀 할당자는 어디에 사용됩니까?


1
일부 OS 는 객체 캐싱을 제공 하는 슬랩 할당자를 사용 하지만 객체의 멤버를 모듈로 2 ** N 인덱스 캐시에 대해 서로 다른 세트로 매핑하여 프로세서 캐시 충돌 누락을 줄이는 데 사용할 수 있습니다 (둘 다 연속 메모리에 여러 인스턴스를 두어 슬래브 내의 가변 패딩에 의해). 경우에 따라 할당 / 사용 속도 또는 메모리 사용보다 캐시 동작이 더 중요 할 수 있습니다.
Paul A. Clayton

답변:


4

성능 집약적 중요 경로가있는 응용 프로그램이있을 때마다 메모리 처리 방법에 대해 염려해야합니다. 대부분의 최종 사용자 클라이언트 측 응용 프로그램은 기본 이벤트 중심이며 대부분의 이벤트는 사용자와의 상호 작용에서 비롯되며 성능 제약이 많지 않기 때문에이 범주에 속하지 않습니다.

그러나 많은 백엔드 소프트웨어는 메모리 처리 방법에 중점을 두어야합니다. 많은 소프트웨어가 더 많은 수의 클라이언트, 더 많은 수의 트랜잭션, 더 많은 데이터 소스를 처리하도록 확장 할 수 있기 때문입니다. 한계를 뛰어 넘어 상상할 수있는 사용 사례를 처리하기 위해 작성된 완전히 일반적인 메모리 할당 자에 의존하기보다는 소프트웨어 사용자 메모리를 분석하고 소프트웨어에 맞는 사용자 지정 할당 체계를 작성하는 방법을 분석 할 수 있습니다.

몇 가지 예를 들자면 ... 첫 번째 회사에서 프로세스 제어 데이터의 수집 / 저장 / 보관을 담당하는 소프트웨어 인 Historian 패키지 (공장, 원자력 발전소 또는 수백만 개의 센서를 갖춘 정유소, 해당 데이터를 저장합니다). 우리는 역사가가 더 많은 데이터를 처리하지 못하게하는 성능 병목 현상을 분석 할 때마다 대부분 메모리 처리 방식에 문제가있었습니다. 우리는 malloc / free가 절대적으로 필요한 경우가 아니라면 호출되지 않도록 많은 노력을 기울였습니다.

현재는 감시 비디오 디지털 레코더 및 분석 패키지를 사용하고 있습니다. 30fps에서 각 채널은 33 밀리 초마다 비디오 프레임을 수신합니다. 판매하는 하드웨어에서 100 채널의 비디오를 쉽게 녹화 할 수 있습니다. 따라서 중요한 경로 (네트워크 호출 => 캡처 구성 요소 => 레코더 관리 소프트웨어 => 저장소 구성 요소 => 디스크)에 동적 메모리 할당이 없는지 확인하는 또 다른 경우입니다. 고정 크기의 버퍼 버킷을 포함하고 LIFO를 사용하여 이전에 할당 된 버퍼를 재사용하는 사용자 지정 프레임 할당자가 있습니다. 600Kb의 저장 공간이 필요한 경우 공간을 낭비하는 1024Kb 버퍼가 생길 수 있지만 각 할당이 매우 수명이 짧은 용도에 맞게 조정되었으므로 버퍼가 사용되기 때문에 잘 작동합니다.

필자가 설명한 응용 프로그램 유형에서 (A에서 B로 많은 데이터를 이동하고 많은 수의 클라이언트 요청을 처리하는) 힙으로 돌아가는 것은 CPU 성능 병목 현상의 주요 원인입니다. 힙 조각화를 최소한으로 유지하는 것이 보조 이점이지만, 대부분의 최신 OS가 이미 조각화가 적은 힙을 구현하고 있다고 말할 수 있는 한 (최소한 Windows는 알고 있지만 다른 사람들도 그렇게하기를 바랍니다). 개인적으로 이러한 유형의 환경에서 12 년 이상 일하면서 힙과 관련된 CPU 사용 문제를 자주 보았지만 실제로 조각난 힙으로 고통받는 시스템을 본 적이 없었습니다.


"우리는 malloc / free가 절대적으로 필요한 경우가 아니라면 호출되지 않도록하기 위해 많은 노력을 기울였습니다 ..." -라우터를 만드는 일부 하드웨어 담당자를 알고 있습니다. 그들은 심지어 귀찮게하지 않습니다 malloc/free. 메모리 블록을 예약하고이를 커서 데이터 구조로 사용합니다. 대부분의 작업은 인덱스 추적으로 줄었습니다.

4

비디오 처리, VFX, 운영 체제 등 사람들이 종종이를 과도하게 사용합니다. 효율적인 할당을 위해 데이터 구조와 할당자를 분리 할 필요는 없습니다.

예를 들어, 효율적인 트리 노드 할당을 octree 자체에서 떨어진 octree 자체로 분할하고 외부 할당 자에 의존하기 위해 많은 추가 복잡성을 도입하고 있습니다. 이러한 두 가지 문제를 함께 해결하고 변경해야하는 이유가 증가하지 않기 때문에 한 번에 많은 노드를 연속적으로 할당하는 것은 ORP의 책임이 SRP를 위반하는 것은 아닙니다. 실제로 말하면 감소시킬 수 있습니다.

예를 들어, C ++에서 표준 컨테이너가 외부 할당 자에 의존하는 데 따른 지연된 부작용 중 하나 는 벤치마킹하기 때문에 C ++ 커뮤니티 std::map와 같은 링크 구조를 만들고 std::list거의 쓸모없는 것으로 간주했습니다.std::allocator이러한 데이터 구조는 한 번에 하나의 노드를 할당합니다. 물론이 경우 연결된 구조가 제대로 작동하지 않지만 연결된 구조에 대한 효율적인 노드 할당이 할당 자보다는 데이터 구조의 책임으로 간주되면 상황이 크게 다르게 나왔을 것입니다. 메모리 추적 / 프로파일 링과 같은 다른 이유로 여전히 커스텀 할당을 사용할 수도 있지만 할당 된 노드를 한 번에 하나씩 할당하는 동안 링크 된 구조를 효율적으로 만들기 위해 할당 자에 의존하는 것이 기본적으로 매우 비효율적입니다. 잘 알려진주의 사항이 있다면 연결된 구조에 이제는 자유 목록과 같은 사용자 지정 할당자가 필요하며 효율적으로 캐시 미스가 왼쪽과 오른쪽으로 트리거되는 것을 피해야합니다. 훨씬 더 실질적으로 적용 가능한 것은std::list<T, BlockSize, Alloc>여기서 BlockSize, 사용 가능리스트에 대해 한 번에 할당 할 인접 노드의 수를 나타냅니다 (1을 지정 std::list하면 현재와 같이 효과적으로 이어집니다 ).

그러나 이러한 경고는 없습니다. 그러면 연결된 목록이 쓸모없는 컬트 만트라를 울리는 전체 블록 헤드 커뮤니티로 이어집니다.


3

사용자 지정 할당자를 원하는 또 다른 영역은 힙 조각화 를 방지하는 입니다. 시간이 지남에 따라 힙은 힙 전체에 조각난 작은 개체를 할당 할 수 있습니다. 프로그램이 힙 메모리를 함께 유지할 수없는 경우, 프로그램이 더 큰 객체를 할당 할 때 기존의 조각난 힙 사이에서 사용 가능한 블록을 찾을 수 없으므로 시스템에서 더 많은 메모리를 요구해야합니다 (너무 작은 것) 개체가 방해가됩니다). 프로그램의 총 메모리 사용량은 시간이 지남에 따라 증가하므로 불필요하게 추가 메모리 페이지를 소비하게됩니다. 따라서 이것은 오랜 기간 동안 실행될 것으로 예상되는 프로그램 (데이터베이스, 서버 등 생각)에있어 매우 큰 문제입니다.

게임과는 별도로 커스텀 할당자는 어디에 사용됩니까?

페이스 북

Facebook이 힙 성능을 개선하고 조각화를 줄이기 위해 사용 하고있는 jemalloc 을 확인하십시오 .


권리. 그러나 복사 가비지 수집기는 조각화 문제를 깔끔하게 해결합니까?
rwallace
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.