Add runtime counter for current assemblies loaded (dotnet/coreclr#24698)
authorSung Yoon Whang <suwhang@microsoft.com>
Wed, 22 May 2019 06:06:17 +0000 (23:06 -0700)
committerGitHub <noreply@github.com>
Wed, 22 May 2019 06:06:17 +0000 (23:06 -0700)
* Consume # of assemblies loaded

* Fix names

* Fix build

* Add ifdef in assemblynative.hpp

* fix merge error

* fix build break

* Address PR feedback

* Fix linux build

* Remove ifdef

Commit migrated from https://github.com/dotnet/coreclr/commit/f33ffab85335b9ca6b0f669d59de599e981c295f

src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/RuntimeEventSource.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs
src/coreclr/src/vm/assembly.cpp
src/coreclr/src/vm/assemblynative.cpp
src/coreclr/src/vm/assemblynative.hpp
src/coreclr/src/vm/ecalllist.h

index 6c13eff..01366c1 100644 (file)
@@ -24,6 +24,7 @@ namespace System.Diagnostics.Tracing
         private IncrementingPollingCounter? _monitorContentionCounter;
         private PollingCounter? _threadPoolQueueCounter;
         private IncrementingPollingCounter? _completedItemsCounter;
+        private PollingCounter? _assemblyCounter;
 
         private const int EnabledPollingIntervalMilliseconds = 1000; // 1 second
 
@@ -56,6 +57,7 @@ namespace System.Diagnostics.Tracing
                 _monitorContentionCounter = _monitorContentionCounter ?? new IncrementingPollingCounter("monitor-lock-contention-count", this, () => Monitor.LockContentionCount) { DisplayName = "Monitor Lock Contention Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; 
                 _threadPoolQueueCounter = _threadPoolQueueCounter ?? new PollingCounter("threadpool-queue-length", this, () => ThreadPool.PendingWorkItemCount) { DisplayName = "ThreadPool Queue Length" };
                 _completedItemsCounter = _completedItemsCounter ?? new IncrementingPollingCounter("threadpool-completed-items-count", this, () => ThreadPool.CompletedWorkItemCount) { DisplayName = "ThreadPool Completed Work Item Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) };
+                _assemblyCounter = _assemblyCounter ?? new PollingCounter("assembly-count", this, () => System.Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" };
             }
         }
     }
index deb83ec..8b0237c 100644 (file)
@@ -120,5 +120,8 @@ namespace System.Reflection
         // Exists to faciliate code sharing between CoreCLR and CoreRT.
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal bool IsRuntimeImplemented() => this is RuntimeAssembly;
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern uint GetAssemblyCount();
     }
 }
index 4573f7c..e04310e 100644 (file)
@@ -80,6 +80,8 @@
 // to help your debugging.
 DWORD g_dwLoaderReasonForNotSharing = 0; // See code:DomainFile::m_dwReasonForRejectingNativeImage for a similar variable.
 
+volatile uint32_t g_cAssemblies = 0;
+
 // These will sometimes result in a crash with error code 0x80131401 SECURITY_E_INCOMPATIBLE_SHARE
 // "Loading this assembly would produce a different grant set from other instances."
 enum ReasonForNotSharing
@@ -179,6 +181,8 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat
 #endif
         m_pManifest = Module::Create(this, mdFileNil, GetManifestFile(), pamTracker);
 
+    FastInterlockIncrement((LONG*)&g_cAssemblies);
+
     PrepareModuleForAssembly(m_pManifest, pamTracker);
 
     CacheManifestFiles();
@@ -326,6 +330,7 @@ void Assembly::StartUnload()
     STATIC_CONTRACT_NOTHROW;
     STATIC_CONTRACT_GC_TRIGGERS;
     STATIC_CONTRACT_FORBID_FAULT;
+
 #ifdef PROFILING_SUPPORTED
     if (CORProfilerTrackAssemblyLoads())
     {
@@ -351,6 +356,8 @@ void Assembly::Terminate( BOOL signalProfiler )
         m_pClassLoader = NULL;
     }
 
+    FastInterlockDecrement((LONG*)&g_cAssemblies);
+
 #ifdef PROFILING_SUPPORTED
     if (CORProfilerTrackAssemblyLoads())
     {
index 5834757..9162bfd 100644 (file)
@@ -778,6 +778,16 @@ BOOL QCALLTYPE AssemblyNative::GetIsCollectible(QCall::AssemblyHandle pAssembly)
     return retVal;
 }
 
+extern volatile uint32_t g_cAssemblies;
+
+FCIMPL0(uint32_t, AssemblyNative::GetAssemblyCount)
+{
+    FCALL_CONTRACT;
+
+    return g_cAssemblies;
+}
+FCIMPLEND
+
 void QCALLTYPE AssemblyNative::GetModule(QCall::AssemblyHandle pAssembly, LPCWSTR wszFileName, QCall::ObjectHandleOnStack retModule)
 {
     QCALL_CONTRACT;
index 12d4ff8..898f131 100644 (file)
@@ -111,6 +111,8 @@ public:
 
     static BOOL QCALLTYPE GetIsCollectible(QCall::AssemblyHandle pAssembly);
 
+    static FCDECL0(uint32_t, GetAssemblyCount);
+
     //
     // PEFile QCalls
     // 
index fa616b8..b69b52e 100644 (file)
@@ -540,6 +540,7 @@ FCFuncEnd()
 FCFuncStart(gAssemblyFuncs)
     QCFuncElement("GetEntryAssemblyNative", AssemblyNative::GetEntryAssembly)
     QCFuncElement("GetExecutingAssemblyNative", AssemblyNative::GetExecutingAssembly)
+    FCFuncElement("GetAssemblyCount", AssemblyNative::GetAssemblyCount)
 FCFuncEnd()
 
 FCFuncStart(gAssemblyBuilderFuncs)