.Net CLR 스레드 풀 이해

.Net Framework에서 CLR은 실행중인 애플리케이션에 리소스를 제공하는 역할을합니다. 특히 CLR 스레드 풀은 스레드를 추가하거나 제거 할시기를 결정합니다. 이것이 어떻게 작동하는지 이해하면 최적의 성능을 위해 ASP.Net 응용 프로그램을 구성하는 방법을 결정하는 데 도움이됩니다.

CLR 스레드 풀에는 작업자 스레드와 I / O 완료 포트 또는 IOCP 스레드라는 두 종류의 스레드가 포함됩니다. 즉, ASP.Net 작업자 프로세스에는 실제로 작업자 스레드 풀과 IOCP 스레드 풀이라는 두 개의 스레드 풀이 포함되어 있습니다. 당연히이 풀은 다른 목적을 가지고 있습니다.

이 같은 방법을 사용하는 경우 Task.Run, TaskFactory.StartNew그리고 ThreadPool.QueueUserWorkItem런타임 처리를 위해 작업자 스레드의 활용합니다. 애플리케이션에서 비동기 I / O 호출을하거나 애플리케이션이 파일 시스템, 데이터베이스, 웹 서비스 등에 액세스하면 런타임은 IOCP 스레드를 사용합니다. 각 애플리케이션 도메인에는 자체 스레드 풀이 있습니다.

.Net Framework에서 이러한 스레드가 어떻게 생성되고 제거되는지 자세히 살펴 보겠습니다. 

스레드 주입 전략

.Net 스레드 풀은 사용중인 스레드 수가 스레드 풀에 구성된 최소 스레드 수와 같아 질 때마다 새 스레드를 주입하기 시작합니다. 의 최소 수를 최소 설정의 기본값은  모두  노동자와 IOCP 스레드는 시스템의 프로세서 수에 의해 결정된다. 따라서 시스템에 4 개의 코어가있는 경우 기본적으로 작업자 스레드 4 개와 IOCP 스레드 4 개가 있습니다. 

그런 다음 .Net 스레드 풀은 기존 스레드가 활용되고 아직 수행 할 작업이있는 경우 요청시 추가 작업자 스레드를 삽입합니다. 마찬가지로 리소스에 대한 수요가 감소하면 스레드 풀이 스레드를 제거하기 시작합니다. 

다음 코드 조각을 실행하면 시스템의 논리 프로세서 수와 사용 가능한 작업자 및 IOCP 스레드의 최소 수가 표시됩니다.

static void Main (string [] args)

{

    int minimumWorkerThreadCount, minimumIOCThreadCount;

      int logicalProcessorCount = System.Environment.ProcessorCount;

      ThreadPool.GetMinThreads (minimumWorkerThreadCount 출력, minimumIOCThreadCount 출력);

      Console.WriteLine (“프로세서 수 :“+ logicalProcessorCount);

     Console.WriteLine (“최소 작업자 스레드 수 :“+ minimumWorkerThreadCount);

      Console.WriteLine (“최소 IOCP 스레드 수 :“+ minimumIOCThreadCount);

      Console.Read ();

}

.Net 스레드 풀은 기본 제공 휴리스틱을 사용하여 스레드를 관리합니다. 채택 된 전략에는 기아 방지 및 언덕 오르기 알고리즘이 포함됩니다. 전자의 경우 .Net 스레드 풀은 대기중인 항목에 진행 상황이 표시되지 않으면 작업자 스레드를 계속 추가합니다. 후자의 경우 .Net 스레드 풀은 가능한 적은 스레드를 사용하여 처리량을 최대화하려고합니다.

.Net 스레드 풀은 500 밀리 초 간격으로 또는 스레드가 사용 가능 해지면 스레드를 삽입하거나 제거합니다. 이제 런타임에 사용 가능한 피드백을 기반으로 .Net 스레드 풀은 스레드를 제거하거나 스레드를 추가하여 처리량을 최대화합니다. 스레드를 추가해도 처리량이 증가하지 않으면 스레드가 사라집니다. 이것이 CLR의 언덕 오르기 기술입니다.

이제 IIS에서 ASP.Net 응용 프로그램을 실행하고 웹 서버에 총 4 개의 CPU가 있다고 가정합니다. 특정 시점에 처리 할 요청이 24 개 있다고 가정합니다. 기본적으로 런타임은 처음 4 개의 요청을 처리하는 데 사용할 수있는 4 개의 스레드를 생성합니다. 500 밀리 초가 경과 할 때까지 추가 스레드가 추가되지 않기 때문에 다른 20 개의 요청은 대기열에서 기다려야합니다. 500 밀리 초가 지나면 새 스레드가 생성됩니다.

보시다시피 워크로드를 따라 잡으려면 500ms 간격이 많이 걸립니다. 이것은 비동기 프로그래밍을 사용하는 좋은 이유입니다. 비동기 프로그래밍을 사용하면 요청이 처리되는 동안 스레드가 차단되지 않으므로 4 개의 스레드가 거의 즉시 해제됩니다. 

권장 스레드 설정

.Net 스레드 풀이 작동하는 방식과 지금까지 설명한 내용을 감안할 때 작업자 및 IOCP 스레드 모두에 대해 최소 구성 값 (기본값)을 변경하는 것이 좋습니다. ASP.Net에서이 작업을 수행하려면 시스템의 machine.config 파일에 있는 구성 요소에서 minWorkerThreadsminIoThreads구성 설정을 변경 해야합니다.

           minIoThreads =”여기에 원하는 값 제공”/>

작업자 및 IOCP 스레드에 대한 최소 구성 값을 1에서 50 사이의 값으로 설정할 수 있습니다. 좋은 방법은 IIS 작업자 프로세스 (W3wp.exe)의 사용자 모드 프로세스 덤프를 가져온 다음 !threadpool명령을 사용하여 보고하는 것입니다. 총 작업자 스레드 수입니다. 이 값을 알고 나면 시스템의 프로세서 코어 수로 나누기 만하면 최소 작업자 및 IOCP 스레드 설정을 결정할 수 있습니다. 예를 들어 총 작업자 스레드 수가 100이고 시스템에 4 개의 프로세서가있는 경우 작업자 및 IOCP 스레드의 최소값을 25로 설정할 수 있습니다.

ASP.Net 외부의 기본 최소 스레드 설정을 변경하려면이 ThreadPool.SetMinThreads()메서드를 사용할 수 있습니다 .

더 나은 스레드 관리 및 성능 향상을 목표로 CLR 스레드 풀이 각 버전의 CLR에서 향상되었습니다. 예를 들어 .Net Framework 4에서 CLR은 스레드 스틸 링 알고리즘을 확보하고 동시성 및 병렬 처리를 지원했습니다. CLR의 새 버전이 나올 때마다 .Net 스레드 풀은 필요에 따라 스레드를 만들고 제거하여 처리량을 최적화하는 데있어 점점 더 스마트 해지고 있습니다. 그 동안 .Net 애플리케이션에서 최고의 성능을 얻기 위해 다양한 최소 스레드 설정을 실험 해 볼 수 있습니다.