PerfCounterImpl.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #ifdef PERF_COUNTERS
  6. // Initialization order
  7. // AB AutoSystemInfo
  8. // AD PerfCounter
  9. // AE PerfCounterSet
  10. // AM Output/Configuration
  11. // AN MemProtectHeap
  12. // AP DbgHelpSymbolManager
  13. // AQ CFGLogger
  14. // AR LeakReport
  15. // AS JavascriptDispatch/RecyclerObjectDumper
  16. // AT HeapAllocator/RecyclerHeuristic
  17. // AU RecyclerWriteBarrierManager
  18. #pragma warning(disable:4075) // initializers put in unrecognized initialization area on purpose
  19. #pragma init_seg(".CRT$XCAD")
  20. #pragma warning(push)
  21. #pragma warning(disable:4838) // conversion from 'unsigned long' to 'LONG' requires a narrowing conversion
  22. #include "Microsoft-Scripting-Jscript9.InternalCounters.h"
  23. #pragma warning(pop)
  24. namespace PerfCounter
  25. {
  26. class Provider
  27. {
  28. public:
  29. static Provider InternalCounter;
  30. #ifdef ENABLE_COUNTER_NOTIFICATION_CALLBACK
  31. void SetNotificationCallBack(PERFLIBREQUEST pfn) { pfnNotificationCallBack = pfn; }
  32. #endif
  33. private:
  34. Provider(HANDLE& handle);
  35. ~Provider();
  36. bool IsInitialized() const { return isInitialized; }
  37. HANDLE GetHandler() { return handle; }
  38. #ifdef ENABLE_COUNTER_NOTIFICATION_CALLBACK
  39. PERFLIBREQUEST pfnNotificationCallBack;
  40. static ULONG WINAPI NotificationCallBack(ULONG RequestCode, PVOID Buffer, ULONG BufferSize);
  41. #endif
  42. HANDLE& handle;
  43. bool isInitialized;
  44. friend class InstanceBase;
  45. friend class Counter;
  46. };
  47. Provider Provider::InternalCounter(JS9InternalCounterProvider);
  48. #ifdef ENABLE_COUNTER_NOTIFICATION_CALLBACK
  49. ULONG WINAPI
  50. Provider::NotificationCallBack(ULONG RequestCode, PVOID Buffer, ULONG BufferSize)
  51. {
  52. if (Provider::InternalCounter.pfnNotificationCallBack != NULL)
  53. {
  54. return Provider::InternalCounter.pfnNotificationCallBack(RequestCode, Buffer, BufferSize);
  55. }
  56. return ERROR_SUCCESS;
  57. }
  58. #endif
  59. Provider::Provider(HANDLE& handle) :
  60. handle(handle), isInitialized(false)
  61. {
  62. PERFLIBREQUEST callback = NULL;
  63. #ifdef ENABLE_COUNTER_NOTIFICATION_CALLBACK
  64. callback = &NotificationCallBack;
  65. #endif
  66. if (ERROR_SUCCESS == CounterInitialize(callback, NULL, NULL, NULL))
  67. {
  68. isInitialized = true;
  69. }
  70. }
  71. Provider::~Provider()
  72. {
  73. if (IsInitialized())
  74. {
  75. CounterCleanup();
  76. }
  77. }
  78. InstanceBase::InstanceBase(Provider& provider, GUID const& guid) : provider(provider), guid(guid), instanceData(NULL)
  79. {
  80. }
  81. InstanceBase::~InstanceBase()
  82. {
  83. if (IsEnabled())
  84. {
  85. ::PerfDeleteInstance(provider.GetHandler(), instanceData);
  86. }
  87. }
  88. bool
  89. InstanceBase::IsProviderInitialized() const
  90. {
  91. return provider.IsInitialized();
  92. }
  93. bool
  94. InstanceBase::IsEnabled() const
  95. {
  96. return instanceData != NULL;
  97. }
  98. static const size_t GUID_LEN = 37; // includes null
  99. static const char16 s_wszObjectNamePrefix[] = _u("jscript9_perf_counter_");
  100. static const size_t OBJECT_NAME_LEN = GUID_LEN + _countof(s_wszObjectNamePrefix) + 11;
  101. static
  102. void GetSharedMemoryObjectName(__inout_ecount(OBJECT_NAME_LEN) char16 wszObjectName[OBJECT_NAME_LEN], DWORD pid, GUID const& guid)
  103. {
  104. swprintf_s(wszObjectName, OBJECT_NAME_LEN, _u("%s%d_%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
  105. s_wszObjectNamePrefix, pid,
  106. guid.Data1,
  107. guid.Data2,
  108. guid.Data3,
  109. guid.Data4[0], guid.Data4[1],
  110. guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
  111. }
  112. bool
  113. InstanceBase::Initialize(char16 const * wszInstanceName, DWORD processId)
  114. {
  115. if (provider.IsInitialized())
  116. {
  117. instanceData = PerfCreateInstance(provider.GetHandler(), &guid,
  118. wszInstanceName, processId);
  119. return instanceData != NULL;
  120. }
  121. return false;
  122. }
  123. DWORD *
  124. InstanceBase::InitializeSharedMemory(DWORD numCounter, HANDLE& handle)
  125. {
  126. Assert(!IsEnabled());
  127. DWORD size = numCounter * sizeof(DWORD);
  128. char16 wszObjectName[OBJECT_NAME_LEN];
  129. GetSharedMemoryObjectName(wszObjectName, GetCurrentProcessId(), guid);
  130. handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, wszObjectName);
  131. if (handle == NULL)
  132. {
  133. return NULL;
  134. }
  135. DWORD * data = (DWORD *)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, size);
  136. if (data == NULL)
  137. {
  138. CloseHandle(handle);
  139. handle = NULL;
  140. }
  141. return data;
  142. }
  143. DWORD *
  144. InstanceBase::OpenSharedMemory(__in_ecount(MAX_OBJECT_NAME_PREFIX) char16 const wszObjectNamePrefix[MAX_OBJECT_NAME_PREFIX],
  145. DWORD pid, DWORD numCounter, HANDLE& handle)
  146. {
  147. DWORD size = numCounter * sizeof(DWORD);
  148. char16 wszObjectName[OBJECT_NAME_LEN];
  149. GetSharedMemoryObjectName(wszObjectName, pid, guid);
  150. char16 wszObjectNameFull[MAX_OBJECT_NAME_PREFIX + OBJECT_NAME_LEN];
  151. swprintf_s(wszObjectNameFull, _u("%s\\%s"), wszObjectNamePrefix, wszObjectName);
  152. handle = ::OpenFileMapping(FILE_MAP_READ, FALSE, wszObjectNameFull);
  153. if (handle == NULL)
  154. {
  155. return NULL;
  156. }
  157. DWORD * data = (DWORD *)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, size);
  158. if (data == NULL)
  159. {
  160. CloseHandle(handle);
  161. handle = NULL;
  162. }
  163. return data;
  164. }
  165. void
  166. InstanceBase::UninitializeSharedMemory(DWORD * data, HANDLE handle)
  167. {
  168. UnmapViewOfFile(data);
  169. CloseHandle(handle);
  170. }
  171. void
  172. Counter::Initialize(InstanceBase& instance, DWORD id, DWORD * count)
  173. {
  174. this->count = count;
  175. if (instance.IsEnabled())
  176. {
  177. ::PerfSetCounterRefValue(instance.GetProvider().GetHandler(), instance.GetData(), id, count);
  178. }
  179. }
  180. void
  181. Counter::Uninitialize(InstanceBase& instance, DWORD id)
  182. {
  183. if (instance.IsEnabled())
  184. {
  185. ::PerfSetCounterRefValue(instance.GetProvider().GetHandler(), instance.GetData(), id, NULL);
  186. }
  187. }
  188. #define DEFINE_PAGE_ALLOCATOR_COUNTER_ID(type) JS9InternalCounter_PageAllocCounterSet_##type##ReservedSize,
  189. static uint ReservedCounterId[PageAllocatorType_Max + 1] =
  190. {
  191. PAGE_ALLOCATOR_TYPE(DEFINE_PAGE_ALLOCATOR_COUNTER_ID)
  192. JS9InternalCounter_PageAllocCounterSet_TotalReservedSize
  193. };
  194. #undef DEFINE_PAGE_ALLOCATOR_COUNTER_ID
  195. #define DEFINE_PAGE_ALLOCATOR_COUNTER_ID(type) JS9InternalCounter_PageAllocCounterSet_##type##CommittedSize,
  196. static uint CommittedCounterId[PageAllocatorType_Max + 1] =
  197. {
  198. PAGE_ALLOCATOR_TYPE(DEFINE_PAGE_ALLOCATOR_COUNTER_ID)
  199. JS9InternalCounter_PageAllocCounterSet_TotalCommittedSize
  200. };
  201. #undef DEFINE_PAGE_ALLOCATOR_COUNTER_ID
  202. #define DEFINE_PAGE_ALLOCATOR_COUNTER_ID(type) JS9InternalCounter_PageAllocCounterSet_##type##UsedSize,
  203. static uint UsedCounterId[PageAllocatorType_Max + 1] =
  204. {
  205. PAGE_ALLOCATOR_TYPE(DEFINE_PAGE_ALLOCATOR_COUNTER_ID)
  206. JS9InternalCounter_PageAllocCounterSet_TotalUsedSize
  207. };
  208. #undef DEFINE_PAGE_ALLOCATOR_COUNTER_ID
  209. uint
  210. PageAllocatorCounterSetDefinition::GetReservedCounterId(PageAllocatorType type)
  211. {
  212. return ReservedCounterId[type];
  213. }
  214. uint
  215. PageAllocatorCounterSetDefinition::GetCommittedCounterId(PageAllocatorType type)
  216. {
  217. return CommittedCounterId[type];
  218. }
  219. uint
  220. PageAllocatorCounterSetDefinition::GetUsedCounterId(PageAllocatorType type)
  221. {
  222. return UsedCounterId[type];
  223. }
  224. GUID const& PageAllocatorCounterSetDefinition::GetGuid() { return JS9InternalCounter_PageAllocCounterSetGuid; }
  225. Provider& PageAllocatorCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  226. GUID const& BasicCounterSetDefinition::GetGuid() { return JS9InternalCounter_BasicCounterSetGuid; }
  227. Provider& BasicCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  228. GUID const& CodeCounterSetDefinition::GetGuid() { return JS9InternalCounter_CodeCounterSetGuid; }
  229. Provider& CodeCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  230. #ifdef HEAP_PERF_COUNTERS
  231. GUID const& HeapCounterSetDefinition::GetGuid() { return JS9InternalCounter_HeapCounterSetGuid; }
  232. Provider& HeapCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  233. #endif
  234. #ifdef RECYCLER_PERF_COUNTERS
  235. GUID const& RecyclerCounterSetDefinition::GetGuid() { return JS9InternalCounter_RecyclerCounterSetGuid; }
  236. Provider& RecyclerCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  237. #endif
  238. #ifdef PROFILE_RECYCLER_ALLOC
  239. GUID const& RecyclerTrackerCounterSetDefinition::GetGuid() { return JS9InternalCounter_RecyclerTrackerCounterSetGuid; }
  240. Provider& RecyclerTrackerCounterSetDefinition::GetProvider() { return Provider::InternalCounter; }
  241. #define DEFINE_RECYCLER_TRACKER_PERF_COUNTER_INDEX(type) \
  242. uint const RecyclerTrackerCounterSetDefinition::##type##CounterIndex = JS9InternalCounter_RecyclerTrackerCounterSet_##type##Count; \
  243. uint const RecyclerTrackerCounterSetDefinition::##type##SizeCounterIndex = JS9InternalCounter_RecyclerTrackerCounterSet_##type##Size;
  244. #define DEFINE_RECYCLER_TRACKER_ARRAY_PERF_COUNTER_INDEX(type) \
  245. uint const RecyclerTrackerCounterSetDefinition::##type##ArrayCounterIndex = JS9InternalCounter_RecyclerTrackerCounterSet_##type##ArrayCount; \
  246. uint const RecyclerTrackerCounterSetDefinition::##type##ArraySizeCounterIndex = JS9InternalCounter_RecyclerTrackerCounterSet_##type##ArraySize;
  247. #define DEFINE_RECYCLER_TRACKER_WEAKREF_PERF_COUNTER_INDEX(type) \
  248. uint const RecyclerTrackerCounterSetDefinition::##type##WeakRefCounterIndex = JS9InternalCounter_RecyclerTrackerCounterSet_##type##WeakRefCount;
  249. RECYCLER_TRACKER_PERF_COUNTER_TYPE(DEFINE_RECYCLER_TRACKER_PERF_COUNTER_INDEX);
  250. RECYCLER_TRACKER_ARRAY_PERF_COUNTER_TYPE(DEFINE_RECYCLER_TRACKER_ARRAY_PERF_COUNTER_INDEX);
  251. RECYCLER_TRACKER_WEAKREF_PERF_COUNTER_TYPE(DEFINE_RECYCLER_TRACKER_WEAKREF_PERF_COUNTER_INDEX);
  252. #endif
  253. };
  254. #endif