Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a potential memory leak due to EventPipe buffer allocation #35924

Merged

Conversation

sywhang
Copy link
Contributor

@sywhang sywhang commented May 6, 2020

This fixes a potential memory leak due to EventPipe buffer allocation causing internal fragmentation within glibc's arenas. It was originally reported in microsoft/ApplicationInsights-dotnet#1678. glibc maintains a pool of memory called arenas per-thread that it uses to allocate blocks of memory requested by malloc. EventPipe may allocate from many threads, and when it does that, it end up causing glibc to commit more memory than what the runtime thinks it committed.

The fix is quite simple - change malloc to ClrVirtualAlloc which uses mmap. I verified the fix does not introduce a significant performant with benchmarks.

The fix was tested against the repro provided by the customer who reported the issue, and was verified that it fixes the issue (more details here: microsoft/ApplicationInsights-dotnet#1678 (comment)).

@sywhang sywhang added this to the 5.0 milestone May 6, 2020
@sywhang sywhang requested review from noahfalk and josalem May 6, 2020 22:41
@@ -23,7 +23,7 @@ EventPipeBuffer::EventPipeBuffer(unsigned int bufferSize, EventPipeThread* pWrit
m_state = EventPipeBufferState::WRITABLE;
m_pWriterThread = pWriterThread;
m_eventSequenceNumber = eventSequenceNumber;
m_pBuffer = new BYTE[bufferSize];
m_pBuffer = (BYTE*)ClrVirtualAlloc(NULL, bufferSize, MEM_COMMIT, PAGE_READWRITE);
memset(m_pBuffer, 0, bufferSize);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can skip the memset now since you used the MEM_COMMIT flag here:

The function also guarantees that when the caller later initially accesses the memory, the contents will be zero.
-docs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't that doc for the Windows VirtualAlloc API? I don't think the PAL implementation memsets it to 0 by default.

Copy link
Contributor

@josalem josalem May 7, 2020

Choose a reason for hiding this comment

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

/* Test for un-supported flags. */
if ( ( flAllocationType & ~( MEM_COMMIT | MEM_RESERVE | MEM_RESET | MEM_TOP_DOWN | MEM_RESERVE_EXECUTABLE | MEM_LARGE_PAGES ) ) != 0 )
{
ASSERT( "flAllocationType can be one, or any combination of MEM_COMMIT, \
MEM_RESERVE, MEM_TOP_DOWN, MEM_RESERVE_EXECUTABLE, or MEM_LARGE_PAGES.\n" );

These comments seem to indicate it is supported, but I'll double check that we actually mimic that behavior

Copy link
Member

Choose a reason for hiding this comment

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

Based on mmap docs and our code not passing MAP_UNINITIALIZED flag to mmap I would assume the memory we get back from VirtualAlloc is zero initialized. However I'd recommend only adding a comment to the memset referencing this discussion rather than removing it. We'd like to take this into servicing which has low tolerance for risk and we've already benchmarked the current code as being good enough as-is. In the future we might do some performance measurements to improve the throughput of EventPipe - if the memset shows up in that analysis we can address it then, if not we've saved time worrying about it.

Copy link
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

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

Suggested some tweaking, but looks good to me : )

src/coreclr/src/vm/eventpipebuffermanager.cpp Outdated Show resolved Hide resolved
src/coreclr/src/vm/eventpipebuffer.cpp Show resolved Hide resolved
src/coreclr/src/vm/eventpipebuffermanager.cpp Outdated Show resolved Hide resolved
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants