I'm writing a small lap counter for slot car races as a little home project. I want to implement a countdown timer, which I've done with the following as a test:
private Thread countdownThread;
private delegate void UpdateTimer(string update);
UpdateTimer ut;
public LapCounterForm()
{
InitializeComponent();
//...
ut += updateTimer;
countdownThread = new Thread(new ThreadStart(startCountdown));
}
private void startCountdown()
{
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
System.Diagnostics.Stopwatch stopwatch = new Stopwatch();
long time = 0;
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds <= 5000)
{
time = 5000 - stopwatch.ElapsedMilliseconds;
TimeSpan ts = TimeSpan.FromMilliseconds(time);
ut(ts.Minutes.ToString().PadLeft(2, '0') + ":" + ts.Seconds.ToString().PadLeft(2, '0') + ":" + ts.Milliseconds.ToString().PadLeft(3, '0'));
}
}
private void updateTimer(string text)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<String>(ut), new object[] { text });
}
else
{
lblCountdownClock.Text = text;
}
}
When I start my thread, it works. I get my 5 second countdown like I want, but I can see that I'm using a lot of CPU in the process (12% of my 8 thread i7 2600k).
I figure I can reduce this load a lot by only updating the UI every 10 milliseconds instead of every millisecond, but I have no idea how to do such, other than using if(time % 10 == 0) before making the TimeSpan and updating the UI but I suspect that will be just as inefficient thanks to the while loop.
Am I reinventing the wheel? I'd like my timer to be as accurate as possible (at least for the slot car lap time recordings, perhaps the UI does not need to be updated so often).
EDIT: I tried commenting out the actual string manipulation and UI update as suggested in the comments. Now when I start my thread my entire UI hangs until the thread exits and I still get 12% CPU usage. I suspect that while loop is eating up a lot of CPU time.
Update: I went with the multimedia timer (here) posted by Kohanz as well as Daniel's answer. I no longer use another thread at all, I just make one of those timer objects and have a tick event handler calculating the time between clicking the start button and the tick event. I can even set the period for my ticks to 1ms so I get my cool looking countdown, and it's apparently using 0% CPU :) I'm quite happy with this.
Dont, just DONT go down this road. You are completely thinking of this in the wrong way. You are basically forcing your thread to freeze for no benefit.
Basically any game works this way: you have an update loop, and whenever that triggers you do neccessary stuff. So for instance if you want to know how much time, you ask some kind of "timer" how much has passed since something happened
Here's a much better way to handle this:
class MyStopwatch {
private DateTime _startTime;
private DateTime _stopTime;
public void start() {
_running = true;
_startTime = DateTime.Now;
}
public void stop() {
_stopTime = DateTime.Now;
_running = false;
}
public double getTimePassed() {
if(_running) {
return (DateTime.Now - _startTime).TotalMilliseconds;
} else {
return (_stopTime - _startTime).TotalMilliseconds;
}
}
}
A bit after the fact, but this shows a way in which you might achieve what you need:
public class LapTimer : IDisposable
{
private readonly System.Diagnostics.Stopwatch _stopWatch = new System.Diagnostics.Stopwatch();
private readonly ConcurrentDictionary<string, List<TimeSpan>> _carLapTimes = new ConcurrentDictionary<string, List<TimeSpan>>();
private readonly Action<TimeSpan> _countdownReportingDelegate;
private readonly TimeSpan _countdownReportingInterval;
private System.Threading.Timer _countDownTimer;
private TimeSpan _countdownTo = TimeSpan.FromSeconds(5);
public LapTimer(TimeSpan countdownReportingInterval, Action<TimeSpan> countdownReporter)
{
_countdownReportingInterval = countdownReportingInterval;
_countdownReportingDelegate = countdownReporter;
}
public void StartRace(TimeSpan countdownTo)
{
_carLapTimes.Clear();
_stopWatch.Restart();
_countdownTo = countdownTo;
_countDownTimer = new System.Threading.Timer(this.CountdownTimerCallback, null, _countdownReportingInterval, _countdownReportingInterval);
}
public void RaceComplete()
{
_stopWatch.Stop();
_countDownTimer.Dispose();
_countDownTimer = null;
}
public void CarCompletedLap(string carId)
{
var elapsed = _stopWatch.Elapsed;
_carLapTimes.AddOrUpdate(carId, new List<TimeSpan>(new[] { elapsed }), (k, list) => { list.Add(elapsed); return list; });
}
public IEnumerable<TimeSpan> GetLapTimesForCar(string carId)
{
List<TimeSpan> lapTimes = null;
if (_carLapTimes.TryGetValue(carId, out lapTimes))
{
yield return lapTimes[0];
for (int i = 1; i < lapTimes.Count; i++)
yield return lapTimes[i] - lapTimes[i - 1];
}
yield break;
}
private void CountdownTimerCallback(object state)
{
if (_countdownReportingDelegate != null)
_countdownReportingDelegate(_countdownTo - _stopWatch.Elapsed);
}
public void Dispose()
{
if (_countDownTimer != null)
{
_countDownTimer.Dispose();
_countDownTimer = null;
}
}
}
class Program
{
public static void Main(params string[] args)
{
using (var lapTimer = new LapTimer(TimeSpan.FromMilliseconds(100), remaining => Console.WriteLine(remaining)))
{
lapTimer.StartRace(TimeSpan.FromSeconds(5));
System.Threading.Thread.Sleep(2000);
lapTimer.RaceComplete();
}
Console.ReadLine();
}
}
Related
I'm building a racing game and I'm working on race times.
I try to build a system to start an instance of a timer with various options.
My little experience is putting me in crisis ... would some good soul want to help me?
This was the idea:
public class Timer {
public float counter;
public bool reset;
public string runtime = "--:--:--";
public string istant = "not istant";
public void startTimer()
{
/* inupdatealternative: counter += Time.deltaTime; */
if(reset == true)
{
counter = 0;
}
else
{
counter = Time.time;
}
var minutes = counter/60; // divide guitime by sixty (minutes)
var seconds = counter%60; // euclidean division (seconds)
var fraction = (counter * 100) % 100; // get fraction of seconds
runtime = string.Format ( "{0:00}:{1:00}:{2:000}", minutes, seconds, fraction);
Debug.Log("in Start: "+runtime);
}
public void resetTimer()
{
reset = true;
}
public string getTimerRuntime()
{
return runtime;
}
public string getTimerIstant()
{
istant = runtime;
return istant;
}
}
in update, for exemple:
var lapTimer = new Timer(); // create a new timer
if(Lap < Pilot.pilotlap )
{
lapTimer.startTimer();
Lap++
}
else if(Lap==Pilot.pilotlap)
{
timerLabel.text = lapTimer.getTimerIstant();
lapTimer.resetTimer();
lapTimer.startTimer();
}
in my head I'm sure someone has already dealt with it ... surely there will be something that manages the times and returns values in various ways: does it exist? or is there anyway how to make or build such a thing?
There is, it's called Stopwatch, it's THE class used in C# to use precise timers, and it's located in the System.Diagnostics namespace.
Using your Update() example, you can use it like this:
// Create a new stopwatch instance
// If the timer is used repeatedly, just instantiate one at start and re-use the same,
// to avoid garbage generation
Stopwatch lapTimer = new Stopwatch();
if(Lap < Pilot.pilotlap )
{
lapTimer.Start();
Lap++
}
else if(Lap==Pilot.pilotlap)
{
lapTimer.Stop();
// ElapsedMilliseconds returns exactly what it says, so you may need to format the value
// before passing it to the timerLabel.text
timerLabel.text = lapTimer.ElapsedMilliseconds.ToString();
lapTimer.Reset();
lapTimer.Start();
}
You can read about the class (its methods, fields and properties) here:
Stopwatch Class Documentation
You are doing a lot of unnecessary bool and local fields copiing and setting there. I would simply use something like
public class Timer
{
private float _startTime;
public bool IsRunning;
// you don't need an extra reset method
// simply pass it as a parameter
public void Start(bool reset = false)
{
if(IsRunning && !reset)
{
Debug.LogWarning("Timer is already running! If you wanted to restart consider passing true as parameter.");
return;
}
_startTime = Time.time;
Debug.Log("in Start: " + GetFormattedTime(_startTime));
IsRunning = true;
}
// depending what stop should do
// since this doesn't use any resources while running you could also simply
// only stick to the Start method and pass in true .. does basically the same
public void Stop()
{
IsRunning = false;
}
// I didn't see any difference between you two methods so I would simply use
public string GetCurrentTime()
{
if(!IsRunning)
{
Debug.LogWarning("Trying to get a time from a Timer that isn't running!");
return "--:--:---";
}
var timeDifference = Time.time - _startTime;
return GetFormattedTime(timeDifference);
}
private static string GetFormattedTime(float time)
{
// e.g. time = 74.6753
var minutes = Mathf.FloorToInt(time / 60f); // e.g. 1 (rounded down)
var seconds = Mathf.FloorToInt(time - 60f * minutes); // e.g. 14 (rounded down)
var fraction = Mathf.RoundToInt((time - seconds) * 1000f); // e.g. 676 (rounded down or up)
// Use a string interpolation for better readability
return $"{minutes:00}:{seconds:00}:{fraction:000}";
}
}
then in your Update you don't want to use
var lapTimer = new Timer(); // create a new timer
all the time since it would create a new timer and you wouldn't get any tracked time ... you rather would use it only once like
private Timer timer;
// just in case you want to keep track of needed times per lap
public List<string> lapTimes = new List<string>();
private void Awake()
{
timer = new Timer();
lapTimes.Clear();
}
private void Update()
{
...
if(Lap < Pilot.pilotlap)
{
timer.Start();
Lap++
}
else if(Lap == Pilot.pilotlap)
{
var currentTime = timer.GetCurrentTime();
timerLabel.text = currentTime;
lapTimes.Add(currentTime);
timer.Start(true)
}
...
}
Note that I don't know if this is all you have in Update or how you use it but you probably also do not want to (re)start the timer and count up the Lap every frame your conditions are true ... there should be more checks involved to make sure this can only be called once per lap ...
Currently I am trying to create a console game. The basic concept is that the user gets a number of randomized letters and has a limited amount of time to make as many words with these letters as possible. An example could be, that the user gets [a,a,c,t,t,e,g,s,o,i] where valid words would be "get", "got", "test", etc. The user input is checked on whether it is present in a word list and whether it consists of letters that are allowed to be used. Unfortunately I have some trouble trying to implement and display the timer for this game.
Please note: My C# knowledge is very limited, as I am just a beginner.
The problem
At the moment I have a background thread that contains a loop with the ReadLine() function. The 'normal' code pauses with the Sleep() function and continues when the time is up. It is heavily inspired by the solution given here. What I am hoping to achieve is to display a timer in the console, that tells the user how many seconds he has left to fill in words. However, I have not figured out how to achieve this.
I have trouble thinking up a solution, because of the following. The reason the timer words is because after the 'normal' code is paused, the Thread containing the loop asking for userinput, is active without interruptions. This means that there are no interruptions that could allow a timer to printed. I have no idea on how to periodically 'pause' the readline function while maintaining its functionality.
So my question to you is, how could I achieve this?
The code
This is a piece of isolated code containing just this functionality. So the words are not tested on whether they meet the requirements.
using System;
using System.Collections.Generic;
using System.Threading;
namespace UnderstandingThreading
{
class Reader
{
private static Thread inputThread;
private static List<string> userInput = new List<string>();
private static bool closeLoop = new bool();
static Reader()
{
inputThread = new Thread(reader);
closeLoop = false;
inputThread.IsBackground = true;
inputThread.Start();
}
private static void reader()
{
while (!closeLoop)
{
userInput.Add(Console.ReadLine());
}
}
public static List<string> ReadLine(int timeOutMilliseconds)
{
Thread.Sleep(timeOutMilliseconds);
closeLoop = true;
return userInput;
}
}
class MainClass
{
public static void Main(string[] args)
{
List<string> allEntries = new List<string>();
Console.WriteLine("Please enter random things for the next 5 seconds");
allEntries = Reader.ReadLine(5000);
for (int i = 0; i < allEntries.Count; i++)
{
Console.WriteLine(allEntries[i]);
}
}
}
}
Thank you,
Sebastiaan
Actually I found a way better way to do and much more easier to implement and to understand. Simply using the class System.Timers.Timer !
class MainClass
{
private static int delay { get; set; }
private static int time_left { get; set; }
public static void Main(string[] args)
{
delay = 8;
time_left = delay;
List<string> allEntries = new List<string>();
Console.WriteLine("Please enter random things for the next 5 seconds");
Console.SetCursorPosition(0, 2);
System.Timers.Timer Timer = new System.Timers.Timer(1000);
Timer.Elapsed += WriteTimeLeft;
Timer.AutoReset = true;
Timer.Enabled = true;
Timer.Start();
allEntries = Reader.ReadLine(10000);
Timer.Stop();
for (int i = 0; i < allEntries.Count; i++)
{
Console.WriteLine(allEntries[i]);
}
Console.Read();
}
public static void WriteTimeLeft(Object source, ElapsedEventArgs e)
{
int currentLineCursorTop = Console.CursorTop;
int currentLineCursorLeft = Console.CursorLeft;
Console.CursorVisible = false;
Console.SetCursorPosition(0, 1);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, 1);
Console.Write(time_left);
Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
Console.CursorVisible = true;
time_left -= 1;
}
Basically, we set a timer which has an interval of 1000ms and we set it as AutoReset, therefore it will fire an event each seconds when it is activated. We just add to the list of the methods launch by the event our custom method WriteTimeLeft(Object source, ElapsedEventArgs e) and we're good to go ! :)
I found a solution to your problem using Task.Delay().
Basically I create as much task as there are seconds and I make each one wait 1 second more than the one before. When a task is completed it calls the function WriteTimeLeft() which take care of displaying correctly the time and letting the user type his answer (I erase the line where I display the time and replace it by the new time and then move back the cursor where it was). To this purpose I added the constant "delay" and the variable "time_left". As this action is really quick the user can type without interuption :)
I believe the code is undertandable but if you have any question do not hesitate to ask :)
This isn't perfect (i'm not a professional of C#) but it'll do what you asked for ;)
class MainClass
{
private static int delay { get; set; }
private static int time_left { get; set; }
public static void Main(string[] args)
{
delay = 10;
time_left = delay;
List<string> allEntries = new List<string>();
Console.WriteLine("Please enter random things for the next 10 seconds");
Console.SetCursorPosition(0, 2);
Timer();
allEntries = Reader.ReadLine(11000);
for (int i = 0; i < allEntries.Count; i++)
{
Console.WriteLine(allEntries[i]);
}
Console.Read();
}
public static void Timer()
{
for (int i = 11; i > 0; i--)
{
var t = Task.Delay(i*1000).ContinueWith(_ => WriteTimeLeft());
}
}
public static void WriteTimeLeft()
{
int currentLineCursorTop = Console.CursorTop;
int currentLineCursorLeft = Console.CursorLeft;
Console.CursorVisible = false;
Console.SetCursorPosition(0, 1);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, 1);
Console.Write(time_left);
Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
Console.CursorVisible = true;
time_left -= 1;
}
}
I'm having some trouble with my DispatchTimer. Every once in a while, it'll "skip" a second or two shown on my UI. It's started in my MainViewModel class where it displays a countdown in my view.
public string Timer
{
get { return _timer; }
set
{
_timer = value;
OnPropertyChanged("Timer");
}
}
public MainViewModel()
{
_countDownTimer = new DispatcherTimer();
_countDownTimer.Tick += async (o, e) => await countdownTimer();
_countDownTimer.Interval = new TimeSpan(0,0,0,1);
_countDownTimer.IsEnabled = true;
_countDownTimer.Start();
}
And here's the method that is called when the countdown goes to zero:
private async Task countdownTimer()
{
TimeSpan TimeRemaining = _next - DateTime.Now;
string t = TimeRemaining.Hours + "h " + TimeRemaining.Minutes + "m " + TimeRemaining.Seconds + "s";
this.Timer = t; // display it on the UI
int secondsRemaining = (int) TimeRemaining.TotalSeconds;
if (secondsRemaining == 0)
{
// do something that takes a while
await Task.Run(() => {
refresIp();
});
}
}
Side note:
The variable _next is simply 5 mins ahead. Once it goes to zero, it goes ahead another 5 mins from the current time: in other words, this countdown happens every 5 mins.
I'm not sure exactly what causes this "hickup", but maybe using await and Task is what's causing the issue versus using threads in this particular case. Though, from my understanding, is that you use await and async for something that can take a while waiting for the result, versus using threads to split up a particular task, hence why the use of await and async. Anyway, some insight would be great.
Example for threading queue book "Accelerated C# 2008" (CrudeThreadPool class) not work correctly. If I insert long job in WorkFunction() on 2-processor machine executing for next task don't run before first is over. How to solve this problem? I want to load the processor to 100 percent
public class CrudeThreadPool
{
static readonly int MAX_WORK_THREADS = 4;
static readonly int WAIT_TIMEOUT = 2000;
public delegate void WorkDelegate();
public CrudeThreadPool()
{
stop = 0;
workLock = new Object();
workQueue = new Queue();
threads = new Thread[MAX_WORK_THREADS];
for (int i = 0; i < MAX_WORK_THREADS; ++i)
{
threads[i] = new Thread(new ThreadStart(this.ThreadFunc));
threads[i].Start();
}
}
private void ThreadFunc()
{
lock (workLock)
{
int shouldStop = 0;
do
{
shouldStop = Interlocked.Exchange(ref stop, stop);
if (shouldStop == 0)
{
WorkDelegate workItem = null;
if (Monitor.Wait(workLock, WAIT_TIMEOUT))
{
// Process the item on the front of the queue
lock (workQueue)
{
workItem = (WorkDelegate)workQueue.Dequeue();
}
workItem();
}
}
} while (shouldStop == 0);
}
}
public void SubmitWorkItem(WorkDelegate item)
{
lock (workLock)
{
lock (workQueue)
{
workQueue.Enqueue(item);
}
Monitor.Pulse(workLock);
}
}
public void Shutdown()
{
Interlocked.Exchange(ref stop, 1);
}
private Queue workQueue;
private Object workLock;
private Thread[] threads;
private int stop;
}
public class EntryPoint
{
static void WorkFunction()
{
Console.WriteLine("WorkFunction() called on Thread 0}", Thread.CurrentThread.GetHashCode());
//some long job
double s = 0;
for (int i = 0; i < 100000000; i++)
s += Math.Sin(i);
}
static void Main()
{
CrudeThreadPool pool = new CrudeThreadPool();
for (int i = 0; i < 10; ++i)
{
pool.SubmitWorkItem(
new CrudeThreadPool.WorkDelegate(EntryPoint.WorkFunction));
}
pool.Shutdown();
}
}
I can see 2 problems:
Inside ThreadFunc() you take a lock(workLock) for the duration of the method, meaning your threadpool is no longer async.
in the Main() method, you close down the threadpool w/o waiting for it to finish. Oddly enough that is why it is working now, stopping each ThreadFunc after 1 loop.
It's hard to tell because there's no indentation, but it looks to me like it's executing the work item while still holding workLock - which is basically going to serialize all the work.
If at all possible, I suggest you start using the Parallel Extensions framework in .NET 4, which has obviously had rather more time spent on it. Otherwise, there's the existing thread pool in the framework, and there are other implementations around if you're willing to have a look. I have one in MiscUtil although I haven't looked at the code for quite a while - it's pretty primitive.
This question already has answers here:
How to measure code performance in .NET?
(18 answers)
Closed 9 years ago.
What is the most exact way of seeing how long something, for example a method call, took in code?
The easiest and quickest I would guess is this:
DateTime start = DateTime.Now;
{
// Do some work
}
TimeSpan timeItTook = DateTime.Now - start;
But how exact is this? Are there better ways?
A better way is to use the Stopwatch class:
using System.Diagnostics;
// ...
Stopwatch sw = new Stopwatch();
sw.Start();
// ...
sw.Stop();
Console.WriteLine("Elapsed={0}",sw.Elapsed);
As others have said, Stopwatch is a good class to use here. You can wrap it in a helpful method:
public static TimeSpan Time(Action action)
{
Stopwatch stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.Elapsed;
}
(Note the use of Stopwatch.StartNew(). I prefer this to creating a Stopwatch and then calling Start() in terms of simplicity.) Obviously this incurs the hit of invoking a delegate, but in the vast majority of cases that won't be relevant. You'd then write:
TimeSpan time = StopwatchUtil.Time(() =>
{
// Do some work
});
You could even make an ITimer interface for this, with implementations of StopwatchTimer, CpuTimer etc where available.
As others said, Stopwatch should be the right tool for this. There can be few improvements made to it though, see this thread specifically: Benchmarking small code samples in C#, can this implementation be improved?.
I have seen some useful tips by Thomas Maierhofer here
Basically his code looks like:
//prevent the JIT Compiler from optimizing Fkt calls away
long seed = Environment.TickCount;
//use the second Core/Processor for the test
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2);
//prevent "Normal" Processes from interrupting Threads
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
//prevent "Normal" Threads from interrupting this thread
Thread.CurrentThread.Priority = ThreadPriority.Highest;
//warm up
method();
var stopwatch = new Stopwatch()
for (int i = 0; i < repetitions; i++)
{
stopwatch.Reset();
stopwatch.Start();
for (int j = 0; j < iterations; j++)
method();
stopwatch.Stop();
print stopwatch.Elapsed.TotalMilliseconds;
}
Another approach is to rely on Process.TotalProcessTime to measure how long the CPU has been kept busy running the very code/process, as shown here This can reflect more real scenario since no other process affects the measurement. It does something like:
var start = Process.GetCurrentProcess().TotalProcessorTime;
method();
var stop = Process.GetCurrentProcess().TotalProcessorTime;
print (end - begin).TotalMilliseconds;
A naked, detailed implementation of the samething can be found here.
I wrote a helper class to perform both in an easy to use manner:
public class Clock
{
interface IStopwatch
{
bool IsRunning { get; }
TimeSpan Elapsed { get; }
void Start();
void Stop();
void Reset();
}
class TimeWatch : IStopwatch
{
Stopwatch stopwatch = new Stopwatch();
public TimeSpan Elapsed
{
get { return stopwatch.Elapsed; }
}
public bool IsRunning
{
get { return stopwatch.IsRunning; }
}
public TimeWatch()
{
if (!Stopwatch.IsHighResolution)
throw new NotSupportedException("Your hardware doesn't support high resolution counter");
//prevent the JIT Compiler from optimizing Fkt calls away
long seed = Environment.TickCount;
//use the second Core/Processor for the test
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2);
//prevent "Normal" Processes from interrupting Threads
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
//prevent "Normal" Threads from interrupting this thread
Thread.CurrentThread.Priority = ThreadPriority.Highest;
}
public void Start()
{
stopwatch.Start();
}
public void Stop()
{
stopwatch.Stop();
}
public void Reset()
{
stopwatch.Reset();
}
}
class CpuWatch : IStopwatch
{
TimeSpan startTime;
TimeSpan endTime;
bool isRunning;
public TimeSpan Elapsed
{
get
{
if (IsRunning)
throw new NotImplementedException("Getting elapsed span while watch is running is not implemented");
return endTime - startTime;
}
}
public bool IsRunning
{
get { return isRunning; }
}
public void Start()
{
startTime = Process.GetCurrentProcess().TotalProcessorTime;
isRunning = true;
}
public void Stop()
{
endTime = Process.GetCurrentProcess().TotalProcessorTime;
isRunning = false;
}
public void Reset()
{
startTime = TimeSpan.Zero;
endTime = TimeSpan.Zero;
}
}
public static void BenchmarkTime(Action action, int iterations = 10000)
{
Benchmark<TimeWatch>(action, iterations);
}
static void Benchmark<T>(Action action, int iterations) where T : IStopwatch, new()
{
//clean Garbage
GC.Collect();
//wait for the finalizer queue to empty
GC.WaitForPendingFinalizers();
//clean Garbage
GC.Collect();
//warm up
action();
var stopwatch = new T();
var timings = new double[5];
for (int i = 0; i < timings.Length; i++)
{
stopwatch.Reset();
stopwatch.Start();
for (int j = 0; j < iterations; j++)
action();
stopwatch.Stop();
timings[i] = stopwatch.Elapsed.TotalMilliseconds;
print timings[i];
}
print "normalized mean: " + timings.NormalizedMean().ToString();
}
public static void BenchmarkCpu(Action action, int iterations = 10000)
{
Benchmark<CpuWatch>(action, iterations);
}
}
Just call
Clock.BenchmarkTime(() =>
{
//code
}, 10000000);
or
Clock.BenchmarkCpu(() =>
{
//code
}, 10000000);
The last part of the Clock is the tricky part. If you want to display the final timing, its up to you to choose what sort of timing you want. I wrote an extension method NormalizedMean which gives you the mean of the read timings discarding the noise. I mean I calculate the the deviation of each timing from the actual mean, and then I discard the values which was farer (only the slower ones) from the mean of deviation (called absolute deviation; note that its not the often heard standard deviation), and finally return the mean of remaining values. This means, for instance, if timed values are { 1, 2, 3, 2, 100 } (in ms or whatever), it discards 100, and returns the mean of { 1, 2, 3, 2 } which is 2. Or if timings are { 240, 220, 200, 220, 220, 270 }, it discards 270, and returns the mean of { 240, 220, 200, 220, 220 } which is 220.
public static double NormalizedMean(this ICollection<double> values)
{
if (values.Count == 0)
return double.NaN;
var deviations = values.Deviations().ToArray();
var meanDeviation = deviations.Sum(t => Math.Abs(t.Item2)) / values.Count;
return deviations.Where(t => t.Item2 > 0 || Math.Abs(t.Item2) <= meanDeviation).Average(t => t.Item1);
}
public static IEnumerable<Tuple<double, double>> Deviations(this ICollection<double> values)
{
if (values.Count == 0)
yield break;
var avg = values.Average();
foreach (var d in values)
yield return Tuple.Create(d, avg - d);
}
Use the Stopwatch class
System.Diagnostics.Stopwatch is designed for this task.
Stopwatch is fine, but loop the work 10^6 times, then divide by 10^6.
You'll get a lot more precision.
I'm using this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(myUrl);
System.Diagnostics.Stopwatch timer = new Stopwatch();
timer.Start();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
statusCode = response.StatusCode.ToString();
response.Close();
timer.Stop();