Skip to content

Commit

Permalink
Apply some obvious rich debug info optimizations (#73373)
Browse files Browse the repository at this point in the history
* Stop sending many duplicate MethodDetails events for rich debug info

When rich debug info is enabled we send MethodDetails events for all
inlinees as otherwise no information for those may have been sent (in
case they have not been jitted). During rundown this was sending a lot
of duplicate events.

* Compress rich debug info and optimize ETW events

* Compress rich debug info when stored in the runtime. For
  Avalonia.ILSpy which has ~33k methods, the memory overhead of rich
  debug info goes from 7 MB -> 2.1 MB

* ETW events do not use the delta compression, but still optimize them a
  little by avoiding sending out the padding and unnecessarily large
  types. The average size of a rich debug info ETW event goes from 259
  bytes to 219 bytes for ILSpy

* Add DoEncodedDeltaU32NonMonotonic and use it

The inline ordinals may not be monotonically increasing and the existing
DoEncodedDeltaU32 is unnecessarily inefficient for the cases where it
isn't (plus, will assert).

* Use non-monotonic delta compression for IL offsets

Gets us an extra ~10% size reduction in my tests
  • Loading branch information
jakobbotsch committed Aug 6, 2022
1 parent e8a85b7 commit 2db51aa
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 62 deletions.
11 changes: 8 additions & 3 deletions src/coreclr/inc/eventtracebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,11 @@ class CrstBase;
class BulkTypeEventLogger;
class TypeHandle;
class Thread;

template<typename ELEMENT, typename TRAITS>
class SetSHash;
template<typename ELEMENT>
class PtrSetSHashTraits;
typedef SetSHash<MethodDesc*, PtrSetSHashTraits<MethodDesc*>> MethodDescSet;

// All ETW helpers must be a part of this namespace
// We have auto-generated macros to directly fire the events
Expand Down Expand Up @@ -903,8 +907,8 @@ namespace ETW
static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions);
static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL);
static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId);
static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId);
static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL);
static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId, MethodDescSet* sentMethodDetailsSet);
static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL, MethodDescSet* sentMethodDetailsSet = NULL);
static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName);
public:
typedef union _MethodStructs
Expand Down Expand Up @@ -937,6 +941,7 @@ namespace ETW
static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig);
static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc);
static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set);
static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName);
static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers);
static VOID MethodRestored(MethodDesc * pMethodDesc);
Expand Down
36 changes: 36 additions & 0 deletions src/coreclr/inc/nibblestream.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,22 @@ class NibbleWriter
WriteEncodedU32(dw);
};

void WriteUnencodedU32(uint32_t x)
{
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
}
CONTRACTL_END;

for (int i = 0; i < 8; i++)
{
WriteNibble(static_cast<NIBBLE>(x & 0b1111));
x >>= 4;
}
}

protected:
NIBBLE m_PendingNibble; // Pending value, not yet written out.
bool m_fPending;
Expand Down Expand Up @@ -288,6 +304,26 @@ class NibbleReader
return (dw & 1) ? (-x) : (x);
}

DWORD ReadUnencodedU32()
{
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
SUPPORTS_DAC;
}
CONTRACTL_END;

DWORD result = 0;

for (int i = 0; i < 8; i++)
{
result |= static_cast<DWORD>(ReadNibble()) << (i * 4);
}

return result;
}

protected:
PTR_BYTE m_pBuffer;
size_t m_cBytes; // size of buffer.
Expand Down
Loading

0 comments on commit 2db51aa

Please sign in to comment.