Introduction

It is has been widely toted that Microsecond Precision (μs) scale time is not possible on .NET or Mono due to many issues which I will not endeavor into explaining.

Based on some of this I originally had setup a task for myself to write a good portable μs scale timer which performed the necessary platform invocation.

After I was done I realized that there is nothing "scientifically" stopping .NET from having this precision based on the fact that the caller executes the invocation and obtains the result and the GC cannot interrupt platform invocation calls so long as you do not pass a
managed type.

E.g., if I pass a plain old pointer to a un-managed function there is nothing for the GC to interrupt or stop unless the Kernel itself interrupts the call for something.

I originally though about using unsafe code but then I realized that I was just going closer to using platform invocation.

I thought about trying to obtain precise clock cycles using a static constructor which forced a GC and then ran to determine things like call overhead and whatnot but I felt that there was more time being spent on trying to obtain information then actually sleeping for the user which was the goal.

I then realized something even more bold and interesting... Sockets have a microsecond precision due to signaling and they are usable from the .NET Framework and there is a Poll method which actually accepts the amount of time in Microseconds (μs).

After some quick tests I realized I had something which was a lightweight sealed class with all static members with no more resources than a single socket.

I tricked the socket into always being busy and then I used the Poll method to obtain the desired sleep time in Microsecond Precision (μs).

I want to know what everyone thinks about this and if anyone sees anything glaring out at me which I did not also take into account.

Here is the class code and testing code complete with platform invocation methods (found here on Stack Overflow @ usleep is obsolte...) for comparison and testing.

#region Cross Platform μTimer
///<summary>/// A Cross platform implementation which can delay time on the microsecond(μs) scale.
/// It operates at a frequencies which are faster then most Platform Invoke results can provide due to the use of Kernel Calls under the hood.
/// Requires Libc.so@usleep on Mono and QueryPerformanceCounter on Windows for uSleep static
///</summary>///<notes>A Tcp Socket will be created on port 7777 by default to help keep track of time. No connections will be recieved from this socket.</notes>publicsealedclass μTimer : IDisposable
{
#region Not Applicable for the MicroFramework
#if(!MF)
#region Uncesessary Interop (Left for Comparison)
#if MONO
using System.Runtime.InteropServices;
[System.Runtime.InteropServices.DllImport("libc.so")] //.a , Not Portable
staticexternint usleep (uint amount);
///<notes>The type useconds_t is an unsigned integer type capable of holding integers in the range [0,1000000]. Programs will be more portable if they never mention this type explicitly. </notes>void uSleep(int waitTime) { usleep(waitTime); }
#else
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
staticexternbool QueryPerformanceCounter(outlong lpPerformanceCount);
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
staticexternbool QueryPerformanceFrequency(outlong lpFrequency);
///<summary>/// Performs a sleep using a plaform dependent but proven method
///</summary>///<paramname="amount">The amount of time to sleep in microseconds(μs)</param>publicstaticvoid uSleep(TimeSpan amount) { μTimer.uSleep(((int)(amount.TotalMilliseconds * 1000))); }
///<summary>/// Performs uSleep by convention of waiting on performance couters
///</summary>///<paramname="waitTime">The amount of time to wait</param>publicstaticvoid uSleep(int waitTime)
{
long time1 = 0, time2 = 0, freq = 0;
QueryPerformanceCounter(out time1);
QueryPerformanceFrequency(out freq);
do
{
QueryPerformanceCounter(out time2);
} while ((time2 - time1) < waitTime);
}
#endif#endregion#endif#endregion#region Statics
//Who but me
constushort Port = 7777;
//Since System.Timespan.TickerPerMicrosecond is constantly 10,000
publicconstlong TicksPerMicrosecond = 10;
///<summary>/// A divider used to scale time for waiting
///</summary>publicconstlong Divider = TimeSpan.TicksPerMillisecond / TicksPerMicrosecond;
staticbool m_Disposed;
///<summary>/// The socket we use to keep track of time
///</summary>static Socket m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
///<summary>/// The memory we give to the socket for events which should not occur
///</summary>static SocketAsyncEventArgs m_SocketMemory = new SocketAsyncEventArgs();
publicstatic DateTime LocalTime { get { returnnew DateTime(Environment.TickCount * TimeSpan.TicksPerMillisecond); } }
publicstatic DateTime UniversalTime { get { return LocalTime.ToUniversalTime(); } }
///<summary>/// Handles the creation of resources used to provide the μSleep method.
///</summary>static μTimer()
{
try
{
//Listen on the Loopback adapter on the specified port
m_Socket.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, Port));
//Only for 1 client
m_Socket.Listen(1);
//Assign an event now because in Begin process we will not call it if the even will not raise
m_SocketMemory.Completed += BeginProcess;
#if(!MF)
//If the SocketAsyncEventArgs will not raise it's own event we will call it now
if (!m_Socket.AcceptAsync(m_SocketMemory))
{
BeginProcess(typeof(μTimer), m_SocketMemory);
}
#elsenew Thread(()=> BeginProcess(this, null)).Start();
#endif
}
catch
{
throw;
}
}
///<summary>/// Handles processing on the master time socket.
/// This should never occcur.
///</summary>///<paramname="sender">The sender of the event</param>///<paramname="e">The SocketAsyncEventArgs from the event</param>///<remarks>/// No one should connect... Ever.. (This is not a signaling implementation)
///</remarks>#if(!MF)
staticvoid BeginProcess(object sender, SocketAsyncEventArgs e)
{
#elsestaticvoid BeginProcess(object sender, object args e)
{
while(!m_Disposed)
{
try
{
Socket dontCare = m_Socket.Accept(); dontCare.Dispose();
thrownew System.InvalidProgramException("A Connection to the system was made by a unauthorized means.");
}
catch { throw; }
}
#endifif (!m_Disposed && e.LastOperation == SocketAsyncOperation.Connect)
{
try
{
thrownew System.InvalidProgramException("A Connection to the system was made by a unauthorized means.");
}
finally
{
if (e.AcceptSocket != null)e.AcceptSocket.Dispose();
}
}
}
///<summary>/// Performs a sleep using a method engineered by Julius Friedman (juliusfriedman@gmail.com)
///</summary>///<paramname="amount">The amount of time to Sleep</param>publicstaticvoid μSleep(TimeSpan amount)
{
//Sample the system clock
DateTime now = μTimer.UniversalTime, then = μTimer.UniversalTime;
TimeSpan waited = now - then;
//If cpu time is not fast enough to accomadate then you are in bigger trouble then you know
if (waited > amount) return;
else System.Threading.Thread.Sleep(amount - waited); //A normal sleep with an amount less that 1 but greater than 0 Millisecond will not switch
waited = now - then;//Waste cycles and calculate time waited in ticks again
if (waited > amount) return;
elseunchecked
{
//Scale time, basis of theory is we shouldn't be able to read from a socket in Accept mode
//and it should take more time than a 1000th of the time we need
if (m_Socket.WaitRead(((int)((amount.Ticks - waited.Ticks / TicksPerMicrosecond) / Divider))))
{
//We didn't sleep
//Sample the system clock
then = μTimer.UniversalTime;
//Calculate waited
//Subtract time already waited from amount
amount -= waited;
//Waited set to now - then to determine wait
waited = now - then;
//return or utilize rest of slice sleeping
if (waited > amount) return;
else System.Threading.Thread.Sleep(amount - waited);
}
}
}
///<summary>/// Performs a sleep using a method engineered by Julius Friedman (juliusfriedman@gmail.com)
///</summary>///<paramname="amount">The amount of time to Sleep in microseconds(μs) </param>publicstaticvoid μSleep(int amount) { μTimer.μSleep(TimeSpan.FromMilliseconds(amount * TimeSpan.TicksPerMillisecond)); }
#endregionvoid IDisposable.Dispose()
{
m_Disposed = true;
if (m_Socket != null)
{
m_Socket.Dispose();
m_Socket = null;
}
}
}
#endregion

Here is the testing code:

I even updated it to show that the StopWatch verifies that my method sleeps for under 1 μs.

Test Failed! (A Result of the writenotice function, take only note of the color which will be "DarkGreen"

Exception.Message: StopWatch Elapsed during µSleep = 00:00:00.0000043

µTimer Took: 00:00:00

PerformanceCounter Took: 00:00:00

StopWatch Took 00:00:00.0000006

Test Passed! (Because my method was faster)

Test Passed! (Because my method was faster)

Press (W) to run again, (D) to debug or any other key to continue. (Press D or Q)

0 Failures, 7778 Successes (Because the CPU Has to warm up the first executions I believe)

On of the key points being: "Chipset vendors should implement an HPET to comply with Intels "IA-PC HPET (High Precision Event Timers) Specification"
and this code is strengthened on the reliance that all NIC processors can handle this requirement quite easily!

Some will say this is a hack and a shortcut but in all honesty, is there anything really wrong with this?

If you need the 'WaitRead' Method code you can check out Manged Media Aggregation which will be releasing this code very shortly along with a bunch of other goodies!

Until then use Poll with the same value as I do in 'WaitRead' and SelectMode.Read

If you run a very simple test that measures the accuracy of Socket.Poll on a modern PC (Windows Vista+) which does not run any video playback, you will get a result showing that

Socket.Poll(1, SelectMode.SelectRead)

is nothing better than

Thread.Sleep(1) or ManualResetEvent.WaitOne(1)

All of them are going to take around 15.6 milliseconds to complete.

Another case is when there is a media playback application running or you manually increase the system timer resolution to the top which is 1 millisecond per cycle (not microsecond, this is not possible for a common PC without specific fancy hardware). In this context you can expect the following results:

Well, I had no negative a priori when I began to read your article" The idea sounds interesting.
I've read it carefully, twice, until the end.
Then I created a small console app to verify that what you are saying is true (since no real output nor comparison with actual facts is shown). I went through the Poll method trick, corrected the delegate name in the RunTest() call; then I quit because I could not bother fixing the thread thingy.
Then I watched the comments...
Your article cannot be easily tested as it is missing some basic namespace declarations and 'using' directives. Therefore it is really tricky to verify your assumptions.
But the main reason to my vote is the way you answer to objections that are made to you. You are totally sarcastic and unrespectful of others and, despite what you claimed several times, this article does not constitute any beginning of a valid proof of concept.
Do you think insulting people will lead them to finally agree with you?

Finally, I re-read that a third time. When I got to this line:

Let me know if I am too high on my horse to see the big picture here orif I actually achieved something which others may find useful!

If you can't realize that Socket.Poll will use Socket.IOControl under the hood which is basically using a kernel level call and there is no way to get closer to the kernel without a driver.... then I am not sure how high I am, rather I think you are high and wish I could join you.

Additionally it is possible to send driver level commands using raw sockets if you have the endpoint, the WaitForMultipleObjects call is done using Poll (Through IOControl) so essentially you can use Sockets for USB development, Driver communication et al. And the Poll method is a reliable timer as indicated (in the microsecond frequency range)

Don't bother, others have already tried to reason this guy and failed.

But I seriously started questioning CodeProjects voting system. There are numerous articles like this which have a high rating because people just upvote them without even bothering to read them thoroughly. Apparently CodeProject guys presume that "not all members play nice" when they downvote, but I have a feeling that most people simply upvote the article if the subject seems interesting to them, even if they lack the knowledge or time to fully analyze them.

Simply put, you're not measuring the elapsed time correctly. And there are several ridiculous statements in that function that I've described in one of my previous comments (but you are blisfully ignoring this fact).

There are numerous errors in this article, and the method simply doesn't provide microsecond resolution on Windows.

1. You start your article by a claim that "GC cannot interrupt platform invocation calls so long as you do not pass a managed type". This is simply not correct. Garbage collector can pause all managed threads in your process whenever it feels like it. A background GC on a Windows Server machine will try to do it less often, but it will nevertheless suspend all threads while collecting young generations.

2. You use Environment.TickCount to get current time information, which uses the GetTickCount() WINAPI function, known for having a poor resolution (typically 10 to 16 ms). When you do that subtraction thingy at the beginning of your method (TimeSpan waited = now - then;), it will return 0 most of the time, and 16 every, say, 16ms. So, you are basically choosing to skip your entire function every 16ms.

3. Next, you call Thread.Sleep(amount - waited) immediately after, claiming that "A normal sleep with an amount less that 1 but greater than 0 Millisecond will not switch". That's wrong, as Thread.Sleep(TimeSpan) overload simply discards your fractional milliseconds, as explained on MSDN[^].

4. So, basically, removing all that redundant, erroneous and misleading checks from your method, you are left with your theory about `Socket.Poll`. Ok, how about this scientific approach: have you actually tried running it, say, 1,000,000 times in a single loop with a 1us timer and checking the totalStopwatch elapsed time? I can assure you, it won't be anywhere near 1 second.

So, if anyone wants a truly precise timer, you should consider using Thread.SpinWait and a Stopwatch, like described in this article: Microsecond and Millisecond C# Timer[^]. But even then, your thread and process can easily get interrupted, so don't count your life on it being precise except in the "average" case. Windows is not a real-time OS.

2) This is not even `addressable`, I am using select to get the time buddy, so that thingy your talking about is just to eliminate the use of a local time zone conversion with no need for a presentation of a base time hence forther shall now be known as the use of Select to delay or simply that `TickCount` thingy "which happens to return 0 MOST of the time".... Your great....

3)This is true on Windows, may not be true everywhere and like I stated in the code, you already waited as small as a unit in which the socket layer was capable of waiting while burning the interrupt and comparing the value, if you needed less time that that the ONLY other way would literally be to use hardware itself via something which lives in kernel space

4)I assure you that you have no idea what your talking about, the StopWatch is not faster than the `socket` or select because of the additional information it must acquire to precisely keep the time whereas and I do believe this is mostly the same in all layered services providers.... the notion of time is not relevant because it is assumed that interrupts are happening and thus even for your 'StopWatch' to acquire it's sh***y information it must rely upon the same semantics in which my socket method is already using but not to communicate to another layer and perform a query or wait on a already busy context, it uses its own.

And LAST but not least you would use fencing to ensure that the `atomacity` of the operations you were performing to keep time were in fact so.

Now I hope I didn't digress to much here or go too far there but please my all means let me have it!

Ok, let me try to comment line by line, because I have a feeling you misunderstood me:

// Let's say you called this method with TimeSpan.FromTicks(100), i.e. 10 microseconds
publicstaticvoid μSleep(TimeSpan amount)
{
// First, this part. You are basically calling Environment.TickCount twice in a row
// (that's your implementation of 'UniversalTime' at the beginning of the article)
DateTime now = μTimer.UniversalTime, then = μTimer.UniversalTime;
// At this point, difference between `now` and `then` is either 0 or 16, due to poor Environment.TickCount resolution.
// Check this StackOverflow answer if you have doubts: http://stackoverflow.com/a/8865560/69809
TimeSpan waited = now - then;
// So, in some cases, 'waited' will be ~16ms. In that case, you will return immediately at the following line
// (although, you don't have a clue how much time has actually passed)
if (waited > amount) return;
// In other cases, 'waited' will be 0, and you will call Thread.Sleep(TimeSpan.FromTicks(100)) here.
// However, Thread.Sleep will discard your fractional milliseconds (MSDN link: http://msdn.microsoft.com/en-us/library/Vstudio/274eh01d)
// and essentially you'll be calling Thread.Sleep(0).
// Thread.Sleep(0) will then relinquish the remainder of its time slice (unless the CPU is really idle, but you have no control over this)
// to any thread of equal priority that is ready to run.
// Usual Windows stuff. No way to know how long this is going to take:
else System.Threading.Thread.Sleep(amount - waited);
// The following is obviously redundant, since you haven't modified 'now' and 'then',
// so they must still be equal at this point:
waited = now - then;
if (waited > amount) return;
// And, finally, the grand finale:
elseunchecked
{
// So, at this point, 'waited.Ticks' is always 0, so you might as well throw everything before
// this point away and call WaitRead(amount) without subtracting anything
if (m_Socket.WaitRead(((int)((amount.Ticks - waited.Ticks / TicksPerMicrosecond) / Divider))))
{
// Again, you're back to calling Environment.TickCount with its notorious 16ms resolution
then = μTimer.UniversalTime;
// No need to comment the rest, since it ends up calling Thread.Sleep(0) again
// and you have no guarantee how long the OS is going to have your thread suspended
amount -= waited;
waited = now - then;
if (waited > amount) return;
else System.Threading.Thread.Sleep(amount - waited);
}
}
}

I hope this clarifies all the problems with your function, and that's without even getting to the socket part.

So, to repeat the point 4. from my previous question, how about trying a test like this:

I don't know what your job includes, but I hope doesn't include programming anything life-critical.

You seem to be lacking fundamental knowledge about the OS you're programming for and the framework you are using, yet you are unwilling not only to accept that, but even to critically approach your theory. That's a truly dangerous trait, for you and people around you.