summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/Performance.cs
blob: 2497b082c324f663e69bd49b16334ced40b9e432 (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
´╗┐using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

namespace Xamarin.Forms.Internals
{
	public static class Performance
	{
		static readonly Dictionary<string, Stats> Statistics = new Dictionary<string, Stats>();

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Conditional("PERF")]
		public static void Clear()
		{
			Statistics.Clear();
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public static void Count(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
		{
			string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);

			Stats stats;
			if (!Statistics.TryGetValue(id, out stats))
				Statistics[id] = stats = new Stats();

			stats.CallCount++;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Conditional("PERF")]
		public static void DumpStats()
		{
			Debug.WriteLine(GetStats());
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public static string GetStats()
		{
			var b = new StringBuilder();
			b.AppendLine("ID                                                                                 | Call Count | Total Time | Avg Time");
			foreach (KeyValuePair<string, Stats> kvp in Statistics.OrderBy(kvp => kvp.Key))
			{
				string key = ShortenPath(kvp.Key);
				double total = TimeSpan.FromTicks(kvp.Value.TotalTime).TotalMilliseconds;
				double avg = total / kvp.Value.CallCount;
				b.AppendFormat("{0,-80} | {1,-10} | {2,-10}ms | {3,-8}ms", key, kvp.Value.CallCount, total, avg);
				b.AppendLine();
			}
			return b.ToString();
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Conditional("PERF")]
		public static void Start(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
		{
			string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);

			Stats stats;
			if (!Statistics.TryGetValue(id, out stats))
				Statistics[id] = stats = new Stats();

			stats.CallCount++;
			stats.StartTimes.Push(Stopwatch.GetTimestamp());
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Conditional("PERF")]
		public static void Stop(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
		{
			string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);
			long stop = Stopwatch.GetTimestamp();

			Stats stats = Statistics[id];
			long start = stats.StartTimes.Pop();
			if (!stats.StartTimes.Any())
				stats.TotalTime += stop - start;
		}

		static string ShortenPath(string path)
		{
			int index = path.IndexOf("Xamarin.Forms.");
			if (index > -1)
				path = path.Substring(index + 14);

			return path;
		}

		class Stats
		{
			public readonly Stack<long> StartTimes = new Stack<long>();
			public int CallCount;
			public long TotalTime;
		}
	}
}