C# Limit Calls Per Second - c#

I am calling a service that only allows 10 calls per second. I am using Stopwatch and Thread.Sleep to limit my calls. Are these the correct tools for this job, or should I be using Timers or some other tool.
public void SomeFunction() {
Stopwatch stopwatch = new Stopwatch();
int numCallsThisSecond = 0;
foreach(MyEvent changedEvent in changedEvents) {
stopwatch.Start();
service.ChangeEvent(changedEvent);
numCallsThisSecond += 1;
stopwatch.Stop();
if(numCallsThisSecond==10 && stopwatch.ElapsedMilliseconds<=1000)
Thread.Sleep((int)(1100-stopwatch.ElapsedMilliseconds));
if(stopwatch.ElapsedMilliseconds>1000) {
stopwatch.Reset();
numCallsThisSecond = 0;
}
}
}
Thank you in advance for any help!

As you already know it can be 10 calls / sec. Code can be simple as follows :
public void SomeFunction()
{
foreach(MyEvent changedEvent in changedEvents)
{
service.ChangeEvent(changedEvent);
Thread.Sleep(100);//you already know it can be only 10 calls / sec
}
}
Edit :
Ok got it, please see if following alternative will be helpful, it only allows 10 or less calls per second depending on how its performing :
public void SomeFunction()
{
DateTime lastRunTime = DateTime.MinValue;
foreach(MyEvent changedEvent in changedEvents)
{
lastRunTime = DateTime.Now;
for (int index = 0; index < 10; index++)
{
if (lastRunTime.Second == DateTime.Now.Second)
{
service.ChangeEvent(changedEvent);
}
else
{
break;//it took longer than 1 sec for 10 calls, so break for next second
}
}
}
}

Related

Impact of locks on multithreading performance [duplicate]

This question already has answers here:
How expensive is the lock statement?
(7 answers)
Closed 5 years ago.
I have a simple class designed to play around with threading. It has a member variable, num, which is initialized to 0, and a method called modify which increments and then decrements num a high number of times. When the program runs, it creates two threads which both run modify, and then starts a timer and starts the threads. It uses a while loop to wait for both threads to finish executing, and then stops the timer and prints the time elapsed to the console. The class:
public class Threading
{
public static void Main()
{
Threading t = new Threading();
t.demo();
}
private int num = 0;
public void doThreading()
{
Thread t1 = new Thread(modify);
Thread t2 = new Thread(modify);
t1.Start();
t2.Start();
Stopwatch timer = new Stopwatch();
timer.Start();
while (thread1.IsAlive || thread2.IsAlive)
{
}
timer.Stop();
Console.WriteLine("Took: " + timer.ElapsedMilliseconds + " milliseconds");
Console.Read();
}
public void modify()
{
for (int i = 0; i < 1000000000; i++)
{
count++;
count--;
}
}
}
After running the program, num will not be 0 because of race conditions. When I add locks to the modify method so that num is 0 after running the program:
public void modify()
{
for (int i = 0; i < 1000000000; i++)
{
lock (this) { count++; }
lock (this) { count--; }
}
}
Then the program takes 8 times as long to execute. I cannot figure out why it would be taking so much longer, I would expect, at most, for it to take 4 times as long to execute. Any idea why it is taking so much longer?
lock can appear to be quite expensive in such a case (all you want is to lock incrementing an int, i.e. make count++ atomic); use Interlocked instead:
public void modify()
{
for (int i = 0; i < 1000000000; i++)
{
Interlocked.Increment(ref count);
Interlocked.Decrement(ref count);
}
}

More efficient way of implementing a countdown timer/clock?

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();
}
}

Run and stop a method for a minute

timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Start();
MyMethodName();
timer1.Stop();
MyMethodName()
-has a for loop for 90,000 entries (and some validations inside that for loop).
for (int i = 0; i <= 90000; i++)
{
//validations go here
}
When the time in timer1 is done for a minute, i want to stop executing other entries in the for loop.
For example, if 45,000 entries are done in a minute, i want to stop executing the method ie. stop the method after a minute.
However the above timer code, executes till all the 90000 records are done looping inside the for loop, somehow the method doesn't run for a minute? Any help?
Two things. Firstly Your timer code is not actually connected to the running of MyMethodName. A timer is designed to run processes when the time has elapsed (and possibly at regular intervals depending on how it is set up.
Secondly and more to the point of your question to abort a loop you have to put code inside the loop. The key would be to have a stopwatch or similar start before your loop and then at the beginning of your loop check how much time has elapsed. If it is a minute or more then break;.
The key thing to note is that you will not stop exactly on a minute but you will finish the iteration of the loop that is running when the minute expires and then stop. This is usually what you want since stopping processing midway through something may cause nasty side effects.
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i =0; i<=90000; i++)
{
if (stopwatch.Elapsed>TimeSpan.FromSeconds(5))
break;
Console.WriteLine(i);
Thread.Sleep(1000);
}
Note that Thread.Sleep is there just because otherwise I get through all 90000 iterations too quickly. ;-)
So you would likely need a much different implementation. Consider this:
public class MyForm
{
private BackgroundWorker _worker;
public MyForm()
{
_worker = new BackgroundWorker();
_worker.DoWork += (s, args) =>
{
var timer = Stopwatch().StartNew();
do
{
// do something
} while (timer.ElapsedMilliseconds < 60000)
};
}
}
and then when you want to run it:
_worker.RunWorkerAsync();
However, you could make it even more robust. You could pass the time in like this:
_worker.RunWorkerAsync(60000);
and then in the DoWork handler, do this:
while (timer.ElapsedMilliseconds < (int)args.Argument)
Further, with the BackgroundWorker, you could support cancellation. Just set the WorkerSupportsCancellation flag to true and then in the condition do this:
while (timer.ElapsedMilliseconds < (int)args.Argument && !_worker.CancellationPending)
so, if necessary, you could do this:
_worker.CancelAsync();
Hmm, use a stopwatch instead
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for(int i= 0; i <= 90000; i++)
{
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
if(ts.Seconds >= 60)
break;
}
However the above timer code, executes till all the 90000 records are done looping inside the for loop, somehow the method doesn't run for a minute? Any help?
The timer will not raise events until you free up the UI thread, which won't occur until after the method completes fully.
If you want to prevent the method from running past a specific duration, you could handle it in your method directly:
MyMethodName(TimeSpan.FromMinutes(1));
Then, in your method:
void MyMethodName(TimeSpan maxRuntime)
{
DateTime expiration = DateTime.Now + maxRuntime;
for (int i = 0; i <= 90000; i++)
{
//validations go here
if (i % 100 == 0) // check every 100?
{
if (DateTime.Now > expiration)
break;
}
}
}
That being said, a better approach would be to push this into a background thread, and cancel as needed.
you can set a flag on in validations to see if it is done or not by hooking up an event handler to the Tick event in the Timer object
//in an area accessible to
//both elements
object readonly _lock = new object();
bool elapsed = false;
where your original code was
elapsed = false;
timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Tick=((sender, everntArgs)=>
{
lock(_lock)
elapsed = true;
});
timer1.Start();
MyMethodName();
timer1.Stop();
Inside of MyMethodName
//inside the loop
for (int i = 0; i <= 90000; i++)
{
//validations go here
lock(_lock)
if(elapsed)
break;
}
If you use a CancellationTokenSource with the CancellationTokenSource(TimeSpan) constructor, it makes it easy to write a method that will cancel an action after a specified time.
You can write a method like so:
public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource(timeout))
action(cancellationTokenSource.Token);
}
And then you can write any action that takes a CancellationToken as a parameter, like this:
private void action(CancellationToken cancel)
{
int i;
for (i = 0; i < 1000000; ++i)
{
if (cancel.IsCancellationRequested)
break;
Thread.Sleep(10); // Simulate work.
}
Console.WriteLine("action() reached " + i);
}
Which you can use like this:
Console.WriteLine("Started at " + DateTime.Now);
RunTimedAction(action, TimeSpan.FromSeconds(10));
Console.WriteLine("Stopped at " + DateTime.Now);
Let's put this together into a complete demo program:
using System;
using System.Threading;
namespace Demo
{
class Program
{
void run()
{
Console.WriteLine("Started at " + DateTime.Now);
RunTimedAction(action, TimeSpan.FromSeconds(10));
Console.WriteLine("Stopped at " + DateTime.Now);
}
private void action(CancellationToken cancel)
{
int i;
for (i = 0; i < 1000000; ++i)
{
if (cancel.IsCancellationRequested)
break;
Thread.Sleep(10); // Simulate work.
}
Console.WriteLine("action() reached " + i);
}
public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource(timeout))
action(cancellationTokenSource.Token);
}
static void Main()
{
new Program().run();
}
}
}

C# sorting values with respect to time

i wanted to create a program like this .
For every minute the time should be printed in the format of
h:m .For every 5 min it should print "break" this should continue for 24 hours ..
like this
0:0
0:1
0:2
0:3
0:4
break
0:6
0:7
0:8
0:9
break
0:11
.
.
.
23:59
i came with a program that solves it ..but i never used DateTime or any time function , i just used Thread.Sleep to dalay printing for 1 minute every time ...
i wanted to use some other method other than Thread.Sleep to solve it ...
so please guide me .. (sorry for my Bad english)
this is how i did with Thread.Sleep .
please provide me with any other solutions
using System;
using System.Threading;
class try22
{
public static void Main()
{
for(int i=0;i<24;i++)
{
for(int j=0;j<60;j++)
{
if(j%5 != 0 || (j == 0 && i == 0))
{
Thread.Sleep(20);
Console.WriteLine(i+":"+j);
}
else if(j%5 == 0 )
{
Thread.Sleep(20);
Console.WriteLine("break");
}
}
}
}
}
thanks guys i came up with the solution of using actual dates instead of array numbers in my problem
im getting weird errors with timer .. :( so i used thread.sleep itslef
using System;
using System.Threading;
class try22
{
public static void Main()
{
DateTime dt1 = new DateTime();
dt1 = DateTime.ParseExact("0:0", "H:m",null);
int cford=dt1.Day+1;
for (; dt1.Day!=cford; )
{
dt1 = addm(dt1);
Console.WriteLine(dts(dt1));
Thread.Sleep(60000);
}
}
public static string dts(DateTime dt)
{
string tmp = dt.ToString("H:m");
if (dt.Minute % 5 == 0)
return "BREAK";
else
return tmp;
}
public static DateTime addm(DateTime dt)
{
return dt.AddMinutes(1);
}
}
Which of these were you asked for?
Show the current time once per minute
Show the current time at the start of every minute like an alarm
Assuming 1, here's a couple of hints in the right direction (which should be helpful either way):
You can get the current date and time as a DateTime object using DateTime.Now
DateTime objects can return custom string output using .ToString("format").
Format is specified with a custom date and time format string. For example, to get the current hour in 24-hour time (without leading zeroes) you could use DateTime.Now.ToString("H").
As per the reference, you can include a string literal (unprocessed string) in your format. For example DateTime.Now.ToString("'Hour is: 'H") would return Hour is: 6
You can get the "minute" value of a DateTime object as an int using .Minute. For example, int minute = DateTime.Now.Minute;
If you want some code to run periodically, one way is to move it into its own method then setup a System.Threading.Timer like this:
void SomeMethod(object state) { /* DO STUFF HERE */ }
// Initialise the timer in your main() method
// As per MSDN for System.Threading.Timer, first number (0) is start delay.
// Second number (60000) is interval in milliseconds (60 seconds)
// This will cause SomeMethod to be called once every 60 seconds starting now.
Timer timer = new Timer(new TimerCallback(SomeMethod), null, 0, 60000);
You will need to stop your application exiting straight away after making the Timer (otherwise it will never get to run). One easy way to do this in a command line application is place a Console.Read() at the end of your Main() method which will wait for user input.
I have used Timer instead of Thread
class Program
{
private static System.Timers.Timer aTimer;
static int j = 0;
static int i = 0;
public static void Main()
{
// Create a timer with a Minute interval.
aTimer = new System.Timers.Timer(60000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 Minute (60000 milliseconds).
aTimer.Interval = 60000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.WriteLine(0 + ":" + 0);
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
j++;
if (j == 60)
{
Console.WriteLine("break");
j = 1;
i = i + 1;
}
if (i == 24)
{
i = 0;
}
if (j % 5 != 0 || (j == 0))
{
Console.WriteLine(i + ":" + j);
}
else if (j % 5 == 0)
{
Console.WriteLine("break");
}
}
}
I am not sure weather you want to use actual System time to start with or just the time since program execution started. Solution i am posting uses time since program started.
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
TimeSpan tt;
static void Main(string[] args)
{
Program p = new Program();
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(p.run));
t.Start();
while (true) ;
}
void run()
{
tt=new TimeSpan(0,1,0);
//Timer interval decides when even will be fired.
Timer t = new Timer(60000);
t.AutoReset = true;
t.Elapsed += new ElapsedEventHandler(t_Elapsed);
t.Start();
}
public void t_Elapsed(object sender, EventArgs e)
{
if (tt.Minutes % 5 == 0)
Console.WriteLine("Break");
Console.WriteLine(tt.Hours.ToString()+":"+tt.Minutes.ToString());
tt = tt.Add(new TimeSpan(0, 1, 0));
}
}
}

Exact time measurement for performance testing [duplicate]

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();

Categories

Resources