From 411fb39bc45067d47b4189bdf7288b9224ced487 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Fri, 12 Apr 2019 17:11:49 -0700 Subject: [PATCH] Fix EventPipe IPC streaming (#23768) * Make events stream out faster when we are doing IPC * Block size should be less during IPC session * Modify some comments * Address PR feedback * more pr feedback * Fix high volume scenario * Fix flush * cleanup * Only flush when we have buffers written --- src/vm/eventpipebuffermanager.cpp | 8 +++++--- src/vm/eventpipebuffermanager.h | 2 +- src/vm/eventpipefile.cpp | 14 ++++++++++++++ src/vm/eventpipefile.h | 1 + src/vm/fastserializer.cpp | 1 - src/vm/fastserializer.h | 2 +- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/vm/eventpipebuffermanager.cpp b/src/vm/eventpipebuffermanager.cpp index e15676e..f08a2b3 100644 --- a/src/vm/eventpipebuffermanager.cpp +++ b/src/vm/eventpipebuffermanager.cpp @@ -434,6 +434,7 @@ void EventPipeBufferManager::WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_I SpinLockHolder _slh(&m_lock); // Naively walk the circular buffer, writing the event stream in timestamp order. + m_numEventsWritten = 0; while(true) { EventPipeEventInstance *pOldestInstance = NULL; @@ -470,13 +471,14 @@ void EventPipeBufferManager::WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_I // Write the oldest event. pFile->WriteEvent(*pOldestInstance); -#ifdef _DEBUG - m_numEventsWritten++; -#endif // _DEBUG + m_numEventsWritten++; // Pop the event from the buffer. pOldestContainingList->PopNextEvent(stopTimeStamp); } + + if (m_numEventsWritten > 0) + pFile->Flush(); } EventPipeEventInstance* EventPipeBufferManager::GetNextEvent() diff --git a/src/vm/eventpipebuffermanager.h b/src/vm/eventpipebuffermanager.h index a7584cc..a6e47f3 100644 --- a/src/vm/eventpipebuffermanager.h +++ b/src/vm/eventpipebuffermanager.h @@ -71,9 +71,9 @@ private: unsigned int m_numBuffersLeaked; Volatile m_numEventsStored; Volatile m_numEventsDropped; - LONG m_numEventsWritten; #endif // _DEBUG + unsigned long m_numEventsWritten; // Allocate a new buffer for the specified thread. // This function will store the buffer in the thread's buffer list for future use and also return it here. // A NULL return value means that a buffer could not be allocated. diff --git a/src/vm/eventpipefile.cpp b/src/vm/eventpipefile.cpp index 73fb48e..b2d82e5 100644 --- a/src/vm/eventpipefile.cpp +++ b/src/vm/eventpipefile.cpp @@ -96,6 +96,20 @@ void EventPipeFile::WriteEvent(EventPipeEventInstance &instance) WriteToBlock(instance, metadataId); } +void EventPipeFile::Flush() +{ + // Write existing buffer to the stream/file regardless of whether it is full or not. + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + m_pSerializer->WriteObject(m_pBlock); // we write current block to the disk, whether it's full or not + m_pBlock->Clear(); +} + void EventPipeFile::WriteEnd() { CONTRACTL diff --git a/src/vm/eventpipefile.h b/src/vm/eventpipefile.h index d99bcd1..9441ec4 100644 --- a/src/vm/eventpipefile.h +++ b/src/vm/eventpipefile.h @@ -21,6 +21,7 @@ public: ~EventPipeFile(); void WriteEvent(EventPipeEventInstance &instance); + void Flush(); const char *GetTypeName() override { diff --git a/src/vm/fastserializer.cpp b/src/vm/fastserializer.cpp index 2941f6a..0b2c0f6 100644 --- a/src/vm/fastserializer.cpp +++ b/src/vm/fastserializer.cpp @@ -63,7 +63,6 @@ FileStreamWriter::FileStreamWriter(const SString &outputFilePath) MODE_ANY; } CONTRACTL_END; - m_pFileStream = new CFileStream(); if (FAILED(m_pFileStream->OpenForWrite(outputFilePath))) { diff --git a/src/vm/fastserializer.h b/src/vm/fastserializer.h index 4d61adc..d5db786 100644 --- a/src/vm/fastserializer.h +++ b/src/vm/fastserializer.h @@ -16,7 +16,7 @@ class IpcStream; // the enumeration has a specific set of values to keep it compatible with consumer library // it's sibling is defined in https://github.com/Microsoft/perfview/blob/10d1f92b242c98073b3817ac5ee6d98cd595d39b/src/FastSerialization/FastSerialization.cs#L2295 -enum class FastSerializerTags : BYTE +enum class FastSerializerTags : uint8_t { Error = 0, // To improve debugabilty, 0 is an illegal tag. NullReference = 1, // Tag for a null object forwardReference. -- 2.7.4