I try to calculate time between operations.
So,write two methods with equal code ,but use different ways.
At first way i do like that:
private static void calcAverageTimeUid(ISomeObject someObj, int N,ISnapshot _Snapshot)
{
Stopwatch stopWatch = new Stopwatch();
int averageTime = 0;
var uid = someObj.Uid;
for (int i = 0; i < N; i++)
{
stopWatch.Start();
var coll = _Snapshot.GetObject(uid);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
averageTime = averageTime + ts.Milliseconds;
}
averageTime = averageTime / N;
}
And i have result averageTime such as 500 milliseconds. N=1000000 and more.
But , i rewrite this method to two methods: mainCalc ,wich should contains come other methods,f.e.
to get average time of uid,id,name and so on.
mainCalc:
private static void mainCalc(ISomeObject someObj,int N,ISnapshot _Snapshot)
{
int averageTimeUID = 0;
for (int i = 0; i < N; i++)
{
var tmp=calcAverageTimeUid2(someObj,N,_Snapshot);
averageTimeUID+=tmp;
}
averageTimeUID = averageTimeUID / N;
}
And other method:
private static int calcAverageTimeUid2(ISomeObject someObj,int N,ISnapshot _Snapshot)
{
Stopwatch stopWatch = new Stopwatch();
var prop = someObj.Uid;
stopWatch.Start();
var obj = _Snapshot.GetObject(prop);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
return ts.Milliseconds;
}
So, i run mainCalc and run calcAcerageTimeUid2 in this method.And result of stopWatch=0 milliseconds!
It is wrong result or not? I dont understand-what way of use stopWatch right?
P.S. delete one of excess StopWatch.
P.P.S. Thank all of you!
Your first routine should be
for (int i = 0; i < N; i++)
{
stopWatch.Start();
var coll = _Snapshot.GetObject(uid);
stopWatch.Stop();
}
averageTime = stopWatch.Elapsed / N;
Note, stopWatch.Start() does not reset the stopwatch back to zero.
Milliseconds is not TotalMilliseconds.
Milliseconds is the entire number of milliseconds of the TimeSpan. Not the total milliseconds which is a double, so you are losing the precision under 1ms.
And why do you return an int, instead of the TimeSpan?
Try this code :
private static void mainCalc(ISomeObject someObj, int N, ISnapshot _Snapshot)
{
var averageTimeUID = TimeSpan.Zero;
for (int i = 0; i < N; i++)
{
averageTimeUID += calcAverageTimeUid2(someObj,N,_Snapshot);
}
averageTimeUID = new TimeSpan( averageTimeUID.Ticks / N );
}
The other method:
private static TimeSpan calcAverageTimeUid2(ISomeObject someObj, int N, ISnapshot _Snapshot)
{
var stopWatch = new Stopwatch();
var prop = someObj.Uid;
stopWatch.Start();
var obj = _Snapshot.GetObject(prop);
stopWatch.Stop();
return stopWatch.Elapsed;
}
The reason you get different results is because you are rounding the number of milliseconds in different places. In your first method, you use one stopwatch and continuously Start() and Stop() it. Your operation must take less than 1 ms, but when you repeatedly start and stop the same stopwatch, the total number of ticks will still increase. That is why with N=1000000 you got only 500 ms.
In the second method, you start and stop a new stopwatch each time, and return the milliseconds. Since each operation is averaging 500/1000000 = 0.00005 ms, the ticks of the stopwatch will accumulate some small value, but the ElapsedMilliseconds (or Milliseconds of the TimeSpan) will still be 0.
EDIT: To solve your problems, the first loop should use the final Elapsed value of the stopwatch once the loop is complete (like the 2nd example in sgmoore's answer). The second method should return the ticks from the method rather than milliseconds and then calculate the milliseconds from the tick frequency of the stopwatch.
In summary, the first operation you are summing a bunch of values like 0.00005, in the second you are summing a bunch of 0s.
Related
This question already has answers here:
Is DateTime.Now the best way to measure a function's performance? [closed]
(16 answers)
Closed 8 years ago.
I have this code:
var userId = Int32.Parse(User.Identity.GetUserId());
using (var context = new IdentityContext())
{
roleId = context.Database.SqlQuery<int>("SELECT RoleId FROM AspNetUserRoles where UserId = " + userId).FirstOrDefault();
}
Is there a very quick and simple way I could time how long this takes to execute. Even if the answer is put into a variable after this code block that would be enough as I can debug and see how long it took.
Use stopwatch :
using System.Diagnostics;
...
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var userId = Int32.Parse(User.Identity.GetUserId());
using (var context = new IdentityContext())
{
roleId = context.Database.SqlQuery<int>("SELECT RoleId FROM AspNetUserRoles where UserId = " + userId).FirstOrDefault();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",ts.Hours, ts.Minutes, ts.Seconds,ts.Milliseconds / 10);
u can put this code before the region:
DateTime start = DateTime.Now;
and this code after it:
DateTime end = DateTime.Now;
TimeSpan span = end - start;
and then in debug mode you can see the value of span;
You have four options, at least.
Small test project I did...
DateTime Checker
DateTime begin = DateTime.UtcNow;
//what you want to control...
DateTime end = DateTime.UtcNow;
Console.WriteLine("DateTime.UtcNow measured time: {0} ms", (end - begin).TotalMilliseconds);
Progress Checker
using System.Diagnostics;
...
TimeSpan begin = Process.GetCurrentProcess().TotalProcessorTime;
//what you want to control...
TimeSpan end = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine("Process.TotalProcessor measured time: {0} ms", (end - begin).TotalMilliseconds);
StopWatch Checker
using System.Diagnostics;
...
Stopwatch watch = new Stopwatch();
watch.Start();
//what you want to control...
watch.Stop();
Console.WriteLine("Stopwatch measured time: {0} ms", watch.ElapsedMilliseconds);
TickCounter Checker
int start = Environment.TickCount;
//what you want to control...
int duration = Environment.TickCount - start;
Console.WriteLine("TickCount measured time: {0} ms", duration);
Stopwatch is your friend
// Create new stopwatch
Stopwatch stopwatch = new Stopwatch();
// Begin timing
stopwatch.Start();
// Do something
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(1);
}
// Stop timing
stopwatch.Stop();
I have a method which should generate a unique 10-character timestamp in Base36, with microsecond resolution. However, it is failing uniqueness tests. How can this be?
private static string _lastValue = string.Empty;
private static readonly DateTime _epoch = DateTime.SpecifyKind(new DateTime(1970,1,1), DateTimeKind.Utc);
private static readonly DateTime _lastInitialized = DateTime.Now;
private static readonly Stopwatch _sw = Stopwatch.StartNew();
public static TimeSpan EpochToStopwatchStart()
{
return _lastInitialized.Subtract(_epoch);
}
public static string GetBase36Timestamp()
{
string result;
do
{
// _sw is a running Stopwatch; Microseconds = ticks / 10
long microseconds = EpochToStopwatchStart().Add(_sw.Elapsed).Ticks / 10L;
result = MicrosecondsToBase36(microseconds);
}
// MicrosecondsToBase36 encodes the Int64 value; the while() loop compares to a
// tracking field to ensure the encoded value changes from the previous one:
while (result == _lastValue);
_lastValue = result;
return result;
}
I know I discard some resolution, but this requires 10 characters in Base36, and the method checks the encoded value anyway. Unexpected dupes happen during a single run. To simplify the problem I run the tests single-threaded. I expect either the answer will be quite interesting, or I will be quite embarrassed for some very silly oversight in the question.
What happens if you add Thread.Sleep(1); in your do/while loop? You are quite possibly getting more than one microsecond generated per iteration.
Analysis
Creating a multi-threaded performance test reveals that despite the while loop, the function is able to exit at a rate of greater than once per microsecond:
static void Main(string[] args)
{
List<string> timeStamps = null; ;
int calls = 1000000;
int maxThreads = 5;
for (int threadCount = 1; threadCount <= maxThreads; threadCount++)
{
timeStamps = new List<string>(calls * maxThreads);
var userThread = new ThreadStart(() =>
{
for (int n = 0; n < calls; n++)
{
timeStamps.Add(TimeStampClass.GetBase36Timestamp());
}
});
Thread[] threads = new Thread[threadCount];
var stopwatch = Stopwatch.StartNew();
for (int j = 0; j < threadCount; j++)
{
threads[j] = new Thread(userThread);
threads[j].Start();
}
for (int j = 0; j < threadCount; j++)
{
threads[j].Join();
}
stopwatch.Stop();
Console.WriteLine("threadCount = {0}\n ------------------", threadCount);
Console.WriteLine("{0} calls in {1} milliseconds", timeStamps.Count, stopwatch.ElapsedMilliseconds);
Console.WriteLine("{0} ticks per call", (double)stopwatch.Elapsed.Ticks / (double)timeStamps.Count);
Console.WriteLine();
}
The resulting output is:
threadCount = 1
------------------
1000000 calls in 1080 milliseconds
10.802299 ticks per call
threadCount = 2
------------------
1985807 calls in 1379 milliseconds
6.94705779564681 ticks per call
threadCount = 3
------------------
2893411 calls in 1731 milliseconds
5.98568471606695 ticks per call
threadCount = 4
------------------
3715722 calls in 2096 milliseconds
5.64319478152564 ticks per call
threadCount = 5
------------------
4611970 calls in 2395 milliseconds
5.19515413153164 ticks per call
Solution for multi-threaded environment:
Surround your while loop with a lock on _lastValue:
public static string GetBase36Timestamp()
{
string result;
lock (_lastValue)
{
do
{
// _sw is a running Stopwatch; Microseconds = ticks / 10
long microseconds = EpochToStopwatchStart().Add(_sw.Elapsed).Ticks / 10L;
result = MicrosecondsToBase36(microseconds);
} while (result == _lastValue);
}
return result;
}
I think you need to use System.Threading.Interlocked.CompareExchange() to do a thread-safe compare-and-swap as an atomic operation. See Interlocked Operations for details. In a nutshell, you ...
Get a copy of the state you want to change as a local variable.
Perform your computation to get the new state
Execute Interlocked.CompareExchange(), which returns the current old-value.
if your local copy of old-value is different than the return value, the swap failed: repeat the above.
otherwise, you're good to go.
Here's a simplified example, riffing off your work:
class TimeStamp
{
static readonly DateTime unixEpoch = new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc) ;
static readonly long BaseMicroseconds = (DateTime.UtcNow-unixEpoch).Ticks / 10L ;
static readonly Stopwatch Stopwatch = Stopwatch.StartNew() ;
static long State = TimeSpan.MinValue.Ticks ;
private long OffsetInMicroseconds ;
private TimeStamp()
{
long oldState ;
long newState ;
do
{
oldState = State ;
newState = Stopwatch.Elapsed.Ticks / 10L ;
} while ( oldState == newState
|| oldState != Interlocked.CompareExchange( ref State , newState , oldState )
) ;
this.OffsetInMicroseconds = newState ;
return ;
}
public static TimeStamp GetNext()
{
return new TimeStamp() ;
}
public override string ToString()
{
long v = BaseMicroseconds + this.OffsetInMicroseconds ;
string s = v.ToString() ; // conversion to Base 36 not implemented ;
return s ;
}
}
I have measured the execution time for two ways of calculating the power of 2:
1) Inline
result = b * b;
2) With a simple function call
result = Power(b);
When running in Debug mode, everything is as expected: Calling a function is considerably more expensive than doing the calculation in line (385 ms in line vs. 570 ms function call).
In release mode, I'd expect the compiler to speed up execution time of the function call considerably because the compiler would inline internally the very small Power() function. But I'd NOT expect the function call to be FASTER than the manual inlined calculation.
Most astonishingly this is the case: In the release build, the first run needs 109 ms and the second run with the call to Power() needs only 62 ms.
How can a function call be faster than manual inlining?
Here is the program for your reproduction:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Test");
// 1. Calculating inline without function call
Stopwatch sw = Stopwatch.StartNew();
for (double d = 0; d < 100000000; d++)
{
double res = d * d;
}
sw.Stop();
Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);
// 2. Calulating power with function call
Stopwatch sw2 = Stopwatch.StartNew();
for (int d = 0; d < 100000000; d++)
{
double res = Power(d);
}
sw2.Stop();
Console.WriteLine("Function: " + sw2.ElapsedMilliseconds);
Console.ReadKey();
}
static double Power(double d)
{
return d * d;
}
}
Your test is wrong. In the second part you use a int d instead of a double. Maybe it explains the time difference.
As Xavier correctly spotted, you are using double in one loop and int in the other. Changing both to the same type will make the results the same - I tested it.
Furthermore: What you are really measuring here is the duration of additions and comparisons. You are not measuring the duration of the squaring of d, because it simply is not happening: In a release build, the optimizer completely removes the body of the loop, because the result is not used. You can confirm this by commenting out the body of the loop. The duration will be the same.
Daniel Hilgarth is right, calculation is not happening at all as the result of is not used (which is probably not the case in Debug mode). Try the following example and you'll get correct results:
static void Main(string[] args)
{
Console.WriteLine("Starting Test");
var list = new List<int>();
// 1. Calculating inline without function call
Stopwatch sw = Stopwatch.StartNew();
for (int d = 0; d < 100000000; d++)
{
int res = d * d;
list.Add(res);
}
sw.Stop();
Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);
// 2. Calulating power with function call
list = new List<int>();
Stopwatch sw2 = Stopwatch.StartNew();
for (int d = 0; d < 100000000; d++)
{
int res = Power(d);
list.Add(res);
}
sw2.Stop();
Console.WriteLine("Function: " + sw2.ElapsedMilliseconds);
Console.ReadKey();
}
I have a requirement in my project (C#, VS2010, .NET 4.0) that a particular for loop must finish within 200 milliseconds. If it doesn't then it has to terminate after this duration without executing the remaining iterations. The loop generally goes for i = 0 to about 500,000 to 700,000 so the total loop time varies.
I have read following questions which are similar but they didn't help in my case:
What is the best way to exit out of a loop after an elapsed time of 30ms in C++
How to execute the loop for specific time
So far I have tried using a Stopwatch object to track the elapsed time but it's not working for me. Here are 2 different methods I have tried so far:
Method 1. Comparing the elapsed time within for loop:
Stopwatch sw = new Stopwatch();
sw.Start();
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (sw.Elapsed > TimeSpan.FromMilliseconds(200))
break;
}
sw.Stop();
This doesn't work because if (sw.Elapsed > TimeSpan.FromMilliseconds(200)) takes more than 200 milliseconds to complete. Hence useless in my case. I am not sure whether TimeSpan.FromMilliseconds() generally takes this long or it's just in my case for some reason.
Method 2. Creating a separate thread to compare time:
Stopwatch sw = new Stopwatch();
sw.Start();
bool bDoExit = false;
int msLimit = 200;
System.Threading.ThreadPool.QueueUserWorkItem((x) =>
{
while (bDoExit == false)
{
if (sw.Elapsed.Milliseconds > msLimit)
{
bDoExit = true;
sw.Stop();
}
System.Threading.Thread.Sleep(10);
}
});
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (bDoExit == true)
break;
}
sw.Stop();
I have some other code in the for loop that prints some statistics. It tells me that in case of Method 2, the for loop definitely breaks before completing all the iterations but the loop timing is still 280-300 milliseconds.
Any suggestions to break a for loop strictly with-in 200 milliseconds or less?
Thanks.
For a faster comparison try comparing
if(sw.ElapsedMilliseconds > 200)
break;
You should do that check in the beggining of your loop and also during the processing, ("// Do some stuff" part of the code) because it is possible, for example, that processing starts at 190 (beginning of the loop), lasts 20 and ends at 210.
You could also measure average execution time of your processing (this is approximate because it relies on average time), this way loop should last 200 milliseconds or less, here is a demo that you can put in a Main method of a Console application and easily modify it for your application:
Stopwatch sw = new Stopwatch();
sw.Start();
string a = String.Empty;
int i;
decimal sum = 0, avg = 0, beginning = 0, end = 0;
for (i = 0; i < 700000; i++) // nEntries is typically more than 500,000
{
beginning = sw.ElapsedMilliseconds;
if (sw.ElapsedMilliseconds + avg > 200)
break;
// Some processing
a += "x";
int s = a.Length * 100;
Thread.Sleep(19);
/////////////
end = sw.ElapsedMilliseconds;
sum += end - beginning;
avg = sum / (i + 1);
}
sw.Stop();
Console.WriteLine(
"avg:{0}, count:{1}, milliseconds elapsed:{2}", avg, i + 1,
sw.ElapsedMilliseconds);
Console.ReadKey();
Another option would be to use CancellationTokenSource:
CancellationTokenSource source = new CancellationTokenSource(100);
while(!source.IsCancellationRequested)
{
// Do stuff
}
Use the first one - simple and have better chances to be precise than second one.
Both cases have the same kind of termination condition, so both should behave are more-or-less the same. Second is much more complicated due to usage of threads and Sleep, so I'd use first one. Also second one is much less precise due to sleeps.
There are abolutely no reasons for TimeSpan.FromMilliseconds(200) to take any significant amount of time (as well as calling it in every iteration).
Using cancellation token:
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)).Token;
while (!cancellationToken.IsCancellationRequested)
{
//Do stuff...
}
I don't know if this is that exactly, but I think it's worth a try using a System.Timers.Timer:
int msLimit = 200;
int nEntries = 500000;
bool cancel = false;
System.Timers.Timer t = new System.Timers.Timer();
t.Interval = msLimit;
t.Elapsed += (s, e) => cancel = true;
t.Start();
for (int i = 0; i < nEntries; i++)
{
// do sth
if (cancel) {
break;
}
}
What is the performance penalty incurred by adding the C# Stop Watch to an object?
Should not be that significant in the context of C# programming. If it proves to be significant, reconsider your need/use of Stopwatch and C#.
You can always try to benchmark it yourself by implementing it 1000 times, timing it, and then dividing the results by 1000. It's difficult to say precisely how performance demanding this feature is, but you could compare it to some other simple operations and see how it relates to.
Since I desired to use some timing statistics in an object creation pool to optimize its performance on-the-fly, I needed to know if adding a Stopwatch to monitor the timing would adversely affect the performance of the object creation. I wanted to time a typical object creation (appr. 20-30 ms) to optimize the timeout for the Task creating them, but only if adding the Stopwatch did not noticeably slow down the loop.
So I wrote this test program to separately time the overhead of creation, Start(), Stop() and elapsed time retrieval of the Stopwatch.
using System;
using System.Diagnostics;
namespace SO9925598_Stopwatch_overhead
{
class Program
{
private const int nLoops = 10000;
private const double nLoopsDouble = nLoops;
private const int waitTime = 2; //ms
static void Main(string[] args)
{
Stopwatch stopwatchTimingTheTest = new Stopwatch();
double frequencyConversionFactor = 1000.0 / Convert.ToDouble(Stopwatch.Frequency); // ms per click
Stopwatch stopwatchUnderTest;
// Instantiation
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest = new Stopwatch();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest = null;
}
long elapsed = stopwatchTimingTheTest.ElapsedTicks;
double overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Creation overhead {overhead} ms per Stopwatch instantiation. (Based on {nLoops} trials).");
// Further tests can all use the same object
stopwatchUnderTest = new Stopwatch();
// Start
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Start() overhead {overhead} ms.");
// Stop
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Stop() overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedTicks;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedTicks overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedMilliseconds;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedMilliseconds overhead {overhead} ms.");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
These were the results:
Creation overhead 0,00011756 ms per Stopwatch instantiation. (Based on 10000 trials).
Stopwatch.Start() overhead 0,000256 ms.
Stopwatch.Stop() overhead 0,00023665 ms.
Stopwatch.ElapsedTicks overhead 0,00010946 ms.
Stopwatch.ElapsedMilliseconds overhead 0,00011758 ms.
The times are the average time per single call of the method based on 10000 samples.
The program was running on a machine with Intel Core i7-8850H CPU at 2.60 GHz with Windows 10 operating system.
Conclusion: for my application where the object creation is 20-30 ms the overhead of the Stopwatch is negligible.
static void Main(string[] args)
{
Worker(1); // jit Warmup
var stopWatchOfStopwatchStopwatch = System.Diagnostics.Stopwatch.StartNew();
var stopWatchOfLoop = System.Diagnostics.Stopwatch.StartNew();
Worker(100000000);
stopWatchOfLoop.Stop();
Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
stopWatchOfStopwatchStopwatch.Stop();
Console.WriteLine("Elapsed of outer SW: " + stopWatchOfStopwatchStopwatch.Elapsed.ToString());
var stopwatchOfcompareLoop = System.Diagnostics.Stopwatch.StartNew();
Worker(100000000);
stopwatchOfcompareLoop.Stop();
Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
}
static void Worker(int iterations)
{
for (int i = 0; i < iterations; i++)
{
Console.WriteLine("bla");
}
}
The difference is insignificant - but that pretty much depends on your performance goals :)