Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 65 additions & 42 deletions src/coreclr/vm/eepolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,6 @@ class CallStackLogger
// MethodDescs of the stack frames, the TOS is at index 0
CDynArray<MethodDesc*> m_frames;

// Index of a stack frame where a possible repetition of frames starts
int m_commonStartIndex = -1;
// Length of the largest found repeated sequence of frames
int m_largestCommonStartLength = 0;
// Number of repetitions of the largest repeated sequence of frames
int m_largestCommonStartRepeat = 0;

StackWalkAction LogCallstackForLogCallbackWorker(CrawlFrame *pCF)
{
WRAPPER_NO_CONTRACT;
Expand All @@ -183,44 +176,14 @@ class CallStackLogger
}
}

MethodDesc *pMD = pCF->GetFunction();

if (m_commonStartIndex != -1)
{
// Some common frames were already found

if (m_frames[m_frames.Count() - m_commonStartIndex] != pMD)
{
// The frame being added is not part of the repeated sequence
if (m_frames.Count() / m_commonStartIndex >= 2)
{
// A sequence repeated at least twice was found. It is the largest one that was found so far
m_largestCommonStartLength = m_commonStartIndex;
m_largestCommonStartRepeat = m_frames.Count() / m_commonStartIndex;
}

m_commonStartIndex = -1;
}
}

if (m_commonStartIndex == -1)
{
if ((m_frames.Count() != 0) && (pMD == m_frames[0]))
{
// We have found a frame with the same MethodDesc as the frame at the top of the stack,
// possibly a new repeated sequence is starting.
m_commonStartIndex = m_frames.Count();
}
}

MethodDesc** itemPtr = m_frames.Append();
if (itemPtr == nullptr)
{
// Memory allocation failure
return SWA_ABORT;
}

*itemPtr = pMD;
*itemPtr = pCF->GetFunction();

return SWA_CONTINUE;
}
Expand Down Expand Up @@ -260,22 +223,82 @@ class CallStackLogger
{
WRAPPER_NO_CONTRACT;

if (m_largestCommonStartLength != 0)
// Length of the largest found repeated sequence of frames
int largestCommonLength = 0;
// Number of repetitions of the largest repeated sequence of frames
int largestCommonRepeat = 0;

// Start index of the repetition
int largestCommonStartOffset;
for (largestCommonStartOffset = 0; largestCommonStartOffset < m_frames.Count(); largestCommonStartOffset++)
{
// Index of a stack frame where a possible repetition of frames starts
int commonStartIndex = -1;
largestCommonLength = 0;
largestCommonRepeat = 0;

for (int i = largestCommonStartOffset; i < m_frames.Count(); i++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a quadratic algorithm. What's the worst-case delay that it can lead to in real-world apps?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there are O(N log N) algorithms to do this if this one is too slow.

{
MethodDesc* pMD = m_frames[i];
if (commonStartIndex != -1)
{
// Some common frames were already found

int commonLength = commonStartIndex - largestCommonStartOffset;
if (m_frames[i - commonLength] != pMD)
{
// The frame being added is not part of the repeated sequence
int commonRepeat = (i - largestCommonStartOffset) / commonLength;
if (commonRepeat >= 2)
{
// A sequence repeated at least twice was found. It is the largest one that was found so far
largestCommonLength = commonLength;
largestCommonRepeat = commonRepeat;
}

commonStartIndex = -1;
}
}

if (commonStartIndex == -1)
{
if ((i != largestCommonStartOffset) && (pMD == m_frames[largestCommonStartOffset]))
{
// We have found a frame with the same MethodDesc as the frame at the start of the repetition search (index largestCommonStartOffset),
// possibly a new repeated sequence is starting.
commonStartIndex = i;
}
}
}

if (largestCommonRepeat != 0)
{
// A repeated sequence of frames was identified
break;
}
}

for (int i = 0; i < largestCommonStartOffset; i++)
{
PrintFrame(i, pWordAt);
}

if (largestCommonLength != 0)
{
SmallStackSString repeatStr;
repeatStr.AppendPrintf("Repeated %d times:\n", m_largestCommonStartRepeat);
repeatStr.AppendPrintf("Repeated %d times:\n", largestCommonRepeat);

PrintToStdErrW(repeatStr.GetUnicode());

PrintToStdErrA("--------------------------------\n");
for (int i = 0; i < m_largestCommonStartLength; i++)
for (int i = largestCommonStartOffset; i < largestCommonStartOffset + largestCommonLength; i++)
{
PrintFrame(i, pWordAt);
}
PrintToStdErrA("--------------------------------\n");
}

for (int i = m_largestCommonStartLength * m_largestCommonStartRepeat; i < m_frames.Count(); i++)
for (int i = largestCommonLength * largestCommonRepeat + largestCommonStartOffset; i < m_frames.Count(); i++)
{
PrintFrame(i, pWordAt);
}
Expand Down
Loading