What is the smallest amount of C# code to get a performance counter up and running?
I simply want to measure the number of CPU cycles and/or time between two points in my code. I've skimmed through all the waffle on the web but it seems like WAY more code than is necessary for such a trivial task. I just want to get a quick measurement up and running and concentrate more on what I'm working on.
I don't think you need a performance counter for that. Do you need more than the timing you can get from StopWatch ? It is very accurate.
Stopwatch watch = Stopwatch.StartNew();
// Do work
watch.Stop();
// elapsed time is in watch.Elapsed
However, to answer the question you actually asked: If you just want to query existing counters, it is in fact quite simple. Here is a full example:
using System;
using System.Diagnostics;
using System.Linq;
static class Test
{
static void Main()
{
var processorCategory = PerformanceCounterCategory.GetCategories()
.FirstOrDefault(cat => cat.CategoryName == "Processor");
var countersInCategory = processorCategory.GetCounters("_Total");
DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time"));
}
private static void DisplayCounter(PerformanceCounter performanceCounter)
{
while (!Console.KeyAvailable)
{
Console.WriteLine("{0}\t{1} = {2}",
performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue());
System.Threading.Thread.Sleep(1000);
}
}
}
Of course, the process will need appropiate permissions to access the performance counters you need.
I like something that can take any code block and wrap it with stopwatch profiling code to measure time spent executing it:
using System.Diagnostics;
using System.Threading;
public static T Profile<T>(Func<T> codeBlock, string description = "")
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
T res = codeBlock();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
const double thresholdSec = 2;
double elapsed = ts.TotalSeconds;
if(elapsed > thresholdSec)
System.Diagnostics.Debug.Write(description + " code was too slow! It took " +
elapsed + " second(s).");
return res;
}
Then call it like that:
Profile(() => MyObj.MySlowMethod());
or:
Profile(() => MyObj.MySlowMethod(), "I can explain why");
There is no trivial way to get this up and running in .NET. However, the simplest way I've found is to build on top of the Enterprise Library which provides some out of the box capabilities for working with performance counters. For example: the Performance Counter Handler
The Enterprise Library also gives you some capabilities for much more easily managing the installation of performance counters.
Additionally, it let's you build on top of it so, you can create an AvergeTimeMeter which allows you to just do this:
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime);
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase);
public void DoSomethingWeWantToMonitor()
{
using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase))
{
// code here that you want to perf mon
}
}
This allows you to simply encapsulate the code you want to monitor in a using block - and concentrate on the code you actually want to work on rather than worrying about all the performance counter infrastructure.
To do this, you'll create a re-usable AverageTimeMeter class like this:
public sealed class AverageTimeMeter : IDisposable
{
private EnterpriseLibraryPerformanceCounter averageCounter;
private EnterpriseLibraryPerformanceCounter baseCounter;
private Stopwatch stopWatch;
private string instanceName;
public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null)
{
this.stopWatch = new Stopwatch();
this.averageCounter = averageCounter;
this.baseCounter = baseCounter;
this.instanceName = instanceName;
this.stopWatch.Start();
}
public void Dispose()
{
this.stopWatch.Stop();
if (this.baseCounter != null)
{
this.baseCounter.Increment();
}
if (this.averageCounter != null)
{
if (string.IsNullOrEmpty(this.instanceName))
{
this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks);
}
else
{
this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks);
}
}
}
}
You have to register your performance counters (shown in the EntLib examples) but this should get your started.
Related
I have a Windows service that uses NetNamedPipe to communicate with other processes on the same machine. It works fine except for one problem: high CPU use. Is there anything I can do to reduce this usage?
To better understand this issue, I made a simple test program that talks to itself over a named pipe and tracks its own CPU use. When using the named pipe infrequently (1 operation per second), CPU use is very low. When using the named pipe frequently (thousands of operations per second), the CPU use increases.
Here is some sample output demonstrating the behaviour. (Note that the CPU uses the Process > % Processor Time counter, which is not as simple as the CPU use you might see in Task Manager.)
NetNamedPipe Passed: 31309 Failed: 0 Elapsed: 10.4 s Rate: 3000 Hz Process CPU: 30.0 %
NetNamedPipe Passed: 13 Failed: 0 Elapsed: 11.0 s Rate: 1 Hz Process CPU: 0.9 %
Ideally, I'd like to continue using NetNamedPipe, but do something to reduce the CPU use. I have experimented with tweaking the optional settings of NetNamedPipeBinding using ideas on Stack Overflow and elsewhere, but was unable to reduce the CPU use. Maybe there is something I am missing?
I realise, that quite possibly, I might have to do something more drastic. I might need to send fewer, larger messages, in "bundles". Or I might need to use a different means of inter-process communication. Any advice on what to look into would be appreciated.
My test program code is below. It targets .NET Framework 4.7.2. I have been running on Windows 10.
Program.cs
using System;
using System.Diagnostics;
using System.Threading;
namespace IpcExperiments
{
class Program
{
private static readonly string MyName = "Alice";
private static readonly string ProcessName = "IpcExperiments";
private static readonly double DesiredRate = 3000; // In Hz
// private static readonly double DesiredRate = Double.MaxValue; // Go as fast as possible!
private static PerformanceCounter ProcessCpu = null;
static void Main(string[] args)
{
ProcessCpu = new PerformanceCounter("Process", "% Processor Time", ProcessName);
Test(new Experiments.NetNamedPipe(), MyName, DesiredRate);
// Optionally, add other tests here.
Console.Write("\r ");
Console.WriteLine();
Console.WriteLine("All tests complete! Press Enter to finish.");
Console.ReadLine();
}
private static void Test(Experiments.IIpcExperiment experiment, string myName, double desiredRate = Double.MaxValue)
{
int i = 0;
int successes = 0;
int fails = 0;
double elapsed = 0;
double rate = 0;
double thisCpu = 0;
double avgCpu = 0;
double cpuCount = 0;
string matchingName = String.Format("Hello {0}!", myName);
string experimentName = experiment.GetExperimentName();
Console.Write("\rCreating {0}...", experimentName);
experiment.Setup();
DateTime startTime = DateTime.Now;
DateTime nextCpuRead = DateTime.MinValue;
while (!Console.KeyAvailable)
{
if (experiment.SayHello(myName).Equals(matchingName))
{
successes++;
}
else
{
fails++;
}
if (nextCpuRead < DateTime.Now)
{
thisCpu = ProcessCpu.NextValue();
if (cpuCount == 0)
{
avgCpu = thisCpu;
}
else
{
avgCpu = ((avgCpu * cpuCount) + thisCpu) / (cpuCount + 1);
}
cpuCount++;
nextCpuRead = DateTime.Now.AddSeconds(1);
}
elapsed = (DateTime.Now - startTime).TotalSeconds;
rate = ((double)i) / elapsed;
Console.Write("\r{0}\tPassed: {1}\tFailed: {2}\tElapsed: {3:0.0} s\tRate: {4:0} Hz\t Process CPU: {5:0.0} %"
, experimentName
, successes
, fails
, elapsed
, rate
, avgCpu);
while (rate > desiredRate && !Console.KeyAvailable)
{
Thread.Sleep(1);
elapsed = (DateTime.Now - startTime).TotalSeconds;
rate = ((double)i) / elapsed;
}
i++;
}
Console.ReadKey(true);
Console.WriteLine();
Console.Write("\rDisposing {0}...", experimentName);
experiment.Shutdown();
}
}
}
IIpcExperiment.cs
namespace IpcExperiments.Experiments
{
interface IIpcExperiment
{
string GetExperimentName();
void Setup();
void Shutdown();
string SayHello(string myName);
}
}
NetNamedPipe.cs
using System;
using System.ServiceModel;
namespace IpcExperiments.Experiments
{
[ServiceContract]
public interface INetNamedPipe
{
[OperationContract]
string SayHello(string myName);
}
public class IpcInterface : INetNamedPipe
{
public string SayHello(string myName)
{
return String.Format("Hello {0}!", myName);
}
}
public class NetNamedPipe : IIpcExperiment
{
private ServiceHost Host;
private INetNamedPipe Client;
public void Setup()
{
SetupHost();
SetupClient();
}
public void Shutdown()
{
Host.Close();
}
public string GetExperimentName()
{
return "NetNamedPipe";
}
public string SayHello(string myName)
{
return Client.SayHello(myName);
}
private void SetupHost()
{
Host = new ServiceHost(typeof(IpcInterface),
new Uri[]{
new Uri(#"net.pipe://localhost")
});
NetNamedPipeBinding nnpb = new NetNamedPipeBinding();
Host.AddServiceEndpoint(typeof(INetNamedPipe)
, nnpb
, "NetNamedPipeExample");
Host.Open();
}
private void SetupClient()
{
NetNamedPipeBinding nnpb = new NetNamedPipeBinding();
ChannelFactory<INetNamedPipe> pipeFactory =
new ChannelFactory<INetNamedPipe>(
nnpb,
new EndpointAddress(#"net.pipe://localhost/NetNamedPipeExample"));
Client = pipeFactory.CreateChannel();
}
}
}
Here's how I solved this in the end.
Before the fix, in the sample code in the question above, I made repeated calls to SayHello and the overhead in doing so consumed a lot of CPU.
After the fix, I am getting the same data through a single Stream. I suspect that the CPU overhead of setting up a stream is approximately the same, but the stream only needs to be set up once. The overall CPU use is much lower.
Streams are supported by WCF named pipes so I didn't have to abandon using named pipes.
You can read about streaming here, or if that link dies put TransferMode.Streaming into your favourite search engine.
My stream needed to be "infinite" so it could push data forever, so I needed to make a custom Stream. This answer on Stack Overflow helped guide me.
I still have some rough edges to work out but the CPU use problem (i.e. the crux of this question) seems to have been solved by this approach.
Just assume I have two pieces of code and I want to check CPU usage and Memory of these codes and compare together, is this a good way to check performance:
public class CodeChecker: IDisposable
{
public PerformanceResult Check(Action<int> codeToTest, int loopLength)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
for(var i = 0; i < loopLength; i++)
{
codeToTest.Invoke(i);
}
stopWatch.Stop();
var process = Process.GetCurrentProcess();
var result = new PerformanceResult(stopWatch.ElapsedMilliseconds, process.PrivateMemorySize64);
return result;
}
}
public class PerformanceResult
{
public long DurationMilliseconds { get; set; }
public long PrivateMemoryBytes { get; set; }
public PerformanceResult(long durationMilliseconds, long privateMemoryBytes)
{
DurationMilliseconds = durationMilliseconds;
PrivateMemoryBytes = privateMemoryBytes;
}
public override string ToString()
{
return $"Duration: {DurationMilliseconds} - Memory: {PrivateMemoryBytes}";
}
}
And:
static void Main(string[] args)
{
Console.WriteLine("Start!");
int loopLength = 10000000;
var collection = new Dictionary<int, Target>();
PerformanceResult result;
using (var codeChecker = new CodeChecker())
{
result = codeChecker.Check((int i) => collection.Add(i, new Target()) , loopLength);
}
Console.WriteLine($"Dict Performance: {result}");
var list = new List<Target>();
using(var codeChecker = new CodeChecker())
{
result = codeChecker.Check((int i) => list.Add(new Target()), loopLength);
}
Console.WriteLine($"List Performance: {result}");
Console.ReadLine();
}
I'm looking for checking performance programmatically and I want to check piece of code specifically not all the application.
Any suggestion to improve aforementioned code?
And I will open to any suggestion for using free tools.
There are lot of factors which may impose a bias into your measurement including CLR and JIT compiler influence, heap state, cold or hot run, overall load in your system, etc. Ideally you need to isolate the pieces of code you'd like to benchmark from each other to exclude mutual impact, benchmark only hot runs, not cold to exclude JIT compilation and other cold run factors and what is most important you need to conduct multiple runs to obtain statistical information as single run can be not representative especially on a system which implies multitasking. Luckily you don't have to do it everything manually - there is great library for bench-marking which does all things mentioned and much more and which is widely used in various .NET projects.
I have written a log class and a function as in the following code:
Log(System.Reflection.MethodBase methodBase, string message)
Every time I log something I also log the class name from the methodBase.Name and methodBase.DeclaringType.Name.
I read the following post Using Get CurrentMethod and I noticed that this method is slow.
Should I use the this.GetType() instead of System.Reflection.MethodBase or I should manually log the class/method name in my log e.g. Log("ClassName.MethodName", "log message)? What is the best practice?
It really depends.
If you use the this.GetType() approach you will lose the method information, but you will have a big performance gain (apparently a factor of 1200, according to your link).
If you offer an interface that lets the caller supply strings (e.g. Log("ClassName.MethodName", "log message"), you will probably gain even better performance, but this makes your API less friendly (the calling developer has to supply the class name and method name).
I know this is an old question, but I figured I'd throw out a simple solution that seems to perform well and maintains symbols
static void Main(string[] args)
{
int loopCount = 1000000; // 1,000,000 (one million) iterations
var timer = new Timer();
timer.Restart();
for (int i = 0; i < loopCount; i++)
Log(MethodBase.GetCurrentMethod(), "whee");
TimeSpan reflectionRunTime = timer.CalculateTime();
timer.Restart();
for (int i = 0; i < loopCount; i++)
Log((Action<string[]>)Main, "whee");
TimeSpan lookupRunTime = timer.CalculateTime();
Console.WriteLine("Reflection Time: {0}ms", reflectionRunTime.TotalMilliseconds);
Console.WriteLine(" Lookup Time: {0}ms", lookupRunTime.TotalMilliseconds);
Console.WriteLine();
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
public static void Log(Delegate info, string message)
{
// do stuff
}
public static void Log(MethodBase info, string message)
{
// do stuff
}
public class Timer
{
private DateTime _startTime;
public void Restart()
{
_startTime = DateTime.Now;
}
public TimeSpan CalculateTime()
{
return DateTime.Now.Subtract(_startTime);
}
}
Running this code gives me the following results:
Reflection Time: 1692.1692ms
Lookup Time: 19.0019ms
Press Enter to exit
For one million iterations, that's not bad at all, especially compared to straight up reflection. The method group is being cast to a Delegate type, you maintain a symbolic link all the way into the logging. No goofy magic strings.
I am new to C# world. I am attempting to calculate time taken by a algorithum for the purpose of comparison. Following code measures the elapsed time from when a subroutine is called until the subroutine returns to the main program.This example is taken from "Data structures through C#" by Michael McMillan.
After running this program the output is Time=0, which is incorrect. The program appears to be logically correct. Can anybody help me. Following is the code
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Chap1
{
class chap1
{
static void Main()
{
int[] nums = new int[100000];
BuildArray(nums);
Timing tObj = new Timing();
tObj.startTime();
DisplayNums(nums);
tObj.stopTime();
Console.WriteLine("Time: " + tObj.result().TotalSeconds);
Console.WriteLine("Start Time: " + tObj.startTime().TotalSeconds);
Console.WriteLine("Duration : " + tObj.result().TotalSeconds);
Console.ReadKey();
}
static void BuildArray(int[] arr)
{
for (int i = 0; i <= 99999; i++)
arr[i] = i;
}
static void DisplayNums(int[] arr)
{
for (int i = 0; i <= arr.GetUpperBound(0); i++)
Console.WriteLine(arr[i]);
}
}
class Timing
{
TimeSpan StartTiming;
TimeSpan duration;
public Timing()
{
StartTiming = new TimeSpan(0);
duration = new TimeSpan(0);
}
public TimeSpan startTime()
{
GC.Collect();
GC.WaitForPendingFinalizers();
StartTiming = Process.GetCurrentProcess().Threads[0].UserProcessorTime;
return StartTiming;
}
public void stopTime()
{
duration = Process.GetCurrentProcess().Threads[0].UserProcessorTime.Subtract(StartTiming);
}
public TimeSpan result()
{
return duration;
}
}
}
The Stopwatch class is designed for this.
UserProcessorTime doesn't begin to have the resolution necessary to measure counting to 100000 in a for loop. Your WriteLine calls won't be included in user time as they are I/O time. Your code might not be running on thread 0. User time isn't updated except at context switches. When you print startTime, you're changing the stored value. There are probably some other things that can go wrong I haven't thought of.
I strongly suggest you use the Stopwatch class which takes advantage of the CPU's performance counters.
You don't use the Timing class anywhere in your main function and I don't see where you print the time either. Is this the EXACT code you're running?
Update per new code:
Don't run it in debug mode... build your release version and then run the executable manually: http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/3f10a46a-ba03-4f5a-9d1f-272a348d660c/
I tested your code and it worked fine when running the release version, but when I was running it in the debugger it was not working properly.
This question already has answers here:
Does using delegates slow down my .NET programs?
(4 answers)
Closed 9 years ago.
Consider the following code:
if (IsDebuggingEnabled) {
instance.Log(GetDetailedDebugInfo());
}
GetDetailedDebugInfo() may be an expensive method, so we only want to call it if we're running in debug mode.
Now, the cleaner alternative is to code something like this:
instance.Log(() => GetDetailedDebugInfo());
Where .Log() is defined such as:
public void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
LogInternal(getMessage.Invoke());
}
}
My concern is with performance, preliminary testing doesn't show the second case to be particularly more expensive, but I don't want to run into any surprises if load increases.
Oh, and please don't suggest conditional compilation because it doesn't apply to this case.
(P.S.: I wrote the code directly in the StackOverflow Ask a Question textarea so don't blame me if there are subtle bugs and it doesn't compile, you get the point :)
No, it shouldn't have a bad performance. After all, you'll be calling it only in debug mode where performance is not at the forefront. Actually, you could remove the lambda and just pass the method name to remove the overhead of an unnecessary intermediate anonymous method.
Note that if you want to do this in Debug builds, you can add a [Conditional("DEBUG")] attribute to the log method.
There is a difference in performance. How significant it is will depend on the rest of your code so I would recommend profiling before embarking on optimisations.
Having said that for your first example:
if (IsDebuggingEnabled)
{
instance.Log(GetDetailedDebugInfo());
}
If IsDebuggingEnabled is static readonly then the check will be jitted away as it knows it can never change. This means that the above sample will have zero performance impact if IsDebuggingEnabled is false, because after the JIT is done the code will be gone.
instance.Log(() => GetDetailedDebugInfo());
public void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
LogInternal(getMessage.Invoke());
}
}
The method will be called every time instance.Log is called. Which will be slower.
But before expending time with this micro optimization you should profile your application or run some performance tests to make sure this is actually a bottle neck in your application.
I was hoping for some documentation regarding performance in such cases, but it seems that all I got were suggestions on how to improve my code... No one seems to have read my P.S. - no points for you.
So I wrote a simple test case:
public static bool IsDebuggingEnabled { get; set; }
static void Main(string[] args)
{
for (int j = 0; j <= 10; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i <= 15000; i++)
{
Log(GetDebugMessage);
if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.ReadLine();
for (int j = 0; j <= 10; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i <= 15000; i++)
{
if (IsDebuggingEnabled) GetDebugMessage();
if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.ReadLine();
}
public static string GetDebugMessage()
{
StringBuilder sb = new StringBuilder(100);
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
sb.Append(rnd.Next(100, 150));
}
return sb.ToString();
}
public static void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
getMessage();
}
}
Timings seem to be exactly the same between the two versions.
I get 145 ms in the first case, and 145 ms in the second case
Looks like I answered my own question.
You can also do this:
// no need for a lambda
instance.Log(GetDetailedDebugInfo)
// Using these instance methods on the logger
public void Log(Func<string> detailsProvider)
{
if (!DebuggingEnabled)
return;
this.LogImpl(detailsProvider());
}
public void Log(string message)
{
if (!DebuggingEnabled)
return;
this.LogImpl(message);
}
protected virtual void LogImpl(string message)
{
....
}
Standard answers:
If you gotta do it, you gotta do it.
Loop it 10^9 times, look at a stopwatch, & that tells you how many nanoseconds it takes.
If your program is big, chances are you have bigger problems elsewhere.
Call getMessage delegate directly instead of calling Invoke on it.
if(IsDebuggingEnabled)
{
LogInternal(getMessage());
}
You should also add null check on getMessage.
I believe delegates create a new thread, so you may be right about it increasing performance.
Why not set up a test run like Dav suggested, and keep a close eye on the number of threads spawned by your app, you can use Process Explorer for that.
Hang on! I've been corrected! Delegates only use threads when you use 'BeginInvoke'... so my above comments don't apply to the way you're using them.