File: Profiler.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
 
namespace Microsoft.Maui.Controls.Internals
{
	/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="Type[@FullName='Microsoft.Maui.Controls.Internals.Profile']/Docs/*" />
	[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable CA1815 // Override equals and operator equals on value types
	public struct Profile : IDisposable
	{
		const int Capacity = 1000;
 
		[DebuggerDisplay("{Name,nq} {Id} {Ticks}")]
		public struct Datum
#pragma warning restore CA1815 // Override equals and operator equals on value types
		{
			public string Name;
			public string Id;
			public long Ticks;
			public int Depth;
			public int Line;
		}
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='Data']/Docs/*" />
		public static List<Datum> Data;
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='IsEnabled']/Docs/*" />
		[EditorBrowsable(EditorBrowsableState.Never)]
		public static bool IsEnabled { get; private set; } = false;
 
		static Stack<Profile> Stack;
		static int Depth = 0;
		static bool Running = false;
		static Stopwatch Stopwatch;
 
		readonly long _start;
		readonly string _name;
		readonly int _slot;
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='Enable']/Docs/*" />
		[EditorBrowsable(EditorBrowsableState.Never)]
		public static void Enable()
		{
			if (!IsEnabled)
			{
				IsEnabled = true;
				Data = new List<Datum>(Capacity);
				Stack = new Stack<Profile>(Capacity);
				Stopwatch = new Stopwatch();
			}
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='Start']/Docs/*" />
		public static void Start()
		{
			if (!IsEnabled)
				return;
 
			Running = true;
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='Stop']/Docs/*" />
		public static void Stop()
		{
			if (!IsEnabled)
				return;
 
			// unwind stack
			Running = false;
			while (Stack.Count > 0)
				Stack.Pop();
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='FrameBegin']/Docs/*" />
		public static void FrameBegin(
			[CallerMemberName] string name = "",
			[CallerLineNumber] int line = 0)
		{
			if (!IsEnabled || !Running)
				return;
 
			FrameBeginBody(name, null, line);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='FrameEnd']/Docs/*" />
		public static void FrameEnd(
			[CallerMemberName] string name = "")
		{
			if (!IsEnabled || !Running)
				return;
 
			FrameEndBody(name);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='FramePartition']/Docs/*" />
		public static void FramePartition(
			string id,
			[CallerLineNumber] int line = 0)
		{
			if (!IsEnabled || !Running)
				return;
 
			FramePartitionBody(id, line);
		}
 
		static void FrameBeginBody(
			string name,
			string id,
			int line)
		{
			if (!Stopwatch.IsRunning)
				Stopwatch.Start();
 
			Stack.Push(new Profile(name, id, line));
		}
 
		static void FrameEndBody(string name)
		{
			var profile = Stack.Pop();
			if (profile._name != name)
				throw new InvalidOperationException(
					$"Expected to end frame '{profile._name}', not '{name}'.");
			profile.Dispose();
		}
 
		static void FramePartitionBody(
			string id,
			int line)
		{
			var profile = Stack.Pop();
			var name = profile._name;
			profile.Dispose();
 
			FrameBeginBody(name, id, line);
		}
 
		Profile(
			string name,
			string id,
			int line)
		{
			this = default(Profile);
			_start = Stopwatch.ElapsedTicks;
 
			_name = name;
 
			_slot = Data.Count;
			Data.Add(new Datum()
			{
				Depth = Depth,
				Name = name,
				Id = id,
				Ticks = -1,
				Line = line
			});
 
			Depth++;
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Profile.xml" path="//Member[@MemberName='Dispose']/Docs/*" />
		public void Dispose()
		{
			if (!IsEnabled)
				return;
			if (Running && _start == 0)
				return;
 
			var ticks = Stopwatch.ElapsedTicks - _start;
			--Depth;
 
			var datum = Data[_slot];
			datum.Ticks = ticks;
			Data[_slot] = datum;
		}
	}
}