From: Sean Gillespie Date: Tue, 30 Jan 2018 22:27:16 +0000 (-0800) Subject: [Local GC] FEATURE_EVENT_TRACE 4/n: Event ports for all GC-keyword events (#16031) X-Git-Tag: accepted/tizen/unified/20190422.045933~3155 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=338b9fa5c5216bdaa4f6c66fc36aea7bb19276b7;p=platform%2Fupstream%2Fcoreclr.git [Local GC] FEATURE_EVENT_TRACE 4/n: Event ports for all GC-keyword events (#16031) * [Local GC] Event ports: GCStart and GCGenerationRange * [Local GC] Event ports: GCEnd * [Local GC] Event ports: GCHeapStats * [Local GC] Event ports: GCCreateSegment * [Local GC] Event ports: GCFreeSegment * Event ports: GCCreateConcurrentThread and GCTerminateConcurrentThread * [Local GC] Event ports: GCTriggered * [Local GC] Event ports: GCMarkWithType * [Local GC] Event ports: GCJoin_V2 * [Local GC] Event ports: GCGlobalHeapHistory_V2 * [Local GC] Event ports: GCAllocationTick_V3 * [Local GC] Event ports: GCAllocationTick_V1 * [Local GC] Event porting: PinObjectAtGCTime * one last merge conflict --- diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 2b31388..d6ab65a 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -816,7 +816,7 @@ public: inline void fire_event (int heap, join_time time, join_type type, int join_id) { - FireEtwGCJoin_V2(heap, time, type, GetClrInstanceId(), join_id); + FIRE_EVENT(GCJoin_V2, heap, time, type, join_id); } void join (gc_heap* gch, int join_id) @@ -3028,13 +3028,12 @@ void gc_heap::fire_pevents() settings.record (&gc_data_global); gc_data_global.print(); - FireEtwGCGlobalHeapHistory_V2(gc_data_global.final_youngest_desired, + FIRE_EVENT(GCGlobalHeapHistory_V2, gc_data_global.final_youngest_desired, gc_data_global.num_heaps, gc_data_global.condemned_generation, gc_data_global.gen0_reduction_count, gc_data_global.reason, gc_data_global.global_mechanims_p, - GetClrInstanceId(), gc_data_global.pause_mode, gc_data_global.mem_pressure); @@ -4677,10 +4676,9 @@ gc_heap::soh_get_segment_to_expand() } #endif //BACKGROUND_GC - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(result), - (size_t)(heap_segment_reserved (result) - heap_segment_mem(result)), - ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP, - GetClrInstanceId()); + FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(result), + (size_t)(heap_segment_reserved (result) - heap_segment_mem(result)), + gc_etw_segment_small_object_heap); } get_gc_data_per_heap()->set_mechanism (gc_heap_expand, (result ? expand_new_seg : expand_no_memory)); @@ -4846,7 +4844,7 @@ gc_heap::get_segment (size_t size, BOOL loh_p) void release_segment (heap_segment* sg) { ptrdiff_t delta = 0; - FireEtwGCFreeSegment_V1((size_t)heap_segment_mem(sg), GetClrInstanceId()); + FIRE_EVENT(GCFreeSegment_V1, heap_segment_mem(sg)); virtual_free (sg, (uint8_t*)heap_segment_reserved (sg)-(uint8_t*)sg); } @@ -4867,7 +4865,7 @@ heap_segment* gc_heap::get_segment_for_loh (size_t size #endif //MULTIPLE_HEAPS res->flags |= heap_segment_flags_loh; - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, GetClrInstanceId()); + FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), gc_etw_segment_large_object_heap); GCToEEInterface::DiagUpdateGenerationBounds(); @@ -7837,7 +7835,7 @@ BOOL gc_heap::insert_ro_segment (heap_segment* seg) set_ro_segment_in_range (seg); } - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg), (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), ETW::GCLog::ETW_GC_INFO::READ_ONLY_HEAP, GetClrInstanceId()); + FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(seg), (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), gc_etw_segment_read_only_heap); leave_spin_lock (&gc_heap::gc_lock); return TRUE; @@ -10448,10 +10446,9 @@ gc_heap::init_gc_heap (int h_number) if (!seg) return 0; - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg), - (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), - ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP, - GetClrInstanceId()); + FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(seg), + (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), + gc_etw_segment_small_object_heap); #ifdef SEG_MAPPING_TABLE seg_mapping_table_add_segment (seg, __this); @@ -10514,10 +10511,9 @@ gc_heap::init_gc_heap (int h_number) return 0; lseg->flags |= heap_segment_flags_loh; - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(lseg), - (size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)), - ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, - GetClrInstanceId()); + FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(lseg), + (size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)), + gc_etw_segment_large_object_heap); #ifdef SEG_MAPPING_TABLE seg_mapping_table_add_segment (lseg, __this); @@ -13229,9 +13225,8 @@ int gc_heap::try_allocate_more_space (alloc_context* acontext, size_t size, if (etw_allocation_running_amount[etw_allocation_index] > etw_allocation_tick) { #ifdef FEATURE_REDHAWK - FireEtwGCAllocationTick_V1((uint32_t)etw_allocation_running_amount[etw_allocation_index], - ((gen_number == 0) ? ETW::GCLog::ETW_GC_INFO::AllocationSmall : ETW::GCLog::ETW_GC_INFO::AllocationLarge), - GetClrInstanceId()); + FIRE_EVENT(GCAllocationTick_V1, (uint32_t)etw_allocation_running_amount[etw_allocation_index], + (gen_number == 0) ? gc_etw_alloc_soh : gc_etw_alloc_loh); #else // Unfortunately some of the ETW macros do not check whether the ETW feature is enabled. // The ones that do are much less efficient. @@ -19163,7 +19158,7 @@ void gc_heap::get_memory_info (uint32_t* memory_load, void fire_mark_event (int heap_num, int root_type, size_t bytes_marked) { dprintf (DT_LOG_0, ("-----------[%d]mark %d: %Id", heap_num, root_type, bytes_marked)); - FireEtwGCMarkWithType (heap_num, GetClrInstanceId(), root_type, bytes_marked); + FIRE_EVENT(GCMarkWithType, heap_num, root_type, bytes_marked); } //returns TRUE is an overflow happened. @@ -26702,7 +26697,7 @@ BOOL gc_heap::prepare_bgc_thread(gc_heap* gh) gh->bgc_threads_timeout_cs.Leave(); if(thread_created) - FireEtwGCCreateConcurrentThread_V1(GetClrInstanceId()); + FIRE_EVENT(GCCreateConcurrentThread_V1); return success; } @@ -27044,7 +27039,7 @@ void gc_heap::bgc_thread_function() //gc_heap::disable_preemptive (current_thread, TRUE); } - FireEtwGCTerminateConcurrentThread_V1(GetClrInstanceId()); + FIRE_EVENT(GCTerminateConcurrentThread_V1); dprintf (3, ("bgc_thread thread exiting")); return; @@ -35081,7 +35076,7 @@ GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason) // We want to get a stack from the user thread that triggered the GC // instead of on the GC thread which is the case for Server GC. // But we are doing it for Workstation GC as well to be uniform. - FireEtwGCTriggered((int) reason, GetClrInstanceId()); + FIRE_EVENT(GCTriggered, static_cast(reason)); #ifdef MULTIPLE_HEAPS GcCondemnedGeneration = condemned_generation_number; diff --git a/src/gc/gc.h b/src/gc/gc.h index e16fccb..6641f0b 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -70,6 +70,29 @@ enum gc_reason reason_max }; +// Types of GCs, emitted by the GCStart ETW event. +enum gc_etw_type +{ + gc_etw_type_ngc = 0, + gc_etw_type_bgc = 1, + gc_etw_type_fgc = 2 +}; + +// Types of segments, emitted by the GCCreateSegment ETW event. +enum gc_etw_segment_type +{ + gc_etw_segment_small_object_heap = 0, + gc_etw_segment_large_object_heap = 1, + gc_etw_segment_read_only_heap = 2 +}; + +// Types of allocations, emitted by the GCAllocationTick ETW event. +enum gc_etw_alloc_kind +{ + gc_etw_alloc_soh = 0, + gc_etw_alloc_loh = 1 +}; + /* forward declerations */ class CObjectHeader; class Object; diff --git a/src/gc/gcee.cpp b/src/gc/gcee.cpp index c5cc88b..358b40c 100644 --- a/src/gc/gcee.cpp +++ b/src/gc/gcee.cpp @@ -77,7 +77,6 @@ void GCHeap::UpdatePreGCCounters() #endif //ENABLE_PERF_COUNTERS -#ifdef FEATURE_EVENT_TRACE #ifdef MULTIPLE_HEAPS //take the first heap.... gc_mechanisms *pSettings = &gc_heap::g_heaps[0]->settings; @@ -85,27 +84,28 @@ void GCHeap::UpdatePreGCCounters() gc_mechanisms *pSettings = &gc_heap::settings; #endif //MULTIPLE_HEAPS - ETW::GCLog::ETW_GC_INFO Info; - - Info.GCStart.Count = (uint32_t)pSettings->gc_index; - Info.GCStart.Depth = (uint32_t)pSettings->condemned_generation; - Info.GCStart.Reason = (ETW::GCLog::ETW_GC_INFO::GC_REASON)((int)(pSettings->reason)); - - Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_NGC; + uint32_t count = (uint32_t)pSettings->gc_index; + uint32_t depth = (uint32_t)pSettings->condemned_generation; + uint32_t reason = (uint32_t)pSettings->reason; + gc_etw_type type = gc_etw_type_ngc; if (pSettings->concurrent) { - Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_BGC; + type = gc_etw_type_bgc; } #ifdef BACKGROUND_GC - else if (Info.GCStart.Depth < max_generation) + else if (depth < max_generation && pSettings->background_p) { - if (pSettings->background_p) - Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_FGC; + type = gc_etw_type_fgc; } -#endif //BACKGROUND_GC +#endif // BACKGROUND_GC - ETW::GCLog::FireGcStartAndGenerationRanges(&Info); -#endif // FEATURE_EVENT_TRACE + FIRE_EVENT(GCStart_V2, count, depth, reason, static_cast(type)); + g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) + { + uint64_t range = static_cast(rangeEnd - rangeStart); + uint64_t rangeReserved = static_cast(rangeEndReserved - rangeStart); + FIRE_EVENT(GCGenerationRange, generation, rangeStart, range, rangeReserved); + }, nullptr); } void GCHeap::UpdatePostGCCounters() @@ -195,50 +195,34 @@ void GCHeap::UpdatePostGCCounters() #endif //ENABLE_PERF_COUNTERS || FEATURE_EVENT_TRACE #ifdef FEATURE_EVENT_TRACE - ETW::GCLog::ETW_GC_INFO Info; - - Info.GCEnd.Depth = condemned_gen; - Info.GCEnd.Count = (uint32_t)pSettings->gc_index; - ETW::GCLog::FireGcEndAndGenerationRanges(Info.GCEnd.Count, Info.GCEnd.Depth); - - ETW::GCLog::ETW_GC_INFO HeapInfo; - ZeroMemory(&HeapInfo, sizeof(HeapInfo)); - - for (int gen_index = 0; gen_index <= (max_generation+1); gen_index++) + g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) { - HeapInfo.HeapStats.GenInfo[gen_index].GenerationSize = g_GenerationSizes[gen_index]; - HeapInfo.HeapStats.GenInfo[gen_index].TotalPromotedSize = g_GenerationPromotedSizes[gen_index]; - } + uint64_t range = static_cast(rangeEnd - rangeStart); + uint64_t rangeReserved = static_cast(rangeEndReserved - rangeStart); + FIRE_EVENT(GCGenerationRange, generation, rangeStart, range, rangeReserved); + }, nullptr); + + FIRE_EVENT(GCEnd_V1, static_cast(pSettings->gc_index), condemned_gen); #ifdef SIMPLE_DPRINTF dprintf (2, ("GC#%d: 0: %Id(%Id); 1: %Id(%Id); 2: %Id(%Id); 3: %Id(%Id)", - Info.GCEnd.Count, - HeapInfo.HeapStats.GenInfo[0].GenerationSize, - HeapInfo.HeapStats.GenInfo[0].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[1].GenerationSize, - HeapInfo.HeapStats.GenInfo[1].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[2].GenerationSize, - HeapInfo.HeapStats.GenInfo[2].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[3].GenerationSize, - HeapInfo.HeapStats.GenInfo[3].TotalPromotedSize)); + pSettings->gc_index, + g_GenerationSizes[0], g_GenerationPromotedSizes[0], + g_GenerationSizes[1], g_GenerationPromotedSizes[1], + g_GenerationSizes[2], g_GenerationPromotedSizes[2], + g_GenerationSizes[3], g_GenerationPromotedSizes[3])); #endif //SIMPLE_DPRINTF - HeapInfo.HeapStats.FinalizationPromotedSize = promoted_finalization_mem; - HeapInfo.HeapStats.FinalizationPromotedCount = GetFinalizablePromotedCount(); - HeapInfo.HeapStats.PinnedObjectCount = (uint32_t)total_num_pinned_objects; - HeapInfo.HeapStats.SinkBlockCount = total_num_sync_blocks; - HeapInfo.HeapStats.GCHandleCount = (uint32_t)total_num_gc_handles; - - FireEtwGCHeapStats_V1(HeapInfo.HeapStats.GenInfo[0].GenerationSize, HeapInfo.HeapStats.GenInfo[0].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[1].GenerationSize, HeapInfo.HeapStats.GenInfo[1].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[2].GenerationSize, HeapInfo.HeapStats.GenInfo[2].TotalPromotedSize, - HeapInfo.HeapStats.GenInfo[3].GenerationSize, HeapInfo.HeapStats.GenInfo[3].TotalPromotedSize, - HeapInfo.HeapStats.FinalizationPromotedSize, - HeapInfo.HeapStats.FinalizationPromotedCount, - HeapInfo.HeapStats.PinnedObjectCount, - HeapInfo.HeapStats.SinkBlockCount, - HeapInfo.HeapStats.GCHandleCount, - GetClrInstanceId()); + FIRE_EVENT(GCHeapStats_V1, + g_GenerationSizes[0], g_GenerationPromotedSizes[0], + g_GenerationSizes[1], g_GenerationPromotedSizes[1], + g_GenerationSizes[2], g_GenerationPromotedSizes[2], + g_GenerationSizes[3], g_GenerationPromotedSizes[3], + promoted_finalization_mem, + GetFinalizablePromotedCount(), + static_cast(total_num_pinned_objects), + total_num_sync_blocks, + static_cast(total_num_gc_handles)); #endif // FEATURE_EVENT_TRACE #if defined(ENABLE_PERF_COUNTERS) @@ -458,70 +442,13 @@ bool GCHeap::IsConcurrentGCInProgress() #ifdef FEATURE_EVENT_TRACE void gc_heap::fire_etw_allocation_event (size_t allocation_amount, int gen_number, uint8_t* object_address) { - void * typeId = nullptr; - const WCHAR * name = nullptr; -#ifdef FEATURE_REDHAWK - typeId = RedhawkGCInterface::GetLastAllocEEType(); -#else - InlineSString strTypeName; - - EX_TRY - { - TypeHandle th = GCToEEInterface::GetThread()->GetTHAllocContextObj(); - - if (th != 0) - { - th.GetName(strTypeName); - name = strTypeName.GetUnicode(); - typeId = th.GetMethodTable(); - } - } - EX_CATCH {} - EX_END_CATCH(SwallowAllExceptions) -#endif - - if (typeId != nullptr) - { - FireEtwGCAllocationTick_V3((uint32_t)allocation_amount, - ((gen_number == 0) ? ETW::GCLog::ETW_GC_INFO::AllocationSmall : ETW::GCLog::ETW_GC_INFO::AllocationLarge), - GetClrInstanceId(), - allocation_amount, - typeId, - name, - heap_number, - object_address - ); - } + gc_etw_alloc_kind kind = gen_number == 0 ? gc_etw_alloc_soh : gc_etw_alloc_loh; + FIRE_EVENT(GCAllocationTick_V3, static_cast(allocation_amount), kind, heap_number, object_address); } + void gc_heap::fire_etw_pin_object_event (uint8_t* object, uint8_t** ppObject) { -#ifdef FEATURE_REDHAWK - UNREFERENCED_PARAMETER(object); - UNREFERENCED_PARAMETER(ppObject); -#else - Object* obj = (Object*)object; - - InlineSString strTypeName; - - EX_TRY - { - FAULT_NOT_FATAL(); - - TypeHandle th = obj->GetGCSafeTypeHandleIfPossible(); - if(th != NULL) - { - th.GetName(strTypeName); - } - - FireEtwPinObjectAtGCTime(ppObject, - object, - obj->GetSize(), - strTypeName.GetUnicode(), - GetClrInstanceId()); - } - EX_CATCH {} - EX_END_CATCH(SwallowAllExceptions) -#endif // FEATURE_REDHAWK + FIRE_EVENT(PinObjectAtGCTime, object, ppObject); } #endif // FEATURE_EVENT_TRACE @@ -600,22 +527,18 @@ void GCHeap::DiagTraceGCSegments() for (seg = generation_start_segment (h->generation_of (max_generation)); seg != 0; seg = heap_segment_next(seg)) { - ETW::GCLog::ETW_GC_INFO Info; - Info.GCCreateSegment.Address = (size_t)heap_segment_mem(seg); - Info.GCCreateSegment.Size = (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)); - Info.GCCreateSegment.Type = (heap_segment_read_only_p (seg) ? - ETW::GCLog::ETW_GC_INFO::READ_ONLY_HEAP : - ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP); - FireEtwGCCreateSegment_V1(Info.GCCreateSegment.Address, Info.GCCreateSegment.Size, Info.GCCreateSegment.Type, GetClrInstanceId()); + uint8_t* address = heap_segment_mem (seg); + size_t size = heap_segment_reserved (seg) - heap_segment_mem (seg); + gc_etw_segment_type type = heap_segment_read_only_p (seg) ? gc_etw_segment_read_only_heap : gc_etw_segment_small_object_heap; + FIRE_EVENT(GCCreateSegment_V1, address, size, static_cast(type)); } // large obj segments for (seg = generation_start_segment (h->generation_of (max_generation+1)); seg != 0; seg = heap_segment_next(seg)) { - FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg), - (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), - ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, - GetClrInstanceId()); + uint8_t* address = heap_segment_mem (seg); + size_t size = heap_segment_reserved (seg) - heap_segment_mem (seg); + FIRE_EVENT(GCCreateSegment_V1, address, size, static_cast(gc_etw_segment_large_object_heap)); } } #endif // FEATURE_EVENT_TRACE @@ -623,9 +546,7 @@ void GCHeap::DiagTraceGCSegments() void GCHeap::DiagDescrGenerations (gen_walk_fn fn, void *context) { -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) pGenGCHeap->descr_generations_to_profiler(fn, context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) } segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) diff --git a/src/gc/gcevents.h b/src/gc/gcevents.h index 974348a..f0f6ff6 100644 --- a/src/gc/gcevents.h +++ b/src/gc/gcevents.h @@ -9,9 +9,25 @@ #define DYNAMIC_EVENT(name, level, keyword, ...) #endif // DYNAMIC_EVENT +KNOWN_EVENT(GCStart_V2, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCEnd_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCGenerationRange, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHeapSurvivalAndMovement) +KNOWN_EVENT(GCHeapStats_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCCreateSegment_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCFreeSegment_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCCreateConcurrentThread_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCTerminateConcurrentThread_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCTriggered, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCMarkWithType, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCJoin_V2, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC) +KNOWN_EVENT(GCGlobalHeapHistory_V2, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) +KNOWN_EVENT(GCAllocationTick_V1, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC) +KNOWN_EVENT(GCAllocationTick_V3, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC) +KNOWN_EVENT(PinObjectAtGCTime, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC) +KNOWN_EVENT(GCPerHeapHistory_V3, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC) + KNOWN_EVENT(SetGCHandle, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHandle) KNOWN_EVENT(DestroyGCHandle, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHandle) -KNOWN_EVENT(GCPerHeapHistory_V3, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCPrivate) KNOWN_EVENT(BGCBegin, GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCPrivate) KNOWN_EVENT(BGC1stNonConEnd, GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCPrivate) diff --git a/src/gc/gcinterface.ee.h b/src/gc/gcinterface.ee.h index a153c1d..a79043e 100644 --- a/src/gc/gcinterface.ee.h +++ b/src/gc/gcinterface.ee.h @@ -26,6 +26,71 @@ public: void* payload, uint32_t payloadSize) = 0; virtual + void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type) = 0; + + virtual + void FireGCEnd_V1(uint32_t count, uint32_t depth) = 0; + + virtual + void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength) = 0; + + virtual + void FireGCHeapStats_V1( + uint64_t generationSize0, + uint64_t totalPromotedSize0, + uint64_t generationSize1, + uint64_t totalPromotedSize1, + uint64_t generationSize2, + uint64_t totalPromotedSize2, + uint64_t generationSize3, + uint64_t totalPromotedSize3, + uint64_t finalizationPromotedSize, + uint64_t finalizationPromotedCount, + uint32_t pinnedObjectCount, + uint32_t sinkBlockCount, + uint32_t gcHandleCount) = 0; + + virtual + void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type) = 0; + + virtual + void FireGCFreeSegment_V1(void* address) = 0; + + virtual + void FireGCCreateConcurrentThread_V1() = 0; + + virtual + void FireGCTerminateConcurrentThread_V1() = 0; + + virtual + void FireGCTriggered(uint32_t reason) = 0; + + virtual + void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes) = 0; + + virtual + void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId) = 0; + + virtual + void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired, + int32_t numHeaps, + uint32_t condemnedGeneration, + uint32_t gen0reductionCount, + uint32_t reason, + uint32_t globalMechanisms, + uint32_t pauseMode, + uint32_t memoryPressure) = 0; + + virtual + void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind) = 0; + + virtual + void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress) = 0; + + virtual + void FirePinObjectAtGCTime(void* object, uint8_t** ppObject) = 0; + + virtual void FireGCPerHeapHistory_V3(void *freeListAllocated, void *freeListRejected, void *endOfSegAllocated, diff --git a/src/inc/eventtrace.h b/src/inc/eventtrace.h index 765249e..1564c94 100644 --- a/src/inc/eventtrace.h +++ b/src/inc/eventtrace.h @@ -325,14 +325,7 @@ namespace ETW static BOOL ShouldTrackMovementForEtw(); static HRESULT ForceGCForDiagnostics(); static VOID ForceGC(LONGLONG l64ClientSequenceNumber); - static VOID FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo); - static VOID FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth); - static VOID FireSingleGenerationRangeEvent( - void * /* context */, - int generation, - BYTE * rangeStart, - BYTE * rangeEnd, - BYTE * rangeEndReserved); + static VOID FireGcStart(ETW_GC_INFO * pGcInfo); static VOID RootReference( LPVOID pvHandle, Object * pRootedNode, diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index 533a3bc..5fb63c9 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -874,15 +874,14 @@ VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) //--------------------------------------------------------------------------------------- // // Helper to fire the GCStart event. Figures out which version of GCStart to fire, and -// includes the client sequence number, if available. Also logs the generation range -// events. +// includes the client sequence number, if available. // // Arguments: // pGcInfo - ETW_GC_INFO containing details from GC about this collection // // static -VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) +VOID ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo) { LIMITED_METHOD_CONTRACT; @@ -902,81 +901,8 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) } FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog); - - // Fire an event per range per generation - IGCHeap *hp = GCHeapUtilities::GetGCHeap(); - hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */); - } -} - - -//--------------------------------------------------------------------------------------- -// -// Helper to fire the GCEnd event and the generation range events. -// -// Arguments: -// Count - (matching Count from corresponding GCStart event0 -// Depth - (matching Depth from corresponding GCStart event0 -// -// - -// static -VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth) -{ - LIMITED_METHOD_CONTRACT; - - if (ETW_TRACING_CATEGORY_ENABLED( - MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_GC_KEYWORD)) - { - // Fire an event per range per generation - IGCHeap *hp = GCHeapUtilities::GetGCHeap(); - hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */); - - // GCEnd - FireEtwGCEnd_V1(Count, Depth, GetClrInstanceId()); } } - -//--------------------------------------------------------------------------------------- -// -// Callback made by GC when we call GCHeapUtilities::DiagDescrGenerations(). This is -// called once per range per generation, and results in a single ETW event per range per -// generation. -// -// Arguments: -// context - unused -// generation - Generation number -// rangeStart - Where does this range start? -// rangeEnd - How large is the used portion of this range? -// rangeEndReserved - How large is the reserved portion of this range? -// - -// static -VOID ETW::GCLog::FireSingleGenerationRangeEvent( - void * /* context */, - int generation, - BYTE * rangeStart, - BYTE * rangeEnd, - BYTE * rangeEndReserved) -{ - CONTRACT_VOID - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; // can be called even on GC threads - PRECONDITION(0 <= generation && generation <= 3); - PRECONDITION(CheckPointer(rangeStart)); - PRECONDITION(CheckPointer(rangeEnd)); - PRECONDITION(CheckPointer(rangeEndReserved)); - } - CONTRACT_END; - - FireEtwGCGenerationRange((BYTE) generation, rangeStart, rangeEnd - rangeStart, rangeEndReserved - rangeStart, GetClrInstanceId()); - - RETURN; -} //--------------------------------------------------------------------------------------- // diff --git a/src/vm/gctoclreventsink.cpp b/src/vm/gctoclreventsink.cpp index 3842bab..50bd263 100644 --- a/src/vm/gctoclreventsink.cpp +++ b/src/vm/gctoclreventsink.cpp @@ -4,6 +4,7 @@ #include "common.h" #include "gctoclreventsink.h" +#include "eventtrace.h" GCToCLREventSink g_gcToClrEventSink; @@ -22,6 +23,188 @@ void GCToCLREventSink::FireDynamicEvent(const char* eventName, void* payload, ui FireEtwGCDynamicEvent(wideEventName, payloadSize, (const BYTE*)payload, GetClrInstanceId()); } +void GCToCLREventSink::FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type) +{ + LIMITED_METHOD_CONTRACT; + + ETW::GCLog::ETW_GC_INFO gcStartInfo; + gcStartInfo.GCStart.Count = count; + gcStartInfo.GCStart.Depth = depth; + gcStartInfo.GCStart.Reason = static_cast(reason); + gcStartInfo.GCStart.Type = static_cast(type); + ETW::GCLog::FireGcStart(&gcStartInfo); +} + +void GCToCLREventSink::FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCGenerationRange(generation, rangeStart, rangeUsedLength, rangeReservedLength, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCEnd_V1(uint32_t count, uint32_t depth) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCEnd_V1(count, depth, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCHeapStats_V1( + uint64_t generationSize0, + uint64_t totalPromotedSize0, + uint64_t generationSize1, + uint64_t totalPromotedSize1, + uint64_t generationSize2, + uint64_t totalPromotedSize2, + uint64_t generationSize3, + uint64_t totalPromotedSize3, + uint64_t finalizationPromotedSize, + uint64_t finalizationPromotedCount, + uint32_t pinnedObjectCount, + uint32_t sinkBlockCount, + uint32_t gcHandleCount) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCHeapStats_V1(generationSize0, totalPromotedSize0, generationSize1, totalPromotedSize1, + generationSize2, totalPromotedSize2, generationSize3, totalPromotedSize3, + finalizationPromotedSize, finalizationPromotedCount, pinnedObjectCount, + sinkBlockCount, gcHandleCount, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCCreateSegment_V1(void* address, size_t size, uint32_t type) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCCreateSegment_V1((uint64_t)address, static_cast(size), type, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCFreeSegment_V1(void* address) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCFreeSegment_V1((uint64_t)address, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCCreateConcurrentThread_V1() +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCCreateConcurrentThread_V1(GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCTerminateConcurrentThread_V1() +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCTerminateConcurrentThread_V1(GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCTriggered(uint32_t reason) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCTriggered(reason, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCMarkWithType(heapNum, GetClrInstanceId(), type, bytes); +} + +void GCToCLREventSink::FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCJoin_V2(heap, joinTime, joinType, GetClrInstanceId(), joinId); +} + +void GCToCLREventSink::FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired, + int32_t numHeaps, + uint32_t condemnedGeneration, + uint32_t gen0reductionCount, + uint32_t reason, + uint32_t globalMechanisms, + uint32_t pauseMode, + uint32_t memoryPressure) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCGlobalHeapHistory_V2(finalYoungestDesired, numHeaps, condemnedGeneration, gen0reductionCount, reason, + globalMechanisms, GetClrInstanceId(), pauseMode, memoryPressure); +} + +void GCToCLREventSink::FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind) +{ + LIMITED_METHOD_CONTRACT; + + FireEtwGCAllocationTick_V1(allocationAmount, allocationKind, GetClrInstanceId()); +} + +void GCToCLREventSink::FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress) +{ + LIMITED_METHOD_CONTRACT; + + void * typeId = nullptr; + const WCHAR * name = nullptr; + InlineSString strTypeName; + EX_TRY + { + TypeHandle th = GetThread()->GetTHAllocContextObj(); + + if (th != 0) + { + th.GetName(strTypeName); + name = strTypeName.GetUnicode(); + typeId = th.GetMethodTable(); + } + } + EX_CATCH {} + EX_END_CATCH(SwallowAllExceptions) + + if (typeId != nullptr) + { + FireEtwGCAllocationTick_V3(static_cast(allocationAmount), + allocationKind, + GetClrInstanceId(), + allocationAmount, + typeId, + name, + heapIndex, + objectAddress); + } +} + +void GCToCLREventSink::FirePinObjectAtGCTime(void* object, uint8_t** ppObject) +{ + LIMITED_METHOD_CONTRACT; + + Object* obj = (Object*)object; + + InlineSString strTypeName; + + EX_TRY + { + FAULT_NOT_FATAL(); + + TypeHandle th = obj->GetGCSafeTypeHandleIfPossible(); + if(th != NULL) + { + th.GetName(strTypeName); + } + + FireEtwPinObjectAtGCTime(ppObject, + object, + obj->GetSize(), + strTypeName.GetUnicode(), + GetClrInstanceId()); + } + EX_CATCH {} + EX_END_CATCH(SwallowAllExceptions) +} + void GCToCLREventSink::FireGCPerHeapHistory_V3(void *freeListAllocated, void *freeListRejected, void *endOfSegAllocated, diff --git a/src/vm/gctoclreventsink.h b/src/vm/gctoclreventsink.h index ca3a219..e34cac4 100644 --- a/src/vm/gctoclreventsink.h +++ b/src/vm/gctoclreventsink.h @@ -11,7 +11,40 @@ class GCToCLREventSink : public IGCToCLREventSink { public: void FireDynamicEvent(const char* eventName, void* payload, uint32_t payloadSize); - + void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type); + void FireGCEnd_V1(uint32_t count, uint32_t depth); + void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength); + void FireGCHeapStats_V1(uint64_t generationSize0, + uint64_t totalPromotedSize0, + uint64_t generationSize1, + uint64_t totalPromotedSize1, + uint64_t generationSize2, + uint64_t totalPromotedSize2, + uint64_t generationSize3, + uint64_t totalPromotedSize3, + uint64_t finalizationPromotedSize, + uint64_t finalizationPromotedCount, + uint32_t pinnedObjectCount, + uint32_t sinkBlockCount, + uint32_t gcHandleCount); + void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type); + void FireGCFreeSegment_V1(void* address); + void FireGCCreateConcurrentThread_V1(); + void FireGCTerminateConcurrentThread_V1(); + void FireGCTriggered(uint32_t reason); + void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes); + void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId); + void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired, + int32_t numHeaps, + uint32_t condemnedGeneration, + uint32_t gen0reductionCount, + uint32_t reason, + uint32_t globalMechanisms, + uint32_t pauseMode, + uint32_t memoryPressure); + void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind); + void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress); + void FirePinObjectAtGCTime(void* object, uint8_t** ppObject); void FireGCPerHeapHistory_V3(void *freeListAllocated, void *freeListRejected, void *endOfSegAllocated,