summaryrefslogtreecommitdiff
path: root/src/vm/eventpipefile.h
blob: 2cc17accff3c8c72da666c9c38f9d970b422b23d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// 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.

#ifndef __EVENTPIPE_FILE_H__
#define __EVENTPIPE_FILE_H__

#ifdef FEATURE_PERFTRACING

#include "eventpipe.h"
#include "eventpipeblock.h"
#include "fastserializableobject.h"

class EventPipeConfiguration;
class EventPipeEventInstance;
class FastSerializer;
struct EventPipeSequencePoint;

struct StackHashKey
{
    BYTE* pStackBytes;
    ULONG Hash;
    ULONG StackSizeInBytes;

    StackHashKey(StackContents* pStack);
    StackHashKey(BYTE* pStack, ULONG stackSizeInBytes, ULONG hash);
};

struct StackHashEntry
{
    ULONG Id;
    ULONG Hash;
    ULONG StackSizeInBytes;
    // This is the first byte of StackSizeInBytes bytes of stack data
    BYTE StackBytes[1];

    static StackHashEntry* CreateNew(StackContents* pStack, ULONG id, ULONG hash);
    StackHashKey GetKey() const;
};

class EventPipeStackHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<StackHashEntry*>>
{
public:
    typedef typename DefaultSHashTraits<StackHashEntry*>::element_t element_t;
    typedef typename DefaultSHashTraits<StackHashEntry*>::count_t count_t;

    typedef const StackHashKey key_t;

    static key_t GetKey(element_t e)
    {
        LIMITED_METHOD_CONTRACT;
        return e->GetKey();
    }
    static BOOL Equals(key_t k1, key_t k2)
    {
        LIMITED_METHOD_CONTRACT;
        return k1.StackSizeInBytes == k2.StackSizeInBytes &&
            memcmp(k1.pStackBytes, k2.pStackBytes, k1.StackSizeInBytes) == 0;
    }
    static count_t Hash(key_t k)
    {
        LIMITED_METHOD_CONTRACT;
        return (count_t)(size_t)k.Hash;
    }

    static element_t Null() { LIMITED_METHOD_CONTRACT; return nullptr; }
    static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == nullptr; }
};

typedef SHash<EventPipeStackHashTraits> EventPipeStackHash;

class EventPipeFile final : public FastSerializableObject
{
public:
    EventPipeFile(StreamWriter *pStreamWriter, EventPipeSerializationFormat format);
    ~EventPipeFile();

    EventPipeSerializationFormat GetSerializationFormat() const;
    void WriteEvent(EventPipeEventInstance &instance, ULONGLONG captureThreadId, unsigned int sequenceNumber, BOOL isSortedEvent);
    void WriteSequencePoint(EventPipeSequencePoint* pSequencePoint);
    enum FlushFlags
    {
        FlushEventBlock = 1,
        FlushMetadataBlock = 2,
        FlushStackBlock = 4,
        FlushAllBlocks = FlushEventBlock | FlushMetadataBlock | FlushStackBlock
    };
    void Flush(FlushFlags flags = FlushAllBlocks);
    bool HasErrors() const;

    const char *GetTypeName() override
    {
        LIMITED_METHOD_CONTRACT;
        return "Trace";
    }

    void FastSerialize(FastSerializer *pSerializer) override
    {
        CONTRACTL
        {
            NOTHROW;
            GC_NOTRIGGER;
            MODE_PREEMPTIVE;
            PRECONDITION(pSerializer != NULL);
        }
        CONTRACTL_END;

        pSerializer->WriteBuffer((BYTE *)&m_fileOpenSystemTime, sizeof(m_fileOpenSystemTime));
        pSerializer->WriteBuffer((BYTE *)&m_fileOpenTimeStamp, sizeof(m_fileOpenTimeStamp));
        pSerializer->WriteBuffer((BYTE *)&m_timeStampFrequency, sizeof(m_timeStampFrequency));

        // the beginning of V3
        pSerializer->WriteBuffer((BYTE *)&m_pointerSize, sizeof(m_pointerSize));
        pSerializer->WriteBuffer((BYTE *)&m_currentProcessId, sizeof(m_currentProcessId));
        pSerializer->WriteBuffer((BYTE *)&m_numberOfProcessors, sizeof(m_numberOfProcessors));
        pSerializer->WriteBuffer((BYTE *)&m_samplingRateInNs, sizeof(m_samplingRateInNs));
    }

private:
    void WriteEnd();

    unsigned int GenerateMetadataId();

    unsigned int GetMetadataId(EventPipeEvent &event);

    unsigned int GetStackId(EventPipeEventInstance &instance);

    void SaveMetadataId(EventPipeEvent &event, unsigned int metadataId);

    void WriteEventToBlock(EventPipeEventInstance &instance,
                           unsigned int metadataId,
                           ULONGLONG captureThreadId = 0,
                           unsigned int sequenceNumber = 0,
                           unsigned int stackId = 0,
                           BOOL isSortedEvent = TRUE);

    // The format to serialize
    EventPipeSerializationFormat m_format;

    // The object responsible for serialization.
    FastSerializer *m_pSerializer;

    EventPipeEventBlock *m_pBlock;
    EventPipeMetadataBlock *m_pMetadataBlock;
    EventPipeStackBlock *m_pStackBlock;

    // The system time when the file was opened.
    SYSTEMTIME m_fileOpenSystemTime;

    // The timestamp when the file was opened.  Used for calculating file-relative timestamps.
    LARGE_INTEGER m_fileOpenTimeStamp;

    // The frequency of the timestamps used for this file.
    LARGE_INTEGER m_timeStampFrequency;

    unsigned int m_pointerSize;

    unsigned int m_currentProcessId;

    unsigned int m_numberOfProcessors;

    unsigned int m_samplingRateInNs;

    // The serialization which is responsible for making sure only a single event
    // or block of events gets written to the file at once.
    SpinLock m_serializationLock;

    // Hashtable of metadata labels.
    MapSHashWithRemove<EventPipeEvent *, unsigned int> *m_pMetadataIds;

    Volatile<LONG> m_metadataIdCounter;

    unsigned int m_stackIdCounter;
    EventPipeStackHash m_stackHash;
#ifdef DEBUG
    LARGE_INTEGER m_lastSortedTimestamp;
#endif
};

#endif // FEATURE_PERFTRACING

#endif // __EVENTPIPE_FILE_H__