4 using System.Collections.Generic;
5 using System.Diagnostics;
8 using System.Threading;
9 using SiliconStudio.Core.Collections;
11 namespace SiliconStudio.Core.Diagnostics
59 internal static Logger Logger = GlobalLogger.GetLogger(
"Profiler");
60 private static readonly FastList<ProfilingEvent> events =
new FastList<ProfilingEvent>();
61 private static readonly Dictionary<ProfilingKey, ProfilingResult> eventsByKey =
new Dictionary<ProfilingKey, ProfilingResult>();
62 private static readonly List<ProfilingResult> profilingResults =
new List<ProfilingResult>();
63 private static readonly StringBuilder profilerResultBuilder =
new StringBuilder();
64 private static readonly
object Locker =
new object();
65 private static bool enableAll;
66 private static int profileId;
89 profilingKey.Enabled =
false;
102 return enableAll || profilingKey.Enabled;
113 profilingKey.Enabled =
true;
114 foreach (var child
in profilingKey.
Children)
129 profilingKey.Enabled =
false;
130 foreach (var child
in profilingKey.
Children)
147 if (profilingKey == null)
throw new ArgumentNullException(
"profilingKey");
149 var localProfileId = Interlocked.Increment(ref profileId) - 1;
150 var isProfileActive = IsEnabled(profilingKey);
152 return new ProfilingState(localProfileId, profilingKey, isProfileActive);
165 var profiler = New(profilingKey);
181 var profiler = New(profilingKey);
182 profiler.Begin(text);
198 var profiler = New(profilingKey);
199 profiler.Begin(textFormat, textFormatArguments);
217 events.Add(profilingEvent);
222 Logger.
Log(
new ProfilingMessage(profilingEvent.Id, profilingEvent.Key, profilingEvent.Type) { Attributes = profilingEvent.Attributes, ElapsedTime = new TimeSpan((profilingEvent.ElapsedTime * 10000000) / Stopwatch.Frequency), Text = profilingEvent.Text });
225 struct ProfilingResult
228 public long AccumulatedTime;
238 if (events.Count == 0)
239 return "No profiling events.";
242 var elapsedTime = events.Count > 0 ? events[events.Count - 1].TimeStamp - events[0].TimeStamp : 0;
244 foreach (var profilingEvent
in events)
246 ProfilingResult profilingResult;
247 if (!eventsByKey.TryGetValue(profilingEvent.Key, out profilingResult))
249 profilingResult.Key = profilingEvent.Key;
250 profilingResult.MinTime = long.MaxValue;
264 profilingResult.AccumulatedTime += profilingEvent.ElapsedTime;
265 if (profilingEvent.ElapsedTime < profilingResult.MinTime)
266 profilingResult.MinTime = profilingEvent.ElapsedTime;
267 if (profilingEvent.ElapsedTime > profilingResult.MaxTime)
268 profilingResult.MaxTime = profilingEvent.ElapsedTime;
273 profilingResult.Count++;
276 eventsByKey[profilingResult.Key] = profilingResult;
279 foreach (var profilingResult
in eventsByKey)
281 profilingResults.Add(profilingResult.Value);
289 profilingResults.Sort((x1, x2) => Math.Sign(x2.AccumulatedTime - x1.AccumulatedTime));
292 foreach (var profilingResult
in profilingResults)
294 profilerResultBuilder.AppendFormat(
"{0,5:P1} | ", (double)profilingResult.AccumulatedTime / (
double)elapsedTime);
295 AppendTime(profilerResultBuilder, profilingResult.AccumulatedTime);
297 profilerResultBuilder.Append(
" | ");
298 AppendTime(profilerResultBuilder, profilingResult.MinTime);
299 profilerResultBuilder.Append(
" | ");
300 AppendTime(profilerResultBuilder, profilingResult.Count != 0 ? profilingResult.AccumulatedTime / profilingResult.Count : 0);
301 profilerResultBuilder.Append(
" | ");
302 AppendTime(profilerResultBuilder, profilingResult.MaxTime);
304 profilerResultBuilder.AppendFormat(
" | {0:00000} | {1}", profilingResult.Count, profilingResult.Key);
305 profilerResultBuilder.AppendLine();
308 profilingResults.Clear();
310 var result = profilerResultBuilder.ToString();
311 profilerResultBuilder.Clear();
316 private static void AppendTime(StringBuilder builder,
long accumulatedTime)
318 var accumulatedTimeSpan =
new TimeSpan((accumulatedTime * 10000000) / Stopwatch.Frequency);
319 if (accumulatedTimeSpan >
new TimeSpan(0, 0, 1, 0))
321 builder.AppendFormat(
"{0:000.000}m ", accumulatedTimeSpan.TotalMinutes);
323 else if (accumulatedTimeSpan >
new TimeSpan(0, 0, 0, 0, 1000))
325 builder.AppendFormat(
"{0:000.000}s ", accumulatedTimeSpan.TotalSeconds);
329 builder.AppendFormat(
"{0:000.000}ms", accumulatedTimeSpan.TotalMilliseconds);
static void ProcessEvent(ref ProfilingEvent profilingEvent)
A profiler state contains information of a portion of code being profiled. See remarks.
High level CPU Profiler. For usage see remarks.
static ProfilingState New(ProfilingKey profilingKey)
Creates a profiler with the specified name. The returned object must be disposed at the end of the se...
A key to identify a specific profile.
delegate void ProfilerDisposeEventDelegate(ref ProfilingState profilingState)
Delegate called when a ProfilingState is disposed (end of profiling).
static ProfilingState Begin(ProfilingKey profilingKey, string text)
Creates a profiler with the specified key. The returned object must be disposed at the end of the sec...
static bool IsEnabled(ProfilingKey profilingKey)
Enables the specified profiler.
List< ProfilingKey > Children
Gets the children.
Base implementation for ILogger.
static string ReportEvents()
ProfilingMessageType
Type of a profiling message.
static void Enable(ProfilingKey profilingKey)
Enables the specified profiler.
A log message generate by Profiler.
static ProfilingState Begin(ProfilingKey profilingKey, string textFormat, params object[] textFormatArguments)
Creates a profiler with the specified key. The returned object must be disposed at the end of the sec...
static void DisableAll()
Disable all profilers.
void Log(ILogMessage logMessage)
Logs the specified log message.
static void EnableAll()
Enables all profilers.
static ProfilingState Begin(ProfilingKey profilingKey)
Creates a profiler with the specified key. The returned object must be disposed at the end of the sec...
static void Disable(ProfilingKey profilingKey)
Disables the specified profiler.
static void Reset()
Resets the id counter to zero and disable all registered profiles.
A profiling event generated by Profiler.