Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PLINQETWProvider.cs « Utils « Parallel « Linq « System « System.Core « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bbfec3cd6e780ec3b428ba8f3e91d3ec833837cb (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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// ==++==
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// PlinqEtwProvider.cs
//
// <OWNER>Microsoft</OWNER>
//
// EventSource for PLINQ.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace System.Linq.Parallel
{
#if !FEATURE_PAL    // PAL doesn't support  eventing    
    using System.Diagnostics.Tracing;

    /// <summary>Provides an event source for tracing PLINQ information.</summary>
    [EventSource(
        Name = "System.Linq.Parallel.PlinqEventSource",
        Guid = "159eeeec-4a14-4418-a8fe-faabcd987887", 
        LocalizationResources = "System.Linq")]
    internal sealed class PlinqEtwProvider : EventSource
    {
        /// <summary>
        /// Defines the singleton instance for the PLINQ ETW provider.
        /// The PLINQ Event provider GUID is {159eeeec-4a14-4418-a8fe-faabcd987887}.
        /// </summary>
        internal static PlinqEtwProvider Log = new PlinqEtwProvider();
        /// <summary>Prevent external instantiation.  All logging should go through the Log instance.</summary>
        private PlinqEtwProvider() { }

        /// <summary>Cached id for the default scheduler.</summary>
        /// <remarks>If PLINQ ever supports other schedulers, that information will need to be passed into the query events.</remarks>
        private static readonly int s_defaultSchedulerId = TaskScheduler.Default.Id;
        /// <summary>Static counter used to generate unique IDs</summary>
        private static int s_queryId = 0;

        /// <summary>Generates the next consecutive query ID.</summary>
        [NonEvent]
        internal static int NextQueryId()
        {
            return Interlocked.Increment(ref s_queryId);
        }

        /// <summary>Enabled for all keywords.</summary>
        private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);

        /// <summary>ETW tasks that have start/stop events.</summary>
        public class Tasks // this name is important for EventSource
        {
            /// <summary>A parallel query.</summary>
            public const EventTask Query = (EventTask)1;
            /// <summary>A fork/join task within a query.</summary>
            public const EventTask ForkJoin = (EventTask)2;
        }

        //-----------------------------------------------------------------------------------
        //        
        // PLINQ Query Event IDs (must be unique)
        //

        /// <summary>The ID of a parallel query begin event.</summary>
        private const int PARALLELQUERYBEGIN_EVENTID = 1;
        /// <summary>The ID of a parallel query end event.</summary>
        private const int PARALLELQUERYEND_EVENTID = 2;
        /// <summary>The ID of a parallel query fork event.</summary>
        private const int PARALLELQUERYFORK_EVENTID = 3;
        /// <summary>The ID of a parallel query join event.</summary>
        private const int PARALLELQUERYJOIN_EVENTID = 4;

        //-----------------------------------------------------------------------------------
        //        
        // PLINQ Query Events
        //

        #region ParallelQueryBegin
        /// <summary>
        /// Denotes the entry point for a PLINQ Query, and declares the fork/join context ID
        /// which will be shared by subsequent events fired by tasks that service this query
        /// </summary>
        /// <param name="queryId">The ID of the query.</param>
        [NonEvent]
        internal void ParallelQueryBegin(int queryId)
        {
            if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
            {
                int taskId = Task.CurrentId ?? 0;
                ParallelQueryBegin(s_defaultSchedulerId, taskId, queryId);
            }
        }

        /// <summary>
        /// Denotes the entry point for a PLINQ query, and declares the fork/join context ID
        /// which will be shared by subsequent events fired by tasks that service this query
        /// </summary>
        /// <param name="taskSchedulerId">The ID of the task scheduler to which the query is scheduled.</param>
        /// <param name="taskId">The ID of the task starting the query; 0 if there is no task.</param>
        /// <param name="queryId">The ID of the query.</param>
        [Event(PARALLELQUERYBEGIN_EVENTID, Level = EventLevel.Informational, Task = PlinqEtwProvider.Tasks.Query, Opcode = EventOpcode.Start)]
        private void ParallelQueryBegin(int taskSchedulerId, int taskId, int queryId)
        {
            WriteEvent(PARALLELQUERYBEGIN_EVENTID, taskSchedulerId, taskId, queryId);
        }
        #endregion

        #region ParallelQueryEnd
        /// <summary>
        /// Denotes the end of PLINQ query that was declared previously with the same query ID.
        /// </summary>
        /// <param name="queryId">The ID of the query.</param>
        [NonEvent]
        internal void ParallelQueryEnd(int queryId)
        {
            if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
            {
                int taskId = Task.CurrentId ?? 0;
                ParallelQueryEnd(s_defaultSchedulerId, taskId, queryId);
            }
        }

        /// <summary>
        /// Denotes the end of PLINQ query that was declared previously with the same query ID.
        /// </summary>
        /// <param name="taskSchedulerId">The ID of the task scheduler to which the query was scheduled.</param>
        /// <param name="taskId">The ID of the task ending the query; 0 if there is no task.</param>
        /// <param name="queryId">The ID of the query.</param>
        [Event(PARALLELQUERYEND_EVENTID, Level = EventLevel.Informational, Task = PlinqEtwProvider.Tasks.Query, Opcode = EventOpcode.Stop)]
        private void ParallelQueryEnd(int taskSchedulerId, int taskId, int queryId)
        {
            WriteEvent(PARALLELQUERYEND_EVENTID, taskSchedulerId, taskId, queryId);
        }
        #endregion

        #region ParallelQueryFork
        /// <summary>
        /// Denotes the start of an individual task that will service a parallel query.
        /// Before this event is fired, the query ID must have been declared with a
        /// ParallelQueryBegin event.
        /// </summary>
        /// <param name="queryId">The ID of the query.</param>
        [NonEvent]
        internal void ParallelQueryFork(int queryId)
        {
            if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
            {
                int taskId = Task.CurrentId ?? 0;
                ParallelQueryFork(s_defaultSchedulerId, taskId, queryId);
            }
        }

        /// <summary>
        /// Denotes the start of an individual task that will service a parallel query.
        /// Before this event is fired, the query ID must have been declared with a
        /// ParallelQueryBegin event.
        /// </summary>
        /// <param name="taskSchedulerId">The ID of the task scheduler to which the task was scheduled.</param>
        /// <param name="taskId">The ID of the task joining the query.</param>
        /// <param name="queryId">The ID of the query.</param>
        [Event(PARALLELQUERYFORK_EVENTID, Level = EventLevel.Verbose, Task = PlinqEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
        private void ParallelQueryFork(int taskSchedulerId, int taskId, int queryId)
        {
            WriteEvent(PARALLELQUERYFORK_EVENTID, taskSchedulerId, taskId, queryId);
        }
        #endregion

        #region ParallelQueryJoin
        /// <summary>
        /// Denotes the end of an individual task that serviced a parallel query.
        /// This should match a previous ParallelQueryFork event with a matching query ID.
        /// </summary>
        /// <param name="queryId">The ID of the query.</param>
        [NonEvent]
        internal void ParallelQueryJoin(int queryId)
        {
            if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
            {
                int taskId = Task.CurrentId ?? 0;
                ParallelQueryJoin(s_defaultSchedulerId, taskId, queryId);
            }
        }

        /// <summary>
        /// Denotes the end of an individual task that serviced a parallel query.
        /// This should match a previous ParallelQueryFork event with a matching query ID.
        /// </summary>
        /// <param name="taskSchedulerId">The ID of the task scheduler to which the task was scheduled.</param>
        /// <param name="taskId">The ID of the task joining the query.</param>
        /// <param name="queryId">The ID of the query.</param>
        [Event(PARALLELQUERYJOIN_EVENTID, Level = EventLevel.Verbose, Task = PlinqEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Stop)]
        private void ParallelQueryJoin(int taskSchedulerId, int taskId, int queryId)
        {
            WriteEvent(PARALLELQUERYJOIN_EVENTID, taskSchedulerId, taskId, queryId);
        }
        #endregion
    }

#endif // !FEATURE_PAL
}