Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Event Pipe File V3 #16107

Merged
merged 30 commits into from
Feb 2, 2018
Merged

Event Pipe File V3 #16107

merged 30 commits into from
Feb 2, 2018

Conversation

adamsitnik
Copy link
Member

This PR is ready for review, but not ready to be merged yet.

Today all non-Windows build are going to fail because I have bumped the version of Event Pipe file, which is not supported by the referenced EventTrace library.

We need to release new version of TraceEvent lib and updated the references to it in CoreCLR, so all tests are going to pass. This + review and then it can be merge.

Changes:

  1. New version of the Event Pipe file
  2. Removed forward references (to avoid the need of reading entire file to read the value of forward reference to the end of event stream)
  3. Introduced Event Blocks which are simply groups of events.
  4. Ensured 4-byte alignment
  5. Proper ending of the file and all objects (End tag was missing for EventPipe object)
  6. Added missing data (pointer size, # of processors, process id, sampling rate)
  7. Removed duplicated data (event id and event version_
  8. Ensured that metadata payload is always present for the metadata events

I am a newbie when it comes to C++, please make sure that the review is very detailed.

/cc @jorive

# Conflicts:
#	src/vm/eventpipeeventinstance.h
@adamsitnik adamsitnik added area-EventSource * NO MERGE * The PR is not ready for merge yet (see discussion for detailed reasons) area-Tracing labels Jan 30, 2018
@adamsitnik adamsitnik requested review from brianrob and vancem January 30, 2018 21:49
Copy link
Member

@brianrob brianrob left a comment

Choose a reason for hiding this comment

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

Thanks for making these changes. Looks good - some comments as well.

@@ -393,6 +393,8 @@ void EventPipe::Disable()
s_pConfig->DeleteSession(s_pSession);
s_pSession = NULL;

s_pFile->WriteEnd(); // write the rest of the events and end tag to the file
Copy link
Member

Choose a reason for hiding this comment

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

If possible, it would be nice to have this occur as part of the destructor of the EventPipeFile. This ensures that no matter how the file is used the end gets properly written. Note that there is at least one more EventPipeFile - the synchronously written file that would also need a call to WriteEnd to be functionally correct, though I'm not 100% sure that it still works today.


void FastSerialize(FastSerializer *pSerializer)
{
unsigned int eventsSize = (unsigned int)(m_pWritePointer - m_pBlock);
Copy link
Member

Choose a reason for hiding this comment

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

You should use size_t as the size here since it is guaranteed to allow you to represent all memory addresses (and sizes) for a given bitness machine.

class EventPipeBlock : public FastSerializableObject
{
public:
EventPipeBlock(unsigned int maxBlockSize);
Copy link
Member

Choose a reason for hiding this comment

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

size_t here as well.

Copy link

Choose a reason for hiding this comment

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

same sizes of blocks can be 32 bit.

}
CONTRACTL_END;

m_pBlock = new BYTE[maxBlockSize];
Copy link
Member

Choose a reason for hiding this comment

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

As a philosophical statement, we say that we don't want failures in tracing to affect program correctness. Thus, one of the things we do is to try to make sure that we don't throw in places that will leak out to the program. The only exception that EventPipe has (or should have) currently is that we will throw if you try to enable tracing in-proc and it fails for some reason. Other than that, we'd rather lose data than affect program correctness.

Thus, here, you should use the nothrow flavor of new:

m_pBlock = new (nothrow) BYTE[maxBlockSize];
if(m_pBlock == NULL)
{
    return;
}

You will of course also need to handle a NULL m_pBlock inside the other functions of EventPipeBlock.

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice! I had no idea about new (nothrow)

m_pWritePointer += stackSize;
}

while (m_pWritePointer < alignedEnd)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Please put { } around this loop.

MapSHashWithRemove<EventPipeEvent*, StreamLabel> *m_pMetadataLabels;
MapSHashWithRemove<EventPipeEvent*, unsigned int> *m_pMetadataIds;

volatile unsigned int m_metadataIdCounter;
Copy link
Member

Choose a reason for hiding this comment

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

If you change the type to Volatile I don't think you'll need the casts when you call InterlockedIncrement.


m_pBlock->Clear();

// "After the last EventBlock is emitted, the stream is ended by emitting a NullReference Tag which indicates that there are no more objects in the stream to read."
Copy link
Member

Choose a reason for hiding this comment

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

Accidental quotes on the comment?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was a quote from the docs, I should have added link


instance.SetMetadataId(metadataId);

if (m_pBlock->WriteEvent(instance))
Copy link
Member

Choose a reason for hiding this comment

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

Nit: { }

{
LIMITED_METHOD_CONTRACT;
return "Microsoft.DotNet.Runtime.EventPipeFile";
pSerializer->WriteBuffer((BYTE*)&m_fileOpenSystemTime, sizeof(m_fileOpenSystemTime));
Copy link
Member

Choose a reason for hiding this comment

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

I like this! Much better that the file itself is represented in FastSerialization instead of being special cased.

}

// Get the type name of this object.
const char* GetTypeName()
void FastSerialize(FastSerializer *pSerializer)
Copy link
Member

Choose a reason for hiding this comment

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

I know that you got rid of the support for forward references as part of this change to make it easier to support streaming. How do you make sure that this block of information is extensible since the forward references are now gone?

Copy link

Choose a reason for hiding this comment

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

@brianrob
Copy link
Member

brianrob commented Feb 1, 2018

One other thing that we should look at is what the right default block size is so that we don't thrash too much but also don't allocate huge blocks.

@vancem
Copy link

vancem commented Feb 1, 2018

I have updated http://nuget.org with version 2.0.4 of the TraceEvent library which has the EventPipe V3 format in it. @adamsitnik you can update your test code to point at it so it does not fail.

Note that I am assuming you know about the fact that you can create a Nuget.Config file at the base of your project and add additional locations to find nuget packages (see https://github.com/Microsoft/perfview/blob/master/Nuget.config) you can thus make your private version of the TraceEvent package and put it there and your test code will find it. This allows you to test everything without needing to update nuget.org.

One other thing that we should look at is what the right default block size is so that we don't thrash too much but also don't allocate huge blocks.

Note that my belief is that any number between 10K to 1Meg will work well enough for write perf. We currently use 100K and that is a fine number.

@adamsitnik
Copy link
Member Author

One of the Ubuntu builds fails with 8:12: error: no matching function for call to 'InterlockedIncrement'

How can I increment a value in atomic, cross-platform way here? I understand that InterlockedIncrement that I have used is Windows-only?

I have ofc search for that on the web, but I can't see anybody using std::atomic in CoreCLR.

@brianrob @jorive any ideas?

@brianrob
Copy link
Member

brianrob commented Feb 2, 2018

It looks like the PAL only implements InterlockedIncrement for LONG and LONGLONG (via InterlockedIncrement64). See https://github.com/dotnet/coreclr/blob/master/src/pal/inc/pal.h#L4159 for details. You just happen to be picking up the int version on Windows most likely.

Probably the best thing to do is to change the data type of the metadata ID counter to Volatile<LONG> and then cast the result to int.

@vancem
Copy link

vancem commented Feb 2, 2018

@adamsitnik - Try FastInterlockIncrement. (although I must admit I am surprised that InterlockedIncrement did not work).

@adamsitnik adamsitnik removed the * NO MERGE * The PR is not ready for merge yet (see discussion for detailed reasons) label Feb 2, 2018
@adamsitnik
Copy link
Member Author

@brianrob @vancem thanks for help and the review!

Brian, I just pushed last minor improvements after additional review from @jorive

Could you check the PR?

If you accept it, and all tests except the unstable HardwareInstrincts pass, who can merge it then? I have this right on GitHub but I don't know the rules.

Copy link
Member

@brianrob brianrob left a comment

Choose a reason for hiding this comment

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

LGTM!

@brianrob
Copy link
Member

brianrob commented Feb 2, 2018

@adamsitnik, once the CI runs complete and pass (or just have the hardware intrinsic failures) you can go ahead and merge. The default option (Squash and merge) is what you should use since you don't need to maintain distinct commits for this change. Requirements for merge are clean CI, MS employee review sign-off.

@adamsitnik adamsitnik merged commit f6ba335 into dotnet:master Feb 2, 2018
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
* write missing information to the event pipe file (pointer size to make it work fo x86)

* define where the events start, not only where they end

* include process Id in the event pipe file, bump the version so old consumers get clear error message

* write the missing EndObject tag to close the header

* include expected CPU sampling rate in the event pipe header file

* include keywords in V3 of EventPipe metadata, fixes dotnet/coreclr#11934

* remove forward references

* entry object comes after the header and ends after it's data, before the event block objects

* introduce event block

* fix the GC contracts

* generate metadata ids

* end the file with null reference tag

* getting it work

* 4 byte alignment of serialized event data

* Revert "include keywords in V3 of EventPipe metadata, fixes dotnet/coreclr#11934"

This reverts commit dotnet/coreclr@98ef2f5.

* remove event Id and event version from metadata buffer (it was duplicated with native code)

* increase the block size to be the same as buffer size

* Write the last event block to the file after disabling the event pipe, right after last events

* include the sife in itself

* the native part was supposed to not duplicate the event id and version, not manged

* ensure 4 byte alignment

* build metadata when it's not provided, so payload is never empty (no need to serialize length)

* this todo is no longer valid

* don't align everything, just the content of event block as suggested by @vancem

* improvements after code review

* update TraceEvent dependency, make the test verify new feature

* InterlockedIncrement(Int32) is not available for non-Windows OSes

* code improvements after Skype code review from @jorive


Commit migrated from dotnet/coreclr@f6ba335
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