1 #region Copyright notice and license
2 
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System;
20 using System.IO;
21 using System.Threading;
22 using Grpc.Core.Internal;
23 
24 namespace Grpc.Core.Profiling
25 {
26     internal static class Profilers
27     {
28         static readonly NopProfiler DefaultProfiler = new NopProfiler();
29         static readonly ThreadLocal<IProfiler> profilers = new ThreadLocal<IProfiler>();
30 
ForCurrentThread()31         public static IProfiler ForCurrentThread()
32         {
33             return profilers.Value ?? DefaultProfiler;
34         }
35 
SetForCurrentThread(IProfiler profiler)36         public static void SetForCurrentThread(IProfiler profiler)
37         {
38             profilers.Value = profiler;
39         }
40 
NewScope(this IProfiler profiler, string tag)41         public static ProfilerScope NewScope(this IProfiler profiler, string tag)
42         {
43             return new ProfilerScope(profiler, tag);
44         }
45     }
46 
47     internal class NopProfiler : IProfiler
48     {
Begin(string tag)49         public void Begin(string tag)
50         {
51         }
52 
End(string tag)53         public void End(string tag)
54         {
55         }
56 
Mark(string tag)57         public void Mark(string tag)
58         {
59         }
60     }
61 
62     // Profiler using Timespec.PreciseNow
63     internal class BasicProfiler : IProfiler
64     {
65         ProfilerEntry[] entries;
66         int count;
67 
BasicProfiler()68         public BasicProfiler() : this(20*1024*1024)
69         {
70         }
71 
BasicProfiler(int capacity)72         public BasicProfiler(int capacity)
73         {
74             this.entries = new ProfilerEntry[capacity];
75         }
76 
Begin(string tag)77         public void Begin(string tag)
78         {
79             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag));
80         }
81 
End(string tag)82         public void End(string tag)
83         {
84             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag));
85         }
86 
Mark(string tag)87         public void Mark(string tag)
88         {
89             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag));
90         }
91 
Reset()92         public void Reset()
93         {
94             count = 0;
95         }
96 
Dump(string filepath)97         public void Dump(string filepath)
98         {
99             using (var stream = File.CreateText(filepath))
100             {
101                 Dump(stream);
102             }
103         }
104 
Dump(TextWriter stream)105         public void Dump(TextWriter stream)
106         {
107             for (int i = 0; i < count; i++)
108             {
109                 var entry = entries[i];
110                 stream.WriteLine(entry.ToString());
111             }
112         }
113 
114         // NOT THREADSAFE!
AddEntry(ProfilerEntry entry)115         void AddEntry(ProfilerEntry entry) {
116             entries[count++] = entry;
117         }
118     }
119 }
120