diff options
Diffstat (limited to 'src/vm/eventpipefile.cpp')
-rw-r--r-- | src/vm/eventpipefile.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/vm/eventpipefile.cpp b/src/vm/eventpipefile.cpp new file mode 100644 index 0000000000..f574814586 --- /dev/null +++ b/src/vm/eventpipefile.cpp @@ -0,0 +1,164 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "eventpipebuffer.h" +#include "eventpipeconfiguration.h" +#include "eventpipefile.h" + +#ifdef FEATURE_PERFTRACING + +EventPipeFile::EventPipeFile( + SString &outputFilePath +#ifdef _DEBUG + , + bool lockOnWrite +#endif // _DEBUG +) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + m_pSerializer = new FastSerializer(outputFilePath, *this); + m_serializationLock.Init(LOCK_TYPE_DEFAULT); + m_pMetadataLabels = new MapSHashWithRemove<EventPipeEvent*, StreamLabel>(); + +#ifdef _DEBUG + m_lockOnWrite = lockOnWrite; +#endif // _DEBUG + + // File start time information. + GetSystemTime(&m_fileOpenSystemTime); + QueryPerformanceCounter(&m_fileOpenTimeStamp); + QueryPerformanceFrequency(&m_timeStampFrequency); + + // Write a forward reference to the beginning of the event stream. + // This also allows readers to know where the event stream ends and skip it if needed. + m_beginEventsForwardReferenceIndex = m_pSerializer->AllocateForwardReference(); + m_pSerializer->WriteForwardReference(m_beginEventsForwardReferenceIndex); + + // Write the header information into the file. + + // Write the current date and time. + m_pSerializer->WriteBuffer((BYTE*)&m_fileOpenSystemTime, sizeof(m_fileOpenSystemTime)); + + // Write FileOpenTimeStamp + m_pSerializer->WriteBuffer((BYTE*)&m_fileOpenTimeStamp, sizeof(m_fileOpenTimeStamp)); + + // Write ClockFrequency + m_pSerializer->WriteBuffer((BYTE*)&m_timeStampFrequency, sizeof(m_timeStampFrequency)); +} + +EventPipeFile::~EventPipeFile() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + // Mark the end of the event stream. + StreamLabel currentLabel = m_pSerializer->GetStreamLabel(); + + // Define the event start forward reference. + m_pSerializer->DefineForwardReference(m_beginEventsForwardReferenceIndex, currentLabel); + + // Close the serializer. + if(m_pSerializer != NULL) + { + delete(m_pSerializer); + m_pSerializer = NULL; + } +} + +void EventPipeFile::WriteEvent(EventPipeEventInstance &instance) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + +#ifdef _DEBUG + if(m_lockOnWrite) + { + // Take the serialization lock. + // This is used for synchronous file writes. + // The circular buffer path only writes from one thread. + SpinLockHolder _slh(&m_serializationLock); + } +#endif // _DEBUG + + // Check to see if we've seen this event type before. + // If not, then write the event metadata to the event stream first. + StreamLabel metadataLabel = GetMetadataLabel(*instance.GetEvent()); + if(metadataLabel == 0) + { + EventPipeEventInstance* pMetadataInstance = EventPipe::GetConfiguration()->BuildEventMetadataEvent(instance); + + metadataLabel = m_pSerializer->GetStreamLabel(); + pMetadataInstance->FastSerialize(m_pSerializer, (StreamLabel)0); // 0 breaks recursion and represents the metadata event. + + SaveMetadataLabel(*instance.GetEvent(), metadataLabel); + + delete[] (pMetadataInstance->GetData()); + delete (pMetadataInstance); + } + + // Write the event to the stream. + instance.FastSerialize(m_pSerializer, metadataLabel); +} + +StreamLabel EventPipeFile::GetMetadataLabel(EventPipeEvent &event) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + StreamLabel outLabel; + if(m_pMetadataLabels->Lookup(&event, &outLabel)) + { + _ASSERTE(outLabel != 0); + return outLabel; + } + + return 0; +} + +void EventPipeFile::SaveMetadataLabel(EventPipeEvent &event, StreamLabel label) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(label > 0); + } + CONTRACTL_END; + + // If a pre-existing metadata label exists, remove it. + StreamLabel outLabel; + if(m_pMetadataLabels->Lookup(&event, &outLabel)) + { + m_pMetadataLabels->Remove(&event); + } + + // Add the metadata label. + m_pMetadataLabels->Add(&event, label); +} + +#endif // FEATURE_PERFTRACING |