문제

나는 많은 양의 MSMQ 대기열(현재 약 10000개)에서 읽는 응용 프로그램을 가지고 있습니다.나는 사용한다 queue.BeginPeek 대기열에서 메시지를 수신하려면 UInt32.MaxValue 시간 초과가 필요합니다.메시지가 대기열에 나타나면 처리하고 호출합니다. queue.BeginPeek 다시.그래서 모든 대기열을 수신하지만 메시지 처리는 Thread Pool에서 수행됩니다.

메모리 사용량이 천천히 증가하는 것을 확인했습니다(2주 동안 작업하면 200MB에서 800MB로 증가함).덤프 파일을 조사한 후 많은 사용 가능한 개체(일부는 수 메가바이트 정도의 크기)가 있는 일반적인 힙 조각화 그림을 볼 수 있습니다.그리고 구멍 사이에는 고정된 물체가 있습니다.

이는 고정된 개체를 생성하는 비관리 코드 호출 작업을 할 때 일반적인 상황인 것 같습니다.하지만 인터넷에서 어떤 해결책도 찾지 못했습니다.

그렇다면 .NET의 메모리 관리는 너무 순수해서 이러한 간단한 시나리오도 완료할 수 없거나 뭔가를 놓친 것일까요?

편집하다 : 샘플 애플리케이션에서 몇 가지 조사를 수행했습니다.고정된 객체 사이의 구멍(자유 객체라고 불리는 여유 메모리 영역)은 새 객체에 메모리를 할당할 때 GC에 의해 재사용됩니다.그러나 내 프로덕션 애플리케이션에서는 고정된 개체가 오래 지속되며 마침내 2세대에 그 사이에 구멍이 있는 상태로 나타납니다(GC는 단지 세대를 구분하는 경계를 이동하기 때문입니다).일반적으로 오래 지속되는 개체가 거의 없기 때문에 덤프 파일에서 2세대에 이 구멍이 보입니다.

따라서 내 애플리케이션의 메모리 소비는 10000*(구멍의 평균 크기)까지 늘어날 수 있습니다.(10000은 향후에도 증가할 수 있는 대기열 수입니다.)현재로서는 이 문제를 해결하는 방법이 없습니다.유일한 방법은 수시로 응용 프로그램을 다시 시작하는 것입니다.

다시 한 번 질문할 수 있는 것은 왜 .NET에 고정된 개체에 대한 별도의 힙이 없는 걸까요?(어쩌면 이것은 초보자 질문일지도 모릅니다).현재 비관리 코드로 작동하는 비동기 작업을 호출하면 메모리 문제가 발생할 수 있다는 것을 확인했습니다.

도움이 되었습니까?

해결책

MSMQ용 관리 래퍼의 소스 코드를 살펴본 후 API 사용 시 실제 문제를 발견한 것 같습니다.부름 BeginPeek 관리되지 않는 API에 전달되기 전에 고정되는 속성 컬렉션을 생성합니다.메시지가 수신될 때만 이러한 속성이 고정 해제되지만 메시지를 계속 수신하려면 호출해야 합니다. BeginPeek 이 시점에서 시간이 지남에 따라 메모리 조각화가 발생합니다.

이 조각화가 정말로 문제라면 제가 생각해 낼 수 있는 유일한 해킹은 매 시간마다 하는 것이므로 모든 통화를 취소해야 합니다. BeginPeek, 가비지 수집을 강제로 수행한 다음 정상적인 수신 작업을 재개합니다.이렇게 하면 가비지 수집기가 조각화를 처리할 수 있습니다.

다른 팁

음, 고정된 개체가 오래 지속되는 데 문제가 있는 경우 간단한 해결 방법은 개체에 시간 초과를 사용하는 것입니다. BeginPeek 다음 세대로 넘어가는 것을 막기 위해 더 짧은 기간을 가지게 됩니다.각 시간 초과 후 및 EndPeek 재발급 받을 수 있어요 BeginPeek.Martin이 언급한 속성이 언제 생성되고 삭제되는지에 따라 대기열 개체(대기열 자체가 아니라 관리 래퍼만)를 다시 만들어야 할 수도 있습니다.운이 좋으면 그렇게 멀리까지 갈 필요는 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top