-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCodeTimer.cs
197 lines (165 loc) · 6.83 KB
/
CodeTimer.cs
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/******************************************************************************
Module: Wintellect.cs
Notices: Copyright (c) 2008-2009 Jeffrey Richter
******************************************************************************/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32.SafeHandles;
[assembly: CLSCompliant(true)]
///////////////////////////////////////////////////////////////////////////////
namespace CodePerformance
{
public sealed class CycleTime
{
private Boolean m_trackingThreadTime;
private SafeWaitHandle m_handle;
private UInt64 m_startCycleTime;
private CycleTime(Boolean trackingThreadTime, SafeWaitHandle handle)
{
m_trackingThreadTime = trackingThreadTime;
m_handle = handle;
m_startCycleTime = m_trackingThreadTime ? Thread() : Process(m_handle);
}
[CLSCompliant(false)]
public UInt64 Elapsed()
{
UInt64 now = m_trackingThreadTime ? Thread(/*m_handle*/) : Process(m_handle);
return now - m_startCycleTime;
}
public static CycleTime StartThread(SafeWaitHandle threadHandle)
{
return new CycleTime(true, threadHandle);
}
public static CycleTime StartProcess(SafeWaitHandle processHandle)
{
return new CycleTime(false, processHandle);
}
public static UInt64 Thread(IntPtr threadHandle)
{
UInt64 cycleTime;
if (!QueryThreadCycleTime(threadHandle, out cycleTime))
throw new Win32Exception();
return cycleTime;
}
/// <summary>
/// Retrieves the cycle time for the specified thread.
/// </summary>
/// <param name="threadHandle">Identifies the thread whose cycle time you'd like to obtain.</param>
/// <returns>The thread's cycle time.</returns>
[CLSCompliant(false)]
public static UInt64 Thread(SafeWaitHandle threadHandle)
{
UInt64 cycleTime;
if (!QueryThreadCycleTime(threadHandle, out cycleTime))
throw new Win32Exception();
return cycleTime;
}
[CLSCompliant(false)]
public static UInt64 Thread()
{
UInt64 cycleTime;
if (!QueryThreadCycleTime((IntPtr)(-2), out cycleTime))
throw new Win32Exception();
return cycleTime;
}
/// <summary>
/// Retrieves the sum of the cycle time of all threads of the specified process.
/// </summary>
/// <param name="processHandle">Identifies the process whose threads' cycles times you'd like to obtain.</param>
/// <returns>The process' cycle time.</returns>
[CLSCompliant(false)]
public static UInt64 Process(SafeWaitHandle processHandle)
{
UInt64 cycleTime;
if (!QueryProcessCycleTime(processHandle, out cycleTime))
throw new Win32Exception();
return cycleTime;
}
/// <summary>
/// Retrieves the cycle time for the idle thread of each processor in the system.
/// </summary>
/// <returns>The number of CPU clock cycles used by each idle thread.</returns>
[CLSCompliant(false)]
public static UInt64[] IdleProcessors()
{
Int32 byteCount = Environment.ProcessorCount;
UInt64[] cycleTimes = new UInt64[byteCount];
byteCount *= 8; // Size of UInt64
if (!QueryIdleProcessorCycleTime(ref byteCount, cycleTimes))
throw new Win32Exception();
return cycleTimes;
}
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean QueryThreadCycleTime(IntPtr threadHandle, out UInt64 CycleTime);
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean QueryThreadCycleTime(SafeWaitHandle threadHandle, out UInt64 CycleTime);
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean QueryProcessCycleTime(SafeWaitHandle processHandle, out UInt64 CycleTime);
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean QueryIdleProcessorCycleTime(ref Int32 byteCount, UInt64[] CycleTimes);
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetCurrentThread();
}
public sealed class CodeTimer //: IDisposable
{
private Int32 m_collectionCount0;
private Int32 m_collectionCount1;
private Int32 m_collectionCount2;
private Thread m_thread;
private NeuronPerformance.Models.IModel m_model;
private Action<NeuronPerformance.Models.IModel> m_performanceMethod;
private UInt64 outThreadCycles;
public CodeTimer(Action<NeuronPerformance.Models.IModel> perfMethod, NeuronPerformance.Models.IModel model)
{
PrepareForOperation();
m_performanceMethod = perfMethod;
m_model = model;
m_thread = new Thread(PerformanceTest);
}
private void PerformanceTest()
{
PrepareForOperation();
IntPtr p = CycleTime.GetCurrentThread();
UInt64 t = CycleTime.Thread(p);
m_performanceMethod(m_model);
outThreadCycles = CycleTime.Thread(p) - t;
}
public PerformanceStatus Time()
{
m_thread.Start();
m_thread.Join();
return new PerformanceStatus(GC.CollectionCount(0) - m_collectionCount0, GC.CollectionCount(1) - m_collectionCount1, GC.CollectionCount(2) - m_collectionCount2, outThreadCycles);
}
private void PrepareForOperation()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
m_collectionCount0 = GC.CollectionCount(0);
m_collectionCount1 = GC.CollectionCount(1);
m_collectionCount2 = GC.CollectionCount(2);
}
}
public class PerformanceStatus
{
public Int32 GCCount1;
public Int32 GCCount2;
public Int32 GCCount3;
public UInt64 CPUCycles;
public PerformanceStatus(Int32 gc1, Int32 gc2, Int32 gc3, UInt64 cpuCycles)
{
this.GCCount1 = gc1;
this.GCCount2 = gc2;
this.GCCount3 = gc3;
this.CPUCycles = cpuCycles;
}
}
}
//////////////////////////////// End of File //////////////////////////////////