I have a for loop that is taking way too long and i dont know why.
Stopwatch proctime = new Stopwatch();
Stopwatch innerlooptime = new Stopwatch();
Stopwatch outerlooptime = new Stopwatch();
proctime.Start();
int length = inbtable.Rows.Count;
outerlooptime.Start();
for (int i = 0; i < length; i++)
{
outerlooptime.Stop();
DataRow newrow = graphdata.NewRow();
innerlooptime.Start();
for (int j = 0; j < graphdata.Columns.Count; j++)
{
colname = graphdata.Columns[j].ColumnName;
newrow[j] = inbtable.Rows[i][colname];
}
innerlooptime.Stop();
outerlooptime.Start();
graphdata.Rows.Add(newrow);
}
proctime.Stop();
if you time it all out, the time spent on just the "inner loop" or the j-loop is like 1/10th of a second.
the time spent inside the i loop, but not the j-loop is like 1/10th of a second.
the time spent on the total loop is around 1-second. so Time-iloop + Time-jloop is like 1/5th of the total time. where is the rest of the time being spent? take a look at the image, comparing processing time (proctime in the code), outerloop time and innerloop time. why dont those add up to something much closer to each other?
You don't show the declarations of your timers, but the variable names imply that you are looking at the processor time, not the actual amount of time spend. Processor time is the amount of time spent by the processor core running your calculations - the processor is shared among all the processes running on your computer, so in 1 second, it is perfectly reasonable to receive 0.2 seconds of processor time.
Try using the Stopwatch class instead:
// using System.Diagnostics;
Stopwatch sw = new Stopwatch();
sw.Start();
DoThings(); // run your code
sw.Stop();
Debug.WriteLine("Actual time elapsed: " + sw.Elapsed.ToString());
I figured out the answer. it was really silly. i had the stopwatches switched around in my message box statement at the end of the function, so one stopwatch was being reported as another one. all the time is being spent somewhere else, outside the code i posted. Thanks for all of your help.
Related
I'm trying to create a method in C# whereby I can repeatedly perform an action (in my particular application it's sending a UDP packet) at a targeted rate. I know that timer inaccuracy in C# will prevent the output from being precisely at the target rate, but best effort is good enough. However, at higher rates, the timing seems to be completely off.
while (!token.IsCancellationRequested)
{
stopwatch.Restart();
Thread.Sleep(5); // Simulate process
int processTime = (int)stopwatch.ElapsedMilliseconds;
int waitTime = taskInterval - processTime;
Task.Delay(Math.Max(0, waitTime)).Wait();
}
See here for the full example console app.
When run, the FPS output of this test app shows around 44-46 Hz for a target of 60 Hz. However at lower rates (say 20 Hz), the output rate is much closer to the target. I can't understand why this would be the case. What is the problem with my code?
The problem is that Thread.Sleep (or Task.Delay) is not very accurate. Take a look at this: Accuracy of Task.Delay
One way to fix this is to a start the timer once, and then have a loop where you delay some ~15 ms in each iteration. Inside each iteration, you calculate how much times the operation should have been executed so far and you compare it with how many times you have run it so far. And you then run the operation enough times to catch up.
Here is some code sample:
private static void timerTask(CancellationToken token)
{
const int taskRateHz = 60;
var stopwatch = new Stopwatch();
stopwatch.Start();
int ran_so_far = 0;
while (!token.IsCancellationRequested)
{
Thread.Sleep(15);
int should_have_run =
stopwatch.ElapsedMilliseconds * taskRateHz / 1000;
int need_to_run_now = should_have_run - ran_so_far;
if(need_to_run_now > 0)
{
for(int i = 0; i < need_to_run_now; i++)
{
ExecuteTheOperationHere();
}
ran_so_far += need_to_run_now;
}
}
}
Please note that you want to use longs instead of ints if the process is to remain alive for a very long time.
If you replace this:
Task.Delay(Math.Max(0, waitTime)).Wait();
with this:
Thread.Sleep(Math.Max(0, waitTime));
You should get closer values on higher rates (why would you use Task.Delay(..).Wait() anyway?).
I have accidentally found a peculiar behaviour for which I am not getting any reason. In the program below there are 2 sections. First section is commented which creates 2 threads and does some work, in second section I added some code for getting primes which I tried for checking AsParallel Performance. AsParallel really decreased the time for program. But the thing which struck me most was when I commented the above section I got a improvement in time.
So my question is did the first section ,which I have commented, had kept the CPU busy enough. Or was there any other reason.
Please see time elapsed for
1) When first section is not commented : Elapsed: 4260619 (Ticks)
2) When first section is commented : Elapsed: 2700445 (Ticks)
class Program
{
[ThreadStatic]
static int thStaticInt = 0;
static void Main(string[] args)
{
//new Thread(() =>
//{
// for (int i = 0; i < 10; i++)
// {
// thStaticInt++;
// Console.WriteLine("from first {0}", thStaticInt);
// }
//}
//).Start();
//new Thread(() =>
//{
// for (int i = 0; i < 10; i++)
// {
// thStaticInt++;
// Console.WriteLine("from second {0}", thStaticInt);
// }
//}
//).Start();
//Console.WriteLine("Press any key");
//Console.ReadLine();
//Another section starts here
IEnumerable<int> numbers = Enumerable.Range(3, 1000000);
Stopwatch watch = new Stopwatch();
watch.Start();
var primes = from n in numbers.AsParallel()
where Enumerable.Range(2, (int)Math.Sqrt(n)).All(i => n % i != 0)
select n;
IEnumerable<int> primeNumbers = primes.ToArray();
watch.Stop();
TimeSpan ts = watch.Elapsed;
Console.WriteLine("Time Elapsed {0}", ts.Ticks);
Console.ReadLine();
}
}
You're not grabbing the complete picture. Your profiling leads you to misinterpretation.
When you start a thread you request the operating system to start a thread, that doesn't mean it starts immediately, it's just a request. The OS decides when it runs your thread and for how long. That being said, in your example, your threads in the commented section could be run before, during or even after your second section.
The work in your threads is also a bit dubious. A counter to ten is very minimalistic. Also keep in mind that what you do, writing to the console, from a thread is only possible because the Console class does the thread synchronization for you. So, how does this fit in the timing? I have no idea.
Then there might be other processes with other threads running that you don't know of.
And on top of all of that you probably have a multicore processor, which might or might not affect everything.
Profiling is not an easy task. You should at least repeat your tests multiple times, corelate the results and have a solid understanding of everything involved.
I'm trying to write something to stop running the code after 15 seconds of running.
I don't want While loop or any kind of loop to be used and would like to use IF-ELSE conditions instead as it would make it easier for me in my code.
The part of code I want to stop being executed after 15 seconds is a FOR loop itself. Let's consider the below code for example:
for (int i = 1; i < 100000; i++)
{
Console.WriteLine("This is test no. "+ i+ "\n");
}
How would you stop this loop after 15 seconds of running?
You can assign DateTime variable before the loop having the current date and time, then in each loop iteration simply check if 15 seconds have passed:
DateTime start = DateTime.Now;
for (int i = 1; i < 100000; i++)
{
if ((DateTime.Now - start).TotalSeconds >= 15)
break;
Console.WriteLine("This is test no. "+ i+ "\n");
}
Update: while the above will usually work, it's not bullet proof and might fail on some edge cases (as Servy pointed out in a comment), causing endless loop. Better practice would be using the Stopwatch class, which is part of System.Diagnostics namespace:
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 1; i < 100000; i++)
{
if (watch.Elapsed.TotalMilliseconds >= 500)
break;
Console.WriteLine("This is test no. " + i + "\n");
}
watch.Stop();
I'm posting my answer from my older post because it's more relevant here,
I think you need to measure time and stop the code after particular time say "15 seconds" ,StopWatch class can help you out.
// Create new stopwatch instance
Stopwatch stopwatch = new Stopwatch();
// start stopwatch
stopwatch.Start();
// Stop the stopwatch
stopwatch.Stop();
// Write result
Console.WriteLine("Time elapsed: {0}",stopwatch.Elapsed);
// you can check for Elapsed property when its greater than 15 seconds
//then stop the code
Elapsed property returns TimeSpan instance you would do something like this.
TimeSpan timeGone = stopwatch.Elapsed;
To fit your scenario you can do something like this
Stopwatch stopwatch = new Stopwatch();
TimeSpan timeGone;
// Use TimeSpan constructor to specify:
// ... Days, hours, minutes, seconds, milliseconds.
// ... The TimeSpan returned has those values.
TimeSpan RequiredTimeLine = new TimeSpan(0, 0, 0, 15, 0);//set to 15 sec
While ( timeGone.Seconds < RequiredTimeLine.Seconds )
{
stopwatch.Start();
Start();
timeGone = stopwatch.Elapsed;
}
Stop();//your method which will stop listening
Some useful links
MSDN StopWatch
Better you can use below code, which would help to improve in performance.
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
I wrote some code which monitors the output of Stopwatch using a tight loop. This loop tracks the number of ticks which have elapsed since the last iteration. I'm observing jumps of 500 microseconds 20 times a second, while most other iterations take <1µs.
Can someone explain why I'm seeing these jumps?
I've tried:
Setting processor affinity (no effect)
Changing thread priority (Highest/AboveNormal makes things worse)
Running outside of the debugger
Release build with optimizations
My code is below:
Stopwatch sw = new Stopwatch();
int crossThresholdCount = 0;
long lastElapsedTicks = 0;
long lastPrintTicks = 0;
Console.WriteLine("IsHighResolution: " + Stopwatch.IsHighResolution);
Console.WriteLine("Frequency: " + Stopwatch.Frequency);
sw.Start();
long thresholdTicks = 5000; // 10000 ticks per ms
while (true)
{
long tempElapsed = sw.ElapsedTicks;
long sincePrev = tempElapsed - lastElapsedTicks;
lastElapsedTicks = tempElapsed;
if (sincePrev > thresholdTicks)
crossThresholdCount++;
// print output
if (crossThresholdCount > 0 && tempElapsed - lastPrintTicks > TimeSpan.TicksPerSecond)
{
lastPrintTicks = tempElapsed;
Console.WriteLine("crossed " + crossThresholdCount + " times");
crossThresholdCount = 0;
}
}
Most likely you are seeing preemptive task switching. This is when the operating system suspends your program, and goes off to execute other programs. This is how things have been since Windows 95 (Win 3.1 and earlier had cooperative multitasking, whereby you could hold the CPU for as long as you want).
By the way, there is a better way to time your execution accurately: QueryThreadCycleTime, which counts CPU cycles only when your code is executing, and so excludes such pauses.
Your test doesn't really make sense... Your process is not the only one to run on your machine. The system gives processor time to each thread in turn, so there are periods of time when your loop is not running at all, which explains the "jumps".
I have seen other user posts which show Stopwatch measuring time spent in "Thread.Sleep(5000)" to be around 5000ms.
But my program produces the following results
for (int i = 0; i < 20; ++i)
{
Stopwatch sw = Stopwatch.StartNew();
DateTime start = DateTime.Now;
Thread.Sleep(5000);
sw.Stop();
Console.Out.WriteLine(
"StopWatch Diff:" +
sw.ElapsedMilliseconds.ToString());
Console.Out.WriteLine(
"DateTime Diff:" +
DateTime.Now.Subtract(start).TotalMilliseconds.ToString());
}
StopWatch Diff:1684
DateTime Diff:5262.592
StopWatch Diff:1625
DateTime Diff:4997.12
StopWatch Diff:1604
DateTime Diff:4997.12
StopWatch Diff:1601
DateTime Diff:4997.12
StopWatch Diff:1690
DateTime Diff:4997.12
StopWatch Diff:1603
Is it just me who is observing this behaviour? Why stopwatch measures 1.6 seconds when 5 seconds have actually passed. It is the time that the thread is actually running?
The Stopwatch class is not reliable.
This is unreliable on processors that do not have a constant clock speed (most processors can reduce the clock speed to conserve energy). This is explained in detail here.