C# Process wait millisecond precise - c#

I am developing an application (sort of a game helper), which sends keystrokes to a game at certain time intervals (you can specify what key will be pressed).
The problem is that I need to do the KeyPress event with a millisecond precision. After some research I found out that Thread.Sleep has a resolution of 20-50 ms and the best I could find so far was using the StopWatch() like following:
cmd_PlayJumps = new DelegateCommand(
() =>
{
ActivateWindow();
Stopwatch _timer = new Stopwatch();
Stopwatch sw = new Stopwatch();
double dElapsed = 0;
//Initial Key Press
_timer.Start();
_Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
int iTotalJumps = SelectedLayout.JumpCollection.Count;
//loop through collection
for (int iJump = 0; iJump < iTotalJumps - 1; iJump++)
{
dElapsed = _timer.Elapsed.TotalMilliseconds;
sw.Restart();
while (sw.Elapsed.TotalMilliseconds < SelectedLayout.JumpCollection[iJump + 1].WaitTime -
dElapsed)
{
//wait
}
_timer.Restart();
_Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
}
//final key press
_Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
_timer.Stop();
_timer = null;
});
As duration of KeyPress event varies within 0.3 - 1.5 ms I also keep track of that in order to get rid of deviation.
Nonetheless, I am only able to get 60% accuracy with this code, as even the StopWatch() is not that precise (of course if my code is not incorrect).
I would like to know, how can I achieve at least 90% accuracy?

The Problem is that you need to be lucky, it all depends on how often the .Tick is reached, which will be around 0.2-2 ms depending on your hardware. It is extremely difficult to avoid this, you could try setting a high process priority to steal the CPU away to get more Ticks in.
This can be achieved with :
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Also try setting
while (sw.Elapsed.TotalMilliseconds <= SelectedLayout.JumpCollection[iJump + 1].WaitTime - dElapsed)
Which should save you another tick sometimes and get the accuracy up a little.
Other than that the Main issue is that windows itself is not the best Timekeeper, DateTime.Now has a tolerance of 16ms for instance and was never thought of as a "real time" operating system.
As a side note :If you really need this to be as accurate as possible I'd advise you to look into Linux.

I got it to an average timing miss of 0.448 milliseconds using a combination of Thread.Sleep and a spin waiter. Setting the thread to high priority does not change the logic, as the thread needs to be running and continuously checking the variable.
static void Main(string[] args)
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
var timespans = new List<TimeSpan>(50);
while (timespans.Count < 50)
{
var scheduledTime = DateTime.Now.AddSeconds(0.40);
Console.WriteLine("Scheduled to run at: {0:hh:mm:ss.FFFF}", scheduledTime);
var wait = scheduledTime - DateTime.Now + TimeSpan.FromMilliseconds(-50);
Thread.Sleep((int)Math.Abs(wait.TotalMilliseconds));
while (DateTime.Now < scheduledTime) ;
var offset = DateTime.Now - scheduledTime;
Console.WriteLine("Actual: {0}", offset);
timespans.Add(offset);
}
Console.WriteLine("Average delay: {0}", timespans.Aggregate((a, b) => a + b).TotalMilliseconds / 50);
Console.Read();
}
Please note that true realtime code cannot be obtained using standard, running on windows, CLR code. The garbage collector could step in, even in between loop cycles, and start collecting objects, at which point have a good chance of getting imprecise timing.
You can reduce the chance of this happening by changing the garbage collector's Latency Mode, at which point it won't do the big collections until extreme low memory situations. If this is not enough for you, consider writing the above solution in a language where better guarantees for timing are given (e.g. C++).

You could try using ElapsedTicks. It is the smallest unit that the Stopwatch can measure and you can convert the number of elapsed ticks to seconds (and fractions of seconds of course) using the Frequency property. I do not know if it is better than Elapsed.TotalMilliseconds but worth a try.

Related

sleep in c# does not work properly

the codes below shows that sleep(1) will sleep an average of 2 miliseconds!
DateTime dt = DateTime.Now;
int i = 0;
long max = -1;
while (true)
{
Stopwatch st=new Stopwatch();
st.Restart();
System.Threading.Thread.Sleep(1);
long el = st.ElapsedMilliseconds;
max = Math.Max(el, max);
i++;
double time = DateTime.Now.Subtract(dt).TotalMilliseconds;
if (time >= 1000)
{
Console.WriteLine("Time =" + time);
Console.WriteLine("i =" + i);
Console.WriteLine("max ="+max);
System.Threading.Thread.Sleep(200);
i = 0;
dt = DateTime.Now;
max = -1;
}
}
Typical Output:
Time =1000.1553
i =495
max =5
could some body explain me the reason? and how can i fix this problem?!
Getting 2 milliseconds is fairly unusual, most anybody that runs your code will get 15 instead. It is rather machine dependent and mostly depends on what other programs you've got running on your machine. One way to change it, for example, is to start Chrome and you'll see (close to) 1 msec sleeps.
You should display more digits to avoid rounding artifacts. A simplification of the code:
static void Main(string[] args) {
Stopwatch st = new Stopwatch();
while (true) {
st.Restart();
System.Threading.Thread.Sleep(1);
st.Stop();
Console.Write("{0} ", st.Elapsed.Ticks / 10000.0);
System.Threading.Thread.Sleep(200);
}
}
Which produces on my machine:
16.2074 15.6224 15.6291 15.5313 15.6242 15.6176 15.6152 15.6279 15.6194 15.6128
15.6236 15.6236 15.6134 15.6158 15.6085 15.6261 15.6297 15.6128 15.6261 15.6218
15.6176 15.6055 15.6218 15.6224 15.6212 15.6134 15.6128 15.5928 15.6375 15.6279
15.6146 15.6254 15.6248 15.6091 15.6188 15.4679 15.6019 15.6212 15.6164 15.614
15.7504 15.6085 15.55 15.6248 15.6152 15.6248 15.6242 15.6158 15.6188 15.6206 ...
This is normal output, I have no programs running on my machine that mess with the operating system. This will be the way it works on most machines.
Some background on what's going on. When you call Thread.Sleep() with a value larger than 0 then you voluntarily give up the processor and your thread goes into a wait state. It will resume when the operating system's thread scheduler runs and enough time has expired.
What's key about that sentence is "when the thread scheduler runs". It runs at distinct times in Windows, driven by the clock interrupt that wakes up the processor from the HALT state. This starts in the kernel, one primary task of the clock interrupt is that it increments the clock value. The one that's used by, for example, DateTime.Now and Environment.TickCount
The clock does not have infinite resolution, it only changes when the clock interrupt occurs. By default on all modern Windows versions, that clock interrupt occurs 64 times per second. Which makes the clock accuracy 1 / 64 = 15.625 milliseconds. You can clearly see this value back in the output of the program on my machine.
So what happened on your machine is that a program changed the clock interrupt rate. That is a rather unfortunate inheritance from Windows 3.1, the first Windows version that supported multi-media timers. Timers that can tick at a high rate to support programs that need to do things with media, like animating a GIF file, tune the frame rate of a video player, keep the audio card fed with sound without stutter or excessive latency. Programs like Chrome.
They do this by calling timeBeginPeriod(). They usually go whole-hog and pick the smallest allowable value, 1 millisecond. Apparently 2 msec on your machine. You can do this too, you'll see the Sleep(1) call now taking about 1 msec instead of 2. Don't forget to call timeEndPeriod() when you no longer need the high rate.
But do keep in mind that this is pretty unfriendly thing to do. Waking up the processor this often is very detrimental to battery life, always an issue on portable machines. Which explains what mystified this site's founding father in his blog post "Why does Windows have terrible battery life". It doesn't, Chrome has terrible battery life :) If you want to find out what program messed with the clock then you can run powercfg -energy from the command line.
I dont think it's weird to see this result. The Stopwatch itself probably takes a millisecond. I highly doubt you can expect a precise 1 millisecond. There is always overhead involved and I doubt sleep guarantees you that the sleep time is that precise.
Personally I would expect a range from 1-5 milliseconds.
Thread.Sleep is designed to pause a thread for at least the number of milliseconds you specify. It basically leaves the execution of the current thead and it's up to the scheduler of the operating system to wake it again. The thing is, you cannot be sure that the underlying OS's scheduler will allow the thread to resume immediately.
I think, System.Threading.Thread.SpinWait is what you are looking for.

Threading Volume #9000

Ok, So, I just started screwing around with threading, now it's taking a bit of time to wrap my head around the concepts so i wrote a pretty simple test to see how much faster if faster at all printing out 20000 lines would be (and i figured it would be faster since i have a quad core processor?)
so first i wrote this, (this is how i would normally do the following):
System.DateTime startdate = DateTime.Now;
for (int i = 0; i < 10000; ++i)
{
Console.WriteLine("Producing " + i);
Console.WriteLine("\t\t\t\tConsuming " + i);
}
System.DateTime endtime = DateTime.Now;
Console.WriteLine(a.startdate.Second + ":" + a.startdate.Millisecond + " to " + endtime.Second + ":" + endtime.Millisecond);
And then with threading:
public class Test
{
static ProducerConsumer queue;
public System.DateTime startdate = DateTime.Now;
static void Main()
{
queue = new ProducerConsumer();
new Thread(new ThreadStart(ConsumerJob)).Start();
for (int i = 0; i < 10000; i++)
{
Console.WriteLine("Producing {0}", i);
queue.Produce(i);
}
Test a = new Test();
}
static void ConsumerJob()
{
Test a = new Test();
for (int i = 0; i < 10000; i++)
{
object o = queue.Consume();
Console.WriteLine("\t\t\t\tConsuming {0}", o);
}
System.DateTime endtime = DateTime.Now;
Console.WriteLine(a.startdate.Second + ":" + a.startdate.Millisecond + " to " + endtime.Second + ":" + endtime.Millisecond);
}
}
public class ProducerConsumer
{
readonly object listLock = new object();
Queue queue = new Queue();
public void Produce(object o)
{
lock (listLock)
{
queue.Enqueue(o);
Monitor.Pulse(listLock);
}
}
public object Consume()
{
lock (listLock)
{
while (queue.Count == 0)
{
Monitor.Wait(listLock);
}
return queue.Dequeue();
}
}
}
Now, For some reason i assumed this would be faster, but after testing it 15 times, the median of the results is ... a few milliseconds different in favor of non threading
Then i figured hey ... maybe i should try it on a million Console.WriteLine's, but the results were similar
am i doing something wrong ?
Writing to the console is internally synchronized. It is not parallel. It also causes cross-process communication.
In short: It is the worst possible benchmark I can think of ;-)
Try benchmarking something real, something that you actually would want to speed up. It needs to be CPU bound and not internally synchronized.
As far as I can see you have only got one thread servicing the queue, so why would this be any quicker?
I have an example for why your expectation of a big speedup through multi-threading is wrong:
Assume you want to upload 100 pictures. The single threaded variant loads the first, uploads it, loads the second, uploads it, etc.
The limiting part here is the bandwidth of your internet connection (assuming that every upload uses up all the upload bandwidth you have).
What happens if you create 100 threads to upload 1 picture only? Well, each thread reads its picture (this is the part that speeds things up a little, because reading the pictures is done in parallel instead of one after the other).
As the currently active thread uses 100% of the internet upload bandwidth to upload its picture, no other thread can upload a single byte when it is not active. As the amount of bytes that needs to be transmitted, the time that 100 threads need to upload one picture each is the same time that one thread needs to upload 100 pictures one after the other.
You only get a speedup if uploading pictures was limited to lets say 50% of the available bandwidth. Then, 100 threads would be done in 50% of the time it would take one thread to upload 100 pictures.
"For some reason i assumed this would be faster"
If you don't know why you assumed it would be faster, why are you surprised that it's not? Simply starting up new threads is never guaranteed to make any operation run faster. There has to be some inefficiency in the original algorithm that a new thread can reduce (and that is sufficient to overcome the extra overhead of creating the thread).
All the advice given by others is good advice, especially the mention of the fact that the console is serialized, as well as the fact that adding threads does not guarantee speedup.
What I want to point out and what it seems the others missed is that in your original scenario you are printing everything in the main thread, while in the second scenario you are merely delegating the entire printing task to the secondary worker. This cannot be any faster than your original scenario because you simply traded one worker for another.
A scenario where you might see speedup is this one:
for(int i = 0; i < largeNumber; i++)
{
// embarrassingly parallel task that takes some time to process
}
and then replacing that with:
int i = 0;
Parallel.For(i, largeNumber,
o =>
{
// embarrassingly parallel task that takes some time to process
});
This will split the loop among the workers such that each worker processes a smaller chunk of the original data. If the task does not need synchronization you should see the expected speedup.
Cool test.
One thing to have in mind when dealing with threads is bottlenecks. Consider this:
You have a Restaurant. Your kitchen can make a new order every 10
minutes (your chef has a bladder problem so he's always in the
bathroom, but is your girlfriend's cousin), so he produces 6 orders an
hour.
You currently employ only one waiter, which can attend tables
immediately (he's probably on E, but you don't care as long as the
service is good).
During the first week of business everything is fine: you get
customers every ten minutes. Customers still wait for exactly ten
minutes for their meal, but that's fine.
However, after that week, you are getting as much as 2 costumers every
ten minutes, and they have to wait as much as 20 minutes to get their
meal. They start complaining and making noises. And god, you have
noise. So what do you do?
Waiters are cheap, so you hire two more. Will the wait time change?
Not at all... waiters will get the order faster, sure (attend two
customers in parallel), but still some customers wait 20 minutes for
the chef to complete their orders.You need another chef, but as you
search, you discover they are lacking! Every one of them is on TV
doing some crazy reality show (except for your girlfriend's cousin who
actually, you discover, is a former drug dealer).
In your case, waiters are the threads making calls to Console.WriteLine; But your chef is the Console itself. It can only service so much calls a second. Adding some threads might make things a bit faster, but the gains should be minimal.
You have multiple sources, but only 1 output. It that case multi-threading will not speed it up. It's like having a road where 4 lanes that merge into 1 lane. Having 4 lanes will move traffic faster, but at the end it will slow back down when it merges into 1 lane.

Process.TotalProcessorTime exceeds the actual time passing

I want to calculate the average CPU usage % between two points of time.
I use the ratio between t1-t0 and Process.TotalProcessorTime1 - Process.TotalProcessorTime0
(where t is the actual DateTime.Now at that point)
but sometimes when the computer is busy I get the TotalProcessorTime difference in Ticks is larger than the actual time (in Ticks) that passed, so my cpu% exceeds 100.
how can that be?
long currentLogTime = DateTime.Now.Ticks;
long currentSPUUsageTime = _process.TotalProcessorTime.Ticks;
long timeDiff= currentLogTime - m_LastLogTime;
if (timeDiff != 0)
{
cpuUsage = (currentSPUUsageTime - m_LastCPUUsageTime) * 100 / timeDiff;
}
If a single process uses more than one processor, it can use processor time in faster than real time.
DateTime.Now is measured with a lower resolution than TotalProcessorTime.
You'll need to use a high-resolution timer to measure the elapsed time. Consider using a Stopwatch instance for this purpose.
Use the StartNew method when you start a new "log period":
m_stopwatch = Stopwatch.StartNew();
Then simply read the ElapsedTicks property to determine how much time that has elapsed:
long timeDiff= m_stopwatch.ElapsedTicks;

More precise Thread.Sleep

How can i do Thread.Sleep(10.4166667);?
OK i see now that Sleep is not the way to go.
So i use Timer but timer is also in ms put i need more precise
Is there timer with nanosecond accuracy?
So you want your thread to sleep precisely for that time and then resume? Forget about it. This parameter tells the system to wake the Thread after at least this number of milliseconds. At least. And after resuming, the thread could be put to sleep once again in a blink of an eye. That just how Operating Systems work and you cannot control it.
Please note that Thread.Sleep sleeps as long as you tell it (not even precisely), no matter how long code before or after takes to execute.
Your question seems to imply that you want some code to be executed in certain intervals, since a precise time seems to matter. Thus you might prefer a Timer.
To do such a precise sleep you would need to use a real time operating system and you would likely need specialized hardware. Integrity RTOS claims to respond to interrupts in nanoseconds, as do others.
This isn't going to happen with C# or any kind of high level sleep call.
Please note that the argument is in milliseconds, so 10 is 10 milliseconds. Are you sure you want 10.41 etc milliseconds? If you want 10.41 seconds, then you can use 10416.
The input to Thread.Sleep is the number of milliseconds for which the thread is blocked. After that it will be runnable, but you have no influence over when it is actually scheduled. I.e. in theory the thread could wait forever before resuming execution.
It hardly ever makes sense to rely on specific number of milliseconds here. If you're trying to synchronize work between two threads there are better options than using Sleep.
As you already mentioned: You could combine DispatcherTimer with Stopwatch (Making sure the IsHighResolution and Frequency suits your needs). Start the Timer and the Stopwatch, and on discreet Ticks of the Timer check the exact elapsed time of the stopwatch.
If you are trying to rate-limit a calculation and insist on using only Thread.Sleep then be aware there is a an underlying kernel pulse rate (roughly 15ms), so your thread will only resume when a pulse occurs. The guarantee provided is to "wait at least the specified duration." For example, if you call Thread.Sleep(1) (to wait 1ms), and the last pulse was 13ms ago, then you will end up waiting 2ms until the next pulse comes.
The draw synchronization I implemented for a rendering engine does something similar to dithering to get the quantization to the 15ms intervals to be uniformly distributed around my desired time interval. It is mostly just a matter of subtracting half the pulse interval from the sleep duration, so only half the invocations wait the extra duration to the next 15ms pulse, and half occur early.
public class TimeSynchronizer {
//see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
public const double THREAD_PULSE_MS = 15.6d;//TODO read exact value for your system
public readonly TimeSpan Min = TimeSpan.Zero;
public TimeSynchronizer(TimeSpan? min = null) {
if (min.HasValue && min.Value.Ticks > 0L) this.Min = min.Value;
}
private DateTime _targetTimeUtc = DateTime.UtcNow;//you may wish to defer this initialization so the first Synchronize() call assuredly doesn't wait
public void Synchronize() {
if (this.Min.Ticks > 0L) {
DateTime nowUtc = DateTime.UtcNow;
TimeSpan waitDuration = this._targetTimeUtc - nowUtc;
//store the exact desired return time for the next inerval
if (waitDuration.Ticks > 0L)
this._targetTimeUtc += this.Min;
else this._targetTimeUtc = nowUtc + this.Min;//missed it (this does not preserve absolute synchronization and can de-phase from metered interval times)
if (waitDuration.TotalMilliseconds > THREAD_PULSE_MS/2d)
Thread.Sleep(waitDuration.Subtract(TimeSpan.FromMilliseconds(THREAD_PULSE_MS/2d)));
}
}
}
I do not recommend this solution if your nominal sleep durations are significantly less than the pulse rate, because it will frequently not wait at all in that case.
The following screenshot shows rough percentile bands on how long it truly takes (from buckets of 20 samples each - dark green are the median values), with a (nominal) minimum duration between frames set at 30fps (33.333ms):
I am suspicious that the exact pulse duration is 1 second / 600, since in SQL server a single DateTime tick is exactly 1/300th of a second

Need microsecond delay in .NET app for throttling UDP multicast transmission rate

I'm writing a UDP multicast client/server pair in C# and I need a delay on the order of 50-100 µsec (microseconds) to throttle the server transmission rate. This helps to avoid significant packet loss and also helps to keep from overloading the clients that are disk I/O bound. Please do not suggest Thread.Sleep or Thread.SpinWait. I would not ask if I needed either of those.
My first thought was to use some kind of a high-performance counter and do a simple while() loop checking the elapsed time but I'd like to avoid that as it feels kludgey. Wouldn't that also peg the CPU utilization for the server process?
Bonus points for a cross-platform solution, i.e. not Windows specific. Thanks in advance, guys!
Very short sleep times are generally best achieved by a CPU spin loop (like the kind you describe). You generally want to avoid using the high-precision timer calls as they can themselves take up time and skew the results. I wouldn't worry too much about CPU pegging on the server for such short wait times.
I would encapsulate the behavior in a class, as follows:
Create a class whose static constructor runs a spin loop for several million iterations and captures how long it takes. This gives you an idea of how long a single loop cycle would take on the underlying hardware.
Compute a uS/iteration value that you can use to compute arbitrary sleep times.
When asked to sleep for a particular period of time, divide uS to sleep by the uS/iteration value previously computed to identify how many loop iterations to perform.
Spin using a while loop until the estimated time elapses.
I would use stopwatch but would need a loop
read this to add more extension to the stopwatch, like ElapsedMicroseconds
or something like this might work too
System.Diagnostics.Stopwatch.IsHighResolution MUST be true
static void Main(string[] args)
{
Stopwatch sw;
sw = Stopwatch.StartNew();
int i = 0;
while (sw.ElapsedMilliseconds <= 5000)
{
if (sw.Elapsed.Ticks % 100 == 0)
{ i++; /* do something*/ }
}
sw.Stop();
}
I've experienced with such requirement when I needed more precision with my multicast application.
I've found that the best solution resides with the MultiMedia timers as seen in this example.
I've used this implementation and added TPL async invoke to it. You should see my SimpleMulticastAnalyzer project for more information.
static void udelay(long us)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
long v = (us * System.Diagnostics.Stopwatch.Frequency )/ 1000000;
while (sw.ElapsedTicks < v)
{
}
}
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("" + i + " " + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
udelay(1000000);
}
}
I would discourage using spin loop as it consumes and creates blocking thread. thread.sleep is better, it doesn't use processor resource during sleep, it just slice the time. Try it, and you'll see from task manager how the CPU usage spike with the spin loop.
Have you looked at multimedia timers? You could probably find a .NET library somewhere that wraps the API calls somewhere.

Categories

Resources