동시성 시각화 도우미를 사용하면 개발자가 다중 스레드 애플리케이션의 동작을 시각화할 수 있습니다. 이 도구에는 심하게 동작하는 다중 스레드 애플리케이션에 대한 일반적인 패턴 갤러리가 포함되어 있습니다. 갤러리에는 도구를 통해 노출되는 일반적이고 인식 가능한 시각적 패턴과 각 패턴으로 표현되는 동작에 대한 설명, 해당 동작의 가능성이 있는 결과 및 이를 해결하는 가장 일반적인 방법이 포함되어 있습니다.
잠금 경합 및 직렬화된 실행
병렬 처리된 애플리케이션은 스레드가 여러 개 있고 컴퓨터에 충분한 수의 논리 코어가 있더라도 연속적으로 계속 실행되는 경우가 있습니다. 첫 번째 증상은 다중 스레드 성능 저하이며 직렬 구현보다 약간 느려질 수도 있습니다. 스레드 뷰에서는 여러 스레드가 병렬로 실행되는 것을 볼 수 없습니다. 대신 한 번에 하나의 스레드만 실행되는 것을 볼 수 있습니다. 이 시점에서 스레드에서 동기화 세그먼트를 클릭하면 차단된 스레드(호출 스택 차단)에 대한 호출 스택과 차단 조건(호출 스택 차단 해제)을 제거한 스레드를 볼 수 있습니다. 또한, 분석 중인 프로세스에서 차단 해제 호출 스택이 발생하면 Thread-Ready 커넥터가 표시됩니다. 이 지점에서 블로킹 및 언블로킹 호출 스택을 통해 코드로 이동하여 직렬화의 원인을 더욱 자세히 조사할 수 있습니다.
다음 그림과 같이 동시성 시각화 도우미는 여러 스레드가 있음에도 불구하고 애플리케이션이 하나의 논리 코어만 사용하는 CPU 사용률 보기에서 이 증상을 노출할 수도 있습니다.
자세한 내용은 MSDN Magazine 문서 스레드 성능 - Visual Studio의 리소스 경합 동시성 프로파일링에서 "문제 섹션으로 시작"을 참조하세요.
고르지 않은 워크로드 배포
애플리케이션의 여러 병렬 스레드에서 작업의 불규칙한 분포가 발생하면 이전 그림과 같이 각 스레드가 작업을 완료할 때 일반적인 계단 단계 패턴이 나타납니다. 동시성 시각화 도우미는 대부분의 경우 각 동시 스레드에 대해 매우 가까운 시작 시간을 표시합니다. 그러나 이러한 스레드는 일반적으로 동시에 종료되는 대신 불규칙한 방식으로 끝납니다. 이 패턴은 병렬 스레드 그룹 간에 작업이 불규칙하게 분포되어 성능이 저하될 수 있음을 나타냅니다. 이러한 문제에 대한 가장 좋은 방법은 병렬 스레드 간에 작업이 분할된 알고리즘을 다시 평가하는 것입니다.
다음 그림과 같이 동시성 시각화 도우미는 CPU 사용률 보기에서 이러한 증상을 CPU 사용률의 점진적인 단계별 축소로 노출할 수도 있습니다.
초과 구독
초과 구독의 경우 프로세스의 활성 스레드 수가 시스템에서 사용 가능한 논리 코어 수보다 큽니다. 이전 그림에서는 모든 활성 스레드에서 중요한 선점 밴딩이 있는 오버 서브스크립션의 결과를 보여 줍니다. 범례는 많은 시간이 선점 상태에 소요된다는 것을 보여줍니다 (이 예에서는 84%입니다). 이는 프로세스가 논리 코어 수보다 더 많은 동시 스레드를 실행하도록 시스템에 요청하고 있음을 나타낼 수 있습니다. 그러나 이는 시스템의 다른 프로세스가 이 프로세스에서 사용할 수 있다고 가정된 리소스를 사용하고 있음을 나타낼 수도 있습니다.
이 문제를 평가할 때는 다음 사항을 고려해야 합니다.
전체 시스템이 초과 구독될 수 있습니다. 다른 프로세서가 시스템에서 스레드를 선점할 수 있음을 고려하십시오. 스레드 뷰에서 선점 세그먼트를 일시 중지하면 도구 설명은 스레드와 스레드를 선점한 프로세스를 식별합니다. 이 프로세스가 선점된 전체 시간 동안 실행된 프로세스는 아니지만 프로세스에 대한 선점 압력을 유발한 항목에 대한 힌트를 제공합니다.
이 작업 단계에서 프로세스에서 실행에 적합한 스레드 수를 결정하는 방법을 평가합니다. 프로세스에서 활성 병렬 스레드 수를 직접 계산하는 경우 시스템에서 사용 가능한 논리 코어 수를 더 잘 고려하도록 해당 알고리즘을 수정하는 것이 좋습니다. 동시성 런타임, 작업 병렬 라이브러리 또는 PLINQ를 사용하는 경우 이러한 라이브러리는 스레드 수를 계산하는 작업을 수행합니다.
비효율적인 I/O
I/O의 남용 또는 오용은 애플리케이션에서 비효율성의 일반적인 원인입니다. 이전 그림을 고려해 보세요. 표시되는 타임라인 프로필은 표시되는 스레드 시간의 44%가 I/O에서 사용됨을 보여줍니다. 타임라인은 많은 양의 I/O를 보여 줍니다. 이는 프로파일된 애플리케이션이 I/O에 의해 자주 차단됨을 나타냅니다. I/O 종류 및 프로그램이 차단되는 위치에 대한 세부 정보를 보려면 문제가 있는 지역을 확대하고, 표시되는 타임라인 프로필을 검사한 다음, 특정 I/O 블록을 클릭하여 현재 호출 스택을 확인합니다.
잠금 호송
잠금 호송은 애플리케이션이 선착순으로 잠금을 획득하고 잠금의 도착률이 획득 속도보다 높을 때 발생합니다. 이 두 조건의 결합으로 인해 잠금 요청이 쌓이게 됩니다. 이 문제를 해결하는 한 가지 방법은 "불공평한" 잠금을 사용하여 잠금이 해제된 상태에서 처음 찾는 스레드에 액세스 권한을 부여하는 것입니다. 이전 그림에서는 이 호송 동작을 보여 줍니다. 이 문제를 해결하려면 동기화 개체에 대한 경합을 줄이고 불공정 잠금을 사용해 보세요.