Microsoft.Extensions.ObjectPool은 객체 집합을 메모리에 저장하여 재사용을 가능하게 하는 ASP.NET Core 인프라의 일부로, 객체의 가비지 컬렉션을 허용하지 않습니다. 관리하려는 객체가 다음과 같다면, 다음 객체 풀을 사용해야 할 수도 있습니다:
- 할당/초기화는 비용이 많이 듭니다.
- 제한된 자원을 대표합니다.
- 예측 가능하고 자주 사용하세요.
재사용은 중요한 주제이며, 우리가 일상적으로 겪는 불가피한 문제입니다.
가장 단순하고 익숙한 예로, 데이터베이스 연결 풀은 재사용된 데이터베이스 연결입니다.
그렇다면 재사용의 의미는 무엇일까요?
간단히 말해, 불필요한 자원 손실을 줄여줍니다.
데이터베이스 연결 외에도 다양한 시나리오나 요구사항에 따라 재사용해야 하는 객체가 많을 수 있으며, 이른바 객체 풀(Object Pool)이 있습니다.
비슷한 함수를 직접 구현해봤어야 합니다. ConcurrentBag이나 ConcurrentQueue, 혹은 다른 솔루션으로요.
이 기능은 Microsoft 문서에서 구현된 사례를 공유합니다
방법: ConcurrentBag을 사용해 객체 풀 생성
하이퍼링크 로그인이 보입니다.
물론 .NET Core에서는 마이크로소프트가 간단한 오브젝트 풀을 구현하는 데 도움을 주었습니다.
먼저, 새로운 .NET Core 콘솔 프로젝트를 만들고 nuget 명령어를 사용해 다음 패키지를 추가하세요:
모든 코드는 다음과 같습니다:
사용 1
풀을 만들기 전에 정책을 정의해야 합니다. 여기서는 포함된 DefaultPooledObjectPolicy를 직접 사용하여 이를 구성합니다.
객체 풀에는 유지되는 최대 스레드 수가 있습니다.
풀 오브젝트의 Get 메서드를 사용해 오브젝트 풀에서 오브젝트를 빼세요.
위 코드는 결과를 실행합니다
#1-464d2e03-604d-4451-b68a-8a3a2abdfccc-itsvse.com-1/1/0001 오전 12:00:00 #2-70122aa0-a949-4c63-b878-321efe64c234-itsvse.com-1/1/0001 오전 12:00:00 #3-de717815-796a-4349-a571-047acc125104-itsvse.com-1/1/0001 오전 12:00:00 #4-3a404341-a560-47f7-a3b0-0d477a8ae17f-itsvse.com-1/1/0001 오전 12:00:00 #5-51c96126-d424-4b58-b07c-6408e6c4cea6-itsvse.com-1/1/0001 오전 12:00:00 #6-7ea4d596-fd2a-43b3-959a-9e48da58a758-itsvse.com-1/1/0001 오전 12:00:00 #7-6874c64b-532d-4f92-a4fb-ff472da574a1-itsvse.com-1/1/0001 오전 12:00:00 #8-ca767674-2c07-4f26-975f-4711a31d795d-itsvse.com-1/1/0001 오전 12:00:00 #9-a9cd1859-a919-46a0-ae5d-85b6d3d11ccb-itsvse.com-1/1/0001 오전 12:00:00 #10-fe89ed8b-4dfd-4eef-b876-b2a60ee50958-itsvse.com-1/1/0001 오전 12:00:00 이 결과는 객체 풀 내 객체들이 직접 새롭게 생성되었고, 일부 속성은 평가절하되지 않았음을 보여줍니다. 이는 현재로서는 실질적인 의미가 많지 않은 경우가 많습니다.
DefaultPooledObjectPolicy가 직접적으로 새로운 객체이기 때문에, 많은 경우 우리가 기대하는 바와 다릅니다!
우리의 실제 사용을 원한다면, 스스로 정책을 정의해야 합니다!
사용법 2를 살펴보겠습니다
사용 2
Create 메서드는 데모 객체를 생성하는 데 사용되며, Return 메서드는 데모 객체를 다시 Object Pool(빌린 후 반환)에 다시 넣는 방법입니다.
여기서 객체 풀은 오직 하나의 객체만 담도록 정의됩니다.
객체 풀에서 꺼낸 후 1단계 반환 연산이 있으므로, item1과 item2는 동일한 객체여야 합니다.
객체 풀에서 item2를 제거하면 반환되지 않기 때문에, 객체 풀은 우리가 정의한 정책에 따라 새로운 객체를 생성합니다.
다음은 사용 2의 출력 결과입니다:
985b3232-0a45-4115-8480-ad3d42c0ae10-itsvse.com/4/15/2020 오전 3:31:15 985b3232-0a45-4115-8480-ad3d42c0ae10-itsvse.com/4/15/2020 오전 3:31:15
True 8912424a-15c5-4891-b625-25b17eee5c8b-itsvse.com/4/15/2020 오전 3:31:15
False item1, item2, item3의 개별 속성이 동일하며, item1과 item2는 실제로 동일한 객체임을 알 수 있습니다. Item3와 Item1은 같은 것이 아닙니다.
사용 3
item1과 item2가 같은 객체임을 알 수 있습니다. 객체 풀에서 객체를 가져올 때 첫 번째 객체가 가져가므로, 반환 후 다시 가져와도 원본이 먼저 나옵니다.
item3는 그곳의 Object Pool에서 직접 가져오며, 다시 생성되지 않습니다. 여기서 Object Pool은 사용 2에서 하나만 관리하는 것이 아니라 여러 객체를 관리하기 때문에 Pool에서 직접 가져옵니다.
다음은 출력 결과입니다
f3cd5467-536b-4ffe-9c71-de53027b4869-itsvse.com/4/15/2020 오전 3:33:58 f3cd5467-536b-4ffe-9c71-de53027b4869-itsvse.com/4/15/2020 오전 3:33:58
True b933b593-af6d-4ebe-b21b-e8784d124764-itsvse.com-4/15/2020 오전 3:33:58
False 두 번째 사용법과 같아요, 본질은 같아요.
사용 4
위의 용법은 우리의 일반적인 사용법과 그리 비슷하지 않은 것 같습니다. 우리는 여전히 주사에 의존해야 합니다.
이제 드디어 의존성 주입을 어떻게 결합할지 살펴보겠습니다. 물론, 본질은 여전히 정책과 제공자라는 두 가지와 떼려야 뗄 수 없습니다.
먼저 프로바이더를 등록한 후, 그 인스턴스를 직접 가져와 객체 풀을 생성해야 합니다.
다른 곳에서 사용하고 싶다면, 생성기를 통해 주입할 수 있습니다.
결과도 이전과 같아서 할 말이 많지 않습니다.
요약
하지만 어떤 용도든, 객체 풀은 풀, 정책, 제공자 세 가지 요소와 떼려야 뗄 수 없다는 점을 이해해야 합니다.
이 셋과 함께라면 우리가 원하는 대로 할 수 있을지도 몰라.
물론, 관심 있다면 확인해 볼 수 있는 특별한 내용들도 몇 가지 있습니다.
LeakTrackingObjectPool(누설 추적 객체풀)
StringBuilderPooledObjectPolicy
|