Skip to content

Commit 2c94e69

Browse files
authored
Delete interop standby lists, dedup Debugger.DefaultCategory (#115446)
* Delete interop standby lists Global free lists on top of regular malloc/free used to be a fine optimization years ago on single-proc machines. They are typically a de-optimization these days, breaking thread locality and trashing caches. * Dedup Debugger.DefaultCategory
1 parent fd8933a commit 2c94e69

File tree

10 files changed

+16
-147
lines changed

10 files changed

+16
-147
lines changed

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,6 @@ static void NotifyOfCrossThreadDependencySlow()
6565
[SuppressGCTransition]
6666
private static partial int IsManagedDebuggerAttached();
6767

68-
// Constants representing the importance level of messages to be logged.
69-
//
70-
// An attached debugger can enable or disable which messages will
71-
// actually be reported to the user through the debugger
72-
// services API. This info is communicated to the runtime so only
73-
// desired events are actually reported to the debugger.
74-
//
75-
// Constant representing the default category
76-
public static readonly string? DefaultCategory;
77-
7868
// Posts a message for the attached debugger. If there is no
7969
// debugger attached, has no effect. The debugger may or may not
8070
// report the message depending on its settings.

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@ public static void NotifyOfCrossThreadDependency()
4141
// nothing to do...yet
4242
}
4343

44-
/// <summary>
45-
/// Constants representing the importance level of messages to be logged.
46-
///
47-
/// An attached debugger can enable or disable which messages will
48-
/// actually be reported to the user through the CLR debugger
49-
/// services API. This info is communicated to the runtime so only
50-
/// desired events are actually reported to the debugger.
51-
/// Constant representing the default category
52-
/// </summary>
53-
public static readonly string DefaultCategory;
54-
5544
/// <summary>
5645
/// Posts a message for the attached debugger. If there is no
5746
/// debugger attached, has no effect. The debugger may or may not

src/coreclr/vm/interoputil.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3662,7 +3662,6 @@ void InitializeComInterop()
36623662
}
36633663
CONTRACTL_END;
36643664

3665-
InitializeSListHead(&RCW::s_RCWStandbyList);
36663665
ComCall::Init();
36673666
CtxEntryCache::Init();
36683667
ComCallWrapperTemplate::Init();

src/coreclr/vm/runtimecallablewrapper.cpp

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ class Object;
4141
#include "finalizerthread.h"
4242
#include "dynamicinterfacecastable.h"
4343

44-
// static
45-
SLIST_HEADER RCW::s_RCWStandbyList;
46-
4744
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
4845
#include "olecontexthelpers.h"
4946
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
@@ -1292,19 +1289,6 @@ const int RCW::s_rGCPressureTable[GCPressureSize_COUNT] =
12921289
GC_PRESSURE_REMOTE, // GCPressureSize_Remote
12931290
};
12941291

1295-
// Deletes all items in code:s_RCWStandbyList.
1296-
void RCW::FlushStandbyList()
1297-
{
1298-
LIMITED_METHOD_CONTRACT;
1299-
1300-
PSLIST_ENTRY pEntry = InterlockedFlushSList(&RCW::s_RCWStandbyList);
1301-
while (pEntry)
1302-
{
1303-
PSLIST_ENTRY pNextEntry = pEntry->Next;
1304-
delete (RCW *)pEntry;
1305-
pEntry = pNextEntry;
1306-
}
1307-
}
13081292
//--------------------------------------------------------------------------------
13091293
// The IUnknown passed in is AddRef'ed if we succeed in creating the wrapper.
13101294
RCW* RCW::CreateRCW(IUnknown *pUnk, DWORD dwSyncBlockIndex, DWORD flags, MethodTable *pClassMT)
@@ -1344,16 +1328,7 @@ RCW* RCW::CreateRCWInternal(IUnknown *pUnk, DWORD dwSyncBlockIndex, DWORD flags,
13441328
CONTRACT_END;
13451329

13461330
// now allocate the wrapper
1347-
RCW *pWrap = (RCW *)InterlockedPopEntrySList(&RCW::s_RCWStandbyList);
1348-
if (pWrap != NULL)
1349-
{
1350-
// cache hit - reinitialize the data structure
1351-
new (pWrap) RCW();
1352-
}
1353-
else
1354-
{
1355-
pWrap = new RCW();
1356-
}
1331+
RCW *pWrap = new RCW();
13571332

13581333
AppDomain * pAppDomain = GetAppDomain();
13591334
ULONG cbRef = SafeAddRefPreemp(pUnk);
@@ -1764,7 +1739,7 @@ void RCW::Cleanup()
17641739
#endif
17651740

17661741
// If there's no thread currently working with the RCW, this call will release helper fields on IUnkEntry
1767-
// and recycle the entire RCW structure, i.e. insert it in the standby list to be reused or free the memory.
1742+
// and delete the entire RCW structure.
17681743
// If a thread still keeps a ref-count on the RCW, it will release it when it's done. Keeping the structure
17691744
// and the helper fields alive reduces the chances of memory corruption in race scenarios.
17701745
DecrementUseCount();

src/coreclr/vm/runtimecallablewrapper.h

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ struct RCW
9999

100100
static CreationFlags CreationFlagsFromObjForComIPFlags(ObjFromComIP::flags flags);
101101

102-
// List of RCW instances that have been freed since the last RCW cleanup.
103-
static SLIST_HEADER s_RCWStandbyList;
104-
105102
// Simple read-only iterator for all cached interface pointers.
106103
class CachedInterfaceEntryIterator
107104
{
@@ -161,9 +158,6 @@ struct RCW
161158
ZeroMemory(this, sizeof(*this));
162159
}
163160

164-
// Deletes all items in code:s_RCWStandbyList.
165-
static void FlushStandbyList();
166-
167161
// Create a new wrapper for given IUnk, IDispatch
168162
static RCW* CreateRCW(IUnknown *pUnk, DWORD dwSyncBlockIndex, DWORD flags, MethodTable *pClassMT);
169163

@@ -489,20 +483,11 @@ struct RCW
489483

490484
if (InterlockedDecrement(&m_cbUseCount) == 0)
491485
{
492-
// this was the final decrement, go ahead and delete/recycle the RCW
493-
{
494-
GCX_PREEMP();
495-
m_UnkEntry.Free();
496-
}
486+
// this was the final decrement, go ahead and delete the RCW
487+
GCX_PREEMP();
488+
m_UnkEntry.Free();
497489

498-
if (g_fEEShutDown)
499-
{
500-
delete this;
501-
}
502-
else
503-
{
504-
InterlockedPushEntrySList(&RCW::s_RCWStandbyList, (PSLIST_ENTRY)this);
505-
}
490+
delete this;
506491
}
507492
}
508493

src/coreclr/vm/syncblk.cpp

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ SPTR_IMPL (SyncBlockCache, SyncBlockCache, s_pSyncBlockCache);
5252

5353
#ifndef DACCESS_COMPILE
5454

55-
#ifndef TARGET_UNIX
56-
// static
57-
SLIST_HEADER InteropSyncBlockInfo::s_InteropInfoStandbyList;
58-
#endif // !TARGET_UNIX
59-
6055
InteropSyncBlockInfo::~InteropSyncBlockInfo()
6156
{
6257
CONTRACTL
@@ -71,30 +66,6 @@ InteropSyncBlockInfo::~InteropSyncBlockInfo()
7166
FreeUMEntryThunk();
7267
}
7368

74-
#ifndef TARGET_UNIX
75-
// Deletes all items in code:s_InteropInfoStandbyList.
76-
void InteropSyncBlockInfo::FlushStandbyList()
77-
{
78-
CONTRACTL
79-
{
80-
NOTHROW;
81-
GC_TRIGGERS;
82-
MODE_ANY;
83-
}
84-
CONTRACTL_END;
85-
86-
PSLIST_ENTRY pEntry = InterlockedFlushSList(&InteropSyncBlockInfo::s_InteropInfoStandbyList);
87-
while (pEntry)
88-
{
89-
PSLIST_ENTRY pNextEntry = pEntry->Next;
90-
91-
// make sure to use the global delete since the destructor has already run
92-
::delete (void *)pEntry;
93-
pEntry = pNextEntry;
94-
}
95-
}
96-
#endif // !TARGET_UNIX
97-
9869
void InteropSyncBlockInfo::FreeUMEntryThunk()
9970
{
10071
CONTRACTL
@@ -656,10 +627,6 @@ void SyncBlockCache::Start()
656627
g_SyncBlockCacheInstance.Init();
657628

658629
SyncBlockCache::GetSyncBlockCache()->m_EphemeralBitmap = bm;
659-
660-
#ifndef TARGET_UNIX
661-
InitializeSListHead(&InteropSyncBlockInfo::s_InteropInfoStandbyList);
662-
#endif // !TARGET_UNIX
663630
}
664631

665632

@@ -976,19 +943,7 @@ void SyncBlockCache::DeleteSyncBlock(SyncBlock *psb)
976943
CleanupSyncBlockComData(psb->m_pInteropInfo);
977944
#endif // FEATURE_COMINTEROP
978945

979-
#ifndef TARGET_UNIX
980-
if (g_fEEShutDown)
981-
{
982-
delete psb->m_pInteropInfo;
983-
}
984-
else
985-
{
986-
psb->m_pInteropInfo->~InteropSyncBlockInfo();
987-
InterlockedPushEntrySList(&InteropSyncBlockInfo::s_InteropInfoStandbyList, (PSLIST_ENTRY)psb->m_pInteropInfo);
988-
}
989-
#else // !TARGET_UNIX
990946
delete psb->m_pInteropInfo;
991-
#endif // !TARGET_UNIX
992947
}
993948

994949
#ifdef FEATURE_METADATA_UPDATER

src/coreclr/vm/syncblk.h

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -615,11 +615,6 @@ class InteropSyncBlockInfo
615615
friend class ClrDataAccess;
616616

617617
public:
618-
#ifndef TARGET_UNIX
619-
// List of InteropSyncBlockInfo instances that have been freed since the last syncblock cleanup.
620-
static SLIST_HEADER s_InteropInfoStandbyList;
621-
#endif // !TARGET_UNIX
622-
623618
InteropSyncBlockInfo()
624619
: m_pUMEntryThunk{}
625620
#ifdef FEATURE_COMINTEROP
@@ -640,11 +635,6 @@ class InteropSyncBlockInfo
640635
~InteropSyncBlockInfo();
641636
#endif
642637

643-
#ifndef TARGET_UNIX
644-
// Deletes all items in code:s_InteropInfoStandbyList.
645-
static void FlushStandbyList();
646-
#endif // !TARGET_UNIX
647-
648638
#ifdef FEATURE_COMINTEROP
649639

650640
//
@@ -963,20 +953,7 @@ class SyncBlock
963953

964954
if (!m_pInteropInfo)
965955
{
966-
NewHolder<InteropSyncBlockInfo> pInteropInfo;
967-
#ifndef TARGET_UNIX
968-
pInteropInfo = (InteropSyncBlockInfo *)InterlockedPopEntrySList(&InteropSyncBlockInfo::s_InteropInfoStandbyList);
969-
970-
if (pInteropInfo != NULL)
971-
{
972-
// cache hit - reinitialize the data structure
973-
new (pInteropInfo) InteropSyncBlockInfo();
974-
}
975-
else
976-
#endif // !TARGET_UNIX
977-
{
978-
pInteropInfo = new InteropSyncBlockInfo();
979-
}
956+
NewHolder<InteropSyncBlockInfo> pInteropInfo = new InteropSyncBlockInfo();
980957

981958
if (SetInteropInfo(pInteropInfo))
982959
pInteropInfo.SuppressRelease();

src/coreclr/vm/threads.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6867,14 +6867,6 @@ void Thread::DoExtraWorkForFinalizer()
68676867

68686868
if (RequireSyncBlockCleanup())
68696869
{
6870-
#ifndef TARGET_UNIX
6871-
InteropSyncBlockInfo::FlushStandbyList();
6872-
#endif // !TARGET_UNIX
6873-
6874-
#ifdef FEATURE_COMINTEROP
6875-
RCW::FlushStandbyList();
6876-
#endif // FEATURE_COMINTEROP
6877-
68786870
SyncBlockCache::GetSyncBlockCache()->CleanupSyncBlocks();
68796871
}
68806872
if (SystemDomain::System()->RequireAppDomainCleanup())

src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ namespace System.Diagnostics
88
{
99
public static partial class Debugger
1010
{
11+
/// <summary>
12+
/// Represents the default category of message with a constant.
13+
/// </summary>
14+
/// <remarks>
15+
/// The value of this default constant is `null`. <see cref="Debugger.DefaultCategory"/>
16+
/// is used by <see cref="Debugger.Log"/>.
17+
/// </remarks>
18+
public static readonly string? DefaultCategory;
19+
1120
/// <summary>
1221
/// Signals a breakpoint to an attached debugger with the <paramref name="exception"/> details
1322
/// if a .NET debugger is attached with break on user-unhandled exception enabled and a method

src/mono/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ namespace System.Diagnostics
77
{
88
public static partial class Debugger
99
{
10-
public static readonly string? DefaultCategory;
11-
1210
public static bool IsAttached => IsAttached_internal();
1311

1412
[MethodImplAttribute(MethodImplOptions.InternalCall)]

0 commit comments

Comments
 (0)