프로파일링 및 런타임 알림 ID
런타임 알림에서는 보고되는 클래스, 스레드, 응용 프로그램 도메인 등에 대한 ID를 제공합니다. 이러한 ID를 사용하여 CLR(공용 언어 런타임)에 추가 정보를 쿼리할 수 있습니다. 각 ID는 항목을 설명하는 메모리 블록의 주소입니다. 그러나 프로파일러에서는 ID를 불분명한 핸들로 처리해야 합니다. 프로파일링 함수를 호출할 때 잘못된 ID를 사용하면 결과가 정의되지 않으며 액세스 위반이 될 가능성이 높습니다. 따라서 프로파일러에서는 ID가 올바로 사용되는지 확인해야 합니다. 유효성 검사를 수행하면 오버헤드가 생성되고 응용 프로그램 실행이 상당히 느려지므로 프로파일링 API에서는 유효성 검사를 수행하지 않습니다.
다음 단원에서는 프로파일링 API에서 ID의 특성에 대해 설명합니다.
고유성
ProcessID는 프로세스의 수명 동안 시스템 전체에서 고유합니다. 다른 모든 ID는 ID의 수명 동안 프로세스 전체에서 고유합니다.
계층 구조 및 포함
ID는 프로세스의 계층 구조를 미러링하는 계층 구조로 정렬됩니다. 프로세스는 응용 프로그램 도메인을, 응용 프로그램 도메인은 어셈블리를, 어셈블리는 모듈을, 모듈은 클래스를, 클래스는 함수를 포함합니다. 스레드는 프로세스 내에 포함되며 응용 도메인 간에 이동될 수 있습니다. 개체는 대부분 응용 프로그램 도메인 내에 포함되며 매우 적은 수의 일부 개체는 동시에 여러 응용 프로그램 도메인의 멤버일 수 있습니다. 컨텍스트는 프로세스 내에 포함됩니다.
수명 및 안정성
지정된 프로세스, 응용 프로그램 도메인, 어셈블리, 스레드 또는 개체가 소멸 또는 해제되거나 끝나는 경우 이와 연결된 ID가 무효화됩니다. 지정된 ID가 무효화되면 여기에 포함된 ID도 모두 무효화됩니다. 예를 들어 응용 프로그램 도메인이 언로드되면 해당 AppDomainID가 무효화됩니다. 동시에 이 응용 프로그램 도메인 내의 어셈블리, 모듈, 클래스 및 함수에 해당하는 AssemblyID, ModuleID, ClassID 및 FunctionID도 무효화됩니다.
특정 ID의 수명 및 안정성은 다음과 같습니다.
ProcessID: ICorProfilerCallback::Initialize 메서드를 호출할 때부터 ICorProfilerCallback::Shutdown 메서드에서 반환될 때까지 활성이고 안정적입니다.
AppDomainID: ICorProfilerCallback::AppDomainCreationFinished 메서드를 호출할 때부터 ICorProfilerCallback::AppDomainShutdownStarted 메서드에서 반환될 때까지 활성이고 안정적입니다.
AssemblyID, ModuleID, ClassID: ID에 대한 LoadFinished 메서드를 호출할 때부터 ID에 대한 UnloadStarted 메서드에서 반환될 때까지 활성이고 안정적입니다.
FunctionID: ICorProfilerCallback::JITCompilationFinished 또는 ICorProfilerCallback::JITCachedFunctionSearchFinished 메서드를 호출할 때부터 포함된 ClassID가 소멸될 때까지 활성이고 안정적입니다.
ThreadID: ICorProfilerCallback::ThreadCreated 메서드를 호출할 때부터 ICorProfilerCallback::ThreadDestroyed 메서드에서 반환될 때까지 활성이고 안정적입니다.
ObjectID: ICorProfilerCallback::ObjectAllocated 메서드를 호출할 때부터 활성입니다. 각 가비지 수집과 함께 변경 또는 소멸될 수 있습니다.
GCHandleID: ICorProfilerCallback2::HandleCreated 메서드를 호출할 때부터 ICorProfilerCallback2::HandleDestroyed 메서드에서 반환될 때까지 활성이고 안정적입니다.
또한 프로파일링 함수에서 반환되는 ID는 반환될 때 활성이 됩니다.
응용 프로그램 도메인 선호도
프로세스에서 사용자가 만든 각 응용 프로그램 도메인에는 AppDomainID가 있습니다. 도메인 중립적인 어셈블리를 보관하는 데 사용되는 특수한 의사 도메인 및 기본 도메인에도 AppDomainID가 있습니다.
어셈블리, 모듈, 클래스, 함수 및 가비지 수집기 핸들에는 응용 프로그램 도메인 선호도가 있습니다. 즉 어셈블리가 여러 응용 프로그램 도메인에 로드되는 경우 어셈블리 및 해당 모듈, 클래스, 함수 및 가비지 수집기 핸들은 각 응용 프로그램 도메인에서 서로 다른 ID를 갖게 되고 각 ID에 대한 작업은 연결된 응용 프로그램 도메인에만 적용됩니다. 도메인 중립적인 어셈블리는 앞에서 언급한 특수한 의사 도메인에 표시됩니다.
참고 사항
ObjectID를 제외한 ID는 불분명한 값으로 처리해야 합니다. 대부분의 ID는 ID만 보아도 어떤 ID인지 어느 정도 이해할 수 있습니다. 다음 ID는 자세히 설명할 필요가 있습니다.
ClassID는 클래스를 나타냅니다. 제네릭 클랙스의 경우 완전히 인스턴스화된 형식을 나타냅니다. List<int>, List<char>, List<object> 및 List<string>에는 각각 고유한 ClassID가 있습니다. List<T>는 인스턴스화되지 않은 형식이며 ClassID가 없습니다. Dictionary<string,V>는 부분적으로 인스턴스화된 형식이며 ClassID가 없습니다.
FunctionID는 함수의 네이티브 코드를 나타냅니다. 제네릭 함수 또는 제네릭 클래스에 대한 함수의 경우 네이티브 코드 인스턴스가 여러 개일 수 있으므로 지정한 함수에 대해 여러 개의 FunctionID가 있을 수 있습니다. 네이티브 코드 인스턴스는 다른 형식(예: List<string> 및 List<object> 공유 코드) 간에 공유될 수 있으므로 FunctionID가 둘 이상의 ClassID에 속할 수 있습니다.
ObjectID는 가비지 수집된 개체를 나타냅니다. ObjectID는 프로파일러에서 ObjectID를 받을 때 개체의 현재 주소이며 각 가비지 수집과 함께 변경될 수 있습니다. 따라서 ObjectID 값은 받은 때부터 다음 가비지 수집이 시작될 때까지만 유효합니다. 또한 CLR에서는 프로파일러에서 가비지 수집 간에 유효한 ObjectID를 유지할 수 있도록 프로파일러에 내부 개체 추적 맵을 업데이트하라는 알림을 제공합니다.
GCHandleID는 가비지 수집 핸들 테이블의 항목을 나타냅니다. GCHandleID는 ObjectID와 달리 불분명한 값입니다. 가비지 수집 핸들은 일부 경우 CLR 자체에서 만들거나 GCHandle 구조체를 사용하여 만들 수 있습니다. GCHandle 구조체는 핸들을 나타낼 뿐이며 핸들이 구조체에 포함되지는 않습니다.
ThreadID는 관리되는 스레드를 나타냅니다. 호스트에서 파이버 모드 실행을 지원하는 경우 관리되는 스레드는 검사되는 시기에 따라 서로 다른 운영 체제 스레드에 있을 수 있습니다.
참고 .NET Framework 버전 2.0에서는 파이버 모드 응용 프로그램에 대한 프로파일링이 지원되지 않습니다.