Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ProfilingState.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Diagnostics;
6 
7 namespace SiliconStudio.Core.Diagnostics
8 {
9  /// <summary>
10  /// A profiler state contains information of a portion of code being profiled. See remarks.
11  /// </summary>
12  /// <remarks>
13  /// This struct is not intended to be used directly but only through <see cref="Profiler.Begin()"/>.
14  /// You can still attach some attributes to it while profiling a portion of code.
15  /// </remarks>
16  public struct ProfilingState : IDisposable
17  {
18  private static readonly Logger Logger = Profiler.Logger;
19  private readonly int profilingId;
20  private readonly ProfilingKey profilingKey;
21  private bool isEnabled;
22  private ProfilerDisposeEventDelegate disposeProfileDelegate;
23  private Dictionary<object, object> attributes;
24  private long startTime;
25  private string beginText;
26 
27  internal ProfilingState(int profilingId, ProfilingKey profilingKey, bool isEnabled)
28  {
29  this.profilingId = profilingId;
30  this.profilingKey = profilingKey;
31  this.isEnabled = isEnabled;
32  this.disposeProfileDelegate = null;
33  attributes = null;
34  beginText = null;
35  startTime = 0;
36  }
37 
38  /// <summary>
39  /// Gets a value indicating whether this instance is initialized.
40  /// </summary>
41  /// <value><c>true</c> if this instance is initialized; otherwise, <c>false</c>.</value>
42  public bool IsInitialized
43  {
44  get
45  {
46  return profilingKey != null;
47  }
48  }
49 
50  /// <summary>
51  /// Gets the profiling unique identifier.
52  /// </summary>
53  /// <value>The profiling unique identifier.</value>
54  public int ProfilingId
55  {
56  get
57  {
58  return profilingId;
59  }
60  }
61 
62  /// <summary>
63  /// Gets the profiling key.
64  /// </summary>
65  /// <value>The profiling key.</value>
67  {
68  get
69  {
70  return profilingKey;
71  }
72  }
73 
74  /// <summary>
75  /// Gets or sets the dispose profile delegate.
76  /// </summary>
77  /// <value>The dispose profile delegate.</value>
78  public ProfilerDisposeEventDelegate DisposeDelegate
79  {
80  get
81  {
82  return disposeProfileDelegate;
83  }
84  set
85  {
86  disposeProfileDelegate = value;
87  }
88  }
89 
90  /// <summary>
91  /// Checks if the profiling key is enabled and update this instance. See remarks.
92  /// </summary>
93  /// <remarks>
94  /// This can be used for long running profiling that are using markers and want to log markers if
95  /// the profiling was activated at runtime.
96  /// </remarks>
97  public void CheckIfEnabled()
98  {
99  isEnabled = Profiler.IsEnabled(profilingKey);
100  }
101 
102  /// <summary>
103  /// Gets the attribute value.
104  /// </summary>
105  /// <param name="key">The key.</param>
106  /// <returns>Value of a key.</returns>
107  /// <remarks>If profiling was not enabled for this profile key, the attribute is not stored</remarks>
108  public object GetAttribute(string key)
109  {
110  if (attributes == null)
111  {
112  return null;
113  }
114  object result;
115  attributes.TryGetValue(key, out result);
116  return result;
117  }
118 
119  /// <summary>
120  /// Sets the attribute value for a specified key. See remarks.
121  /// </summary>
122  /// <param name="key">The key.</param>
123  /// <param name="value">The value.</param>
124  /// <remarks>If profiling was not enabled for this profile key, the attribute is not stored</remarks>
125  public void SetAttribute(string key, object value)
126  {
127  // If profiling is not enabled, doesn't store anything
128  if (!isEnabled) return;
129 
130  if (attributes == null)
131  {
132  attributes = new Dictionary<object, object>();
133  }
134  attributes[key] = value;
135  }
136 
137  public void Dispose()
138  {
139  // Perform a Start event only if the profiling is running
140  if (!isEnabled) return;
141 
142  // Give a chance to the profiling to end and put some property in this profiler state
143  if (disposeProfileDelegate != null)
144  {
145  disposeProfileDelegate(ref this);
146  }
147 
148  End();
149  }
150 
151  /// <summary>
152  /// Emits a Begin profiling event.
153  /// </summary>
154  public void Begin()
155  {
156  EmitEvent(ProfilingMessageType.Begin);
157  }
158 
159  /// <summary>
160  /// Emits a Begin profiling event with the specified text.
161  /// </summary>
162  /// <param name="text">The text.</param>
163  public void Begin(string text)
164  {
165  EmitEvent(ProfilingMessageType.Begin, text);
166  }
167 
168  /// <summary>
169  /// Emits a Begin profiling event with the specified formatted text.
170  /// </summary>
171  /// <param name="textFormat">The text format.</param>
172  /// <param name="textFormatArguments">The text format arguments.</param>
173  public void Begin(string textFormat, params object[] textFormatArguments)
174  {
175  EmitEvent(ProfilingMessageType.Begin, textFormat, textFormatArguments);
176  }
177 
178  /// <summary>
179  /// Emits a Mark event.
180  /// </summary>
181  public void Mark()
182  {
183  EmitEvent(ProfilingMessageType.Mark);
184  }
185 
186  /// <summary>
187  /// Emits a Mark event with the specified text.
188  /// </summary>
189  /// <param name="text">The text.</param>
190  public void Mark(string text)
191  {
192  EmitEvent(ProfilingMessageType.Mark, text);
193  }
194 
195  /// <summary>
196  /// Emits a Mark event with the specified formatted text.
197  /// </summary>
198  /// <param name="textFormat">The text format.</param>
199  /// <param name="textFormatArguments">The text format arguments.</param>
200  public void Mark(string textFormat, params object[] textFormatArguments)
201  {
202  EmitEvent(ProfilingMessageType.Mark, textFormat, textFormatArguments);
203  }
204 
205  /// <summary>
206  /// Emits a End profiling event.
207  /// </summary>
208  public void End()
209  {
210  EmitEvent(ProfilingMessageType.End);
211  }
212 
213  /// <summary>
214  /// Emits a End profiling event with the specified text.
215  /// </summary>
216  /// <param name="text">The text.</param>
217  public void End(string text)
218  {
219  EmitEvent(ProfilingMessageType.End, text);
220  }
221 
222  /// <summary>
223  /// Emits a End profiling event with the specified formatted text.
224  /// </summary>
225  /// <param name="textFormat">The text format.</param>
226  /// <param name="textFormatArguments">The text format arguments.</param>
227  public void End(string textFormat, params object[] textFormatArguments)
228  {
229  EmitEvent(ProfilingMessageType.End, textFormat, textFormatArguments);
230  }
231 
232  private void EmitEvent(ProfilingMessageType profilingType, string text = null)
233  {
234  // Perform a Mark event only if the profiling is running
235  if (!isEnabled) return;
236 
237  var timeStamp = Stopwatch.GetTimestamp();
238 
239  // In the case of begin/end, reuse the text from the `begin`event
240  // if the text is null for `end` event.
241  if (text == null && profilingType != ProfilingMessageType.Mark)
242  text = beginText;
243 
244  if (profilingType == ProfilingMessageType.Begin)
245  {
246  startTime = timeStamp;
247  beginText = text;
248  }
249  else if (profilingType == ProfilingMessageType.End)
250  {
251  beginText = null;
252  }
253 
254  // Create profiler event
255  // TODO ideally we should make a copy of the attributes
256  var profilerEvent = new ProfilingEvent(profilingId, profilingKey, profilingType, timeStamp, timeStamp - startTime, text, attributes);
257 
258  // Send profiler event to Profiler
259  Profiler.ProcessEvent(ref profilerEvent);
260  }
261 
262  private void EmitEvent(ProfilingMessageType profilingType, string textFormat, params object[] textFormatArguments)
263  {
264  // Perform a Mark event only if the profiling is running
265  if (!isEnabled) return;
266 
267  var timeStamp = Stopwatch.GetTimestamp();
268 
269  // In the case of begin/end, reuse the text from the `begin`event
270  // if the text is null for `end` event.
271  var text = textFormat != null ? string.Format(textFormat, textFormatArguments) : profilingType == ProfilingMessageType.Mark ? null : beginText;
272 
273  if (profilingType == ProfilingMessageType.Begin)
274  {
275  startTime = timeStamp;
276  beginText = text;
277  }
278  else if (profilingType == ProfilingMessageType.End)
279  {
280  beginText = null;
281  }
282 
283  // Create profiler event
284  // TODO ideally we should make a copy of the attributes
285  var profilerEvent = new ProfilingEvent(profilingId, profilingKey, profilingType, timeStamp, timeStamp - startTime, text, attributes);
286 
287  // Send profiler event to Profiler
288  Profiler.ProcessEvent(ref profilerEvent);
289  }
290 
291  private TimeSpan GetElapsedTime()
292  {
293  var delta = Stopwatch.GetTimestamp() - startTime;
294  return new TimeSpan((delta * 10000000) / Stopwatch.Frequency);
295  }
296  }
297 }
A profiler state contains information of a portion of code being profiled. See remarks.
A key to identify a specific profile.
Definition: ProfilingKey.cs:11
delegate void ProfilerDisposeEventDelegate(ref ProfilingState profilingState)
Delegate called when a ProfilingState is disposed (end of profiling).
void Begin()
Emits a Begin profiling event.
void SetAttribute(string key, object value)
Sets the attribute value for a specified key. See remarks.
Base implementation for ILogger.
Definition: Logger.cs:10
void End()
Emits a End profiling event.
void Begin(string text)
Emits a Begin profiling event with the specified text.
ProfilingMessageType
Type of a profiling message.
void End(string text)
Emits a End profiling event with the specified text.
void Mark(string textFormat, params object[] textFormatArguments)
Emits a Mark event with the specified formatted text.
void End(string textFormat, params object[] textFormatArguments)
Emits a End profiling event with the specified formatted text.
object GetAttribute(string key)
Gets the attribute value.
void Begin(string textFormat, params object[] textFormatArguments)
Emits a Begin profiling event with the specified formatted text.
void CheckIfEnabled()
Checks if the profiling key is enabled and update this instance. See remarks.
void Mark(string text)
Emits a Mark event with the specified text.