Thread Quantum

Edit October 26, 2014: The commenter known as dirbase corrected me on some errors I made in this post, which I will now be correcting.  Thank you very much for the constructive feedback, dirbase. :) 

Still being a bit lazy about the blog -- I've been busy reading and working, both of which have longer quantums than writing for this blog, apparently.

Basically I just wanted to take a moment out of this Sunday afternoon to discuss thread quantums.  This entire post is inspired by Windows Internals, 6th Ed. by Mark Russinovich, et al.  As always, I could not recommend the book more highly.

So, we've all seen this screen, right?  Adjust processor scheduling for best performance of "Programs" or "Background services:"

Advanced System Properties

Well that seems like a very simple, straightforward choice... but who knows what it actually means?  To answer that question, we need to know about a basic mechanism that Windows uses: Quantum.

A thread quantum is the amount of time that a thread is allowed to run until Windows checks if there is another thread at the same priority waiting for its chance to run.  If there are no other threads of the same priority waiting to run, then the thread is allowed to run for another quantum.

Process Priority is that attribute that you can set on a process in Task Manager or in Process Explorer by right-clicking a process and choosing its priority.  Even though it's the threads that actually "run" and not processes per se, each process can have many dynamically-lived threads, so Windows allows you to set a priority per process, and in turn each thread of that process inherits its base priority from its parent process. (Threads actually have two priority attributes, a base and a current priority.  Scheduling decisions are made based on the thread's current priority.)

There are 32 process priority levels, 0-31, that are often given simplified labels such as "Normal," "Above Normal," "Real time," etc.  Those are all within the subset of 0-1 on the Interrupt Request Level (IRQL) scale.  What this means is that if you set a process to run at "Real Time" - or the highest possible priority - the process and its threads will still not have the ability to preempt or block hardware interrupts, but it could delay and even block the execution of important system threads, not to mention all other code running at Passive level.  That is why you should have a very good reason for setting a process to such a high priority.  Doing so has the ability to affect system-wide stability.

So now, back to quantum.  We now know its definition, but how long exactly is a quantum?  That depends on your hardware clock resolution (not to be confused with timer expiration frequency,) the speed of your processor, and how you have configured that setting pictured above to optimize performance for "Programs" or "Background services."  As of Windows 7 and Windows Server 2008 R2, clients are configured to let threads run for 2 clock intervals before another scheduling decision is made, while it's 12 clock intervals on servers. So when you change that setting on the Performance Options page, you are bouncing back and forth between those two values.

The reasoning for the longer default quantums on Server operating systems is to minimize context switching, and that if a process on a server is woken up, with a longer quantum it will have a better chance of completing the request and going back to sleep without being interrupted in between.  On the other hand, shorter quantums can make things seem "snappier" on your desktop, leading to a better experience for desktop OSes.

As I said before, the resolution of your system clock is a factor in determining how long a quantum really is.  In contemporary x86 and x64 processors, this is usually 15.6 milliseconds and it's set by the HAL, not the OS kernel.  You can see what it's set to for yourself by using a kernel debugger and examining KeMaximumIncrement:

KeMaximumIncrement

Reading the bytes right to left, if you convert 02, 62, 5A to decimal, you will get 156250, which represents about 15.6ms. Don't confuse this value with timer expiration frequency/interval.  The two values are related, but different.

There are a couple of different ways to obtain timer expiration frequency/interval.  One way is with clockres.exe from Sysinternals:

clockres.exe

Notice that the maximum timer interval is the familiar 15.6 milliseconds, which is also my hardware clock interval.  But my current timer interval is 1ms.  Programs running on your system can request system-wide changes to this timer, which is what has happened here.  You can use powercfg.exe -energy to run a power efficiency analysis of your system that will identify processes that have made such requests to increase the resolution of the system timer.  When timer expirations fire at a higher frequency, that causes the system to use more energy, which can be of significant concern on laptops and mobile devices that run on battery power.  In my case, it's usually Google Chrome that asks that the system timer resolution be increased from its default of 15.6ms.  But remember that even when this timer interval changes, it doesn't change the length of thread quantums, as thread quantum calculation is done using the max or base clock interval.

When Windows boots up, it uses the above KeMaximumIncrement value, in seconds, and multiplies it by the processor speed in Hertz, divides it by 3 and stores the result in KiCyclesPerClockQuantum:

KiCyclesPerClockQuantum

Converted to decimal, that is 17151040 CPU cycles.

The other factor in determining the length of a quantum is base processor frequency.  You can obtain this value in several different ways, including using the !cpuinfo command in the debugger: 

!cpuinfo

3.293 GHz is the base frequency of my processor, even though a command such as Powershell's

$(Get-WMIObject Win32_Processor).MaxClockSpeed

would report 3.801 GHz as the maximum frequency. This is a slightly overclocked Intel i5-2500k.  Now that we have those two pieces of information, all that's left is some good old fashioned arithmetic:

The CPU completes 3,293,000,000 cycles per second, and the max timer interval, as well as the hardware clock resolution, is 15.6 ms.  3293000000 * 0.0156 = 51370800 CPU cycles per clock interval.

1 Quantum Unit = 1/3 (one third) of a clock interval, therefore 1 Quantum Unit = 17123600 CPU cycles.

This is only a tiny, rounding error amount off from the value that is stored in KiCyclesPerClockQuantum.

Assuming that at a rate of 3.293GHz, each CPU cycle is 304 picoseconds, that works out to 5.2 milliseconds per quantum unit.  Since my PC is configured for thread quantums of 2 clock intervals, and each clock interval is 3 quantum units, that means my PC is making a thread scheduling decision about every 31 milliseconds.

Now there's one final complication to this, and that is by using the "Programs" performance setting as opposed to the "Background services" setting, you are also enabling variable length quantums.  Whereas a typically configured server will use fixed-length, 12 clock-interval quantums... but I'll leave off here and if you're interested in knowing more about variable length quantums, I would suggest the book I mentioned at the beginning of this post.

Windows Portable Executable (PE) Diagram

This one falls squarely under the category of "Windows Internals."  I ran across this sweet diagram today that dissects the Windows Portable Executable format.  It would make an awesome poster, in my opinion.

The original link is here, and I have mirrored the PDF version here:

PE101-v1.pdf (382.25 kb) - Credit goes to Ange Albertini - corkami.com.

ORS - Office Rageface Sender

freddie

If you work in an office in a corporate environment like I do, you're probably familiar with Microsoft Office Communicator, often referred to as OCS. These days they call it Lync -- but it's still most widely known as OCS. Anyway, it's an IM client that you can use to communicate with your bosses... and for them to see when you're taking a bit too long of a lunch break. The one thing it doesn't do, however, is quickly paste pictures for others to see. A picture is worth a thousand words, right? So I set out this last weekend to remedy this situation.

What I ended up with a couple days later is what I'm calling ORS - or Office Rageface Sender. A coworker of mine is very fond of those ragefaces that seem to be all the... rage... lately, but it's difficult to make those jokes without actually being able to show the relevant picture to go with it. 

Currently, ORS is a network application, but only works within your current subnet, because it uses UDP broadcasts as a "discovery" mechanism to discover peers on the network (i.e. other people also running ORS) to populate your contact list. In addition, TCP port 9068 is used for direct communication. 

Upon launching ORS for the first time, you will be asked for your nickname. You can change it at any time by clicking the status bar at the bottom of the main window. Your nickname will be saved in the registry so it won’t ask you every time you launch the app. The effects of duplicate nicknames on the network hasn’t been thoroughly explored, (hey I’m only one guy) but they should be minimal as communications are typically IP-based. 

Also when you launch ORS for the first time, it will create an Images folder at the same location where the executable is running. Dump all your favorite images here. Optimally, they should be as close to 512x512 as possible, as they will be displayed in a 512x512 window. However, images larger than that will be automatically scaled down to fit. Images smaller than that will be centered (not stretched.) 

When you right-click on a person’s name in the main window, a context menu will pop up which contains a list of all the images currently in your Images directory. This list and context menu is dynamic, so you don’t need to relaunch the app every time you modify the contents of your images directory. By clicking an image name over a contact, that image will be displayed on their screen in real-time. 

If the recipient does not currently have the image that you are trying to send them, you will automatically send it to them over TCP, it will be saved to their own Images directory, and then displayed normally. If they already have the same image (as determined by name,) that local image will be displayed. If two users have the same filename in their images directory but are actually different pictures, then the recipient will see a different image than the one you intended. 

The application minimizes to the system tray. You can right-click the icon to exit the app, or just close the form. 

If you’d like to give this a try when you’re in the same broadcast domain with one or two other people, you can download the program at the very end of this post. I very much welcome bug reports, feature requests, etc. You probably don't want to run this with a bunch of people you don't trust, as it would be possible for them to flash pictures of boobs on your screen if they wanted to.

ors

Finally, here are some stats on how much broadcast traffic each client sends, just to prove how nominal it is. About 1 packet every 10 seconds. 

Avg packets/sec 0.128
Avg packet size 75 bytes
Avg bytes/sec   9.587

ORS.exe (93.00 kb)

C# applications with "install" or "setup" in the name and Application Compatibility

Hello ladies and gents.

I've been busy the past few days creating a very complex (for me) .NET application in C#. I want to talk about an issue that I banged my head on for a few hours, because the solution is out there and easy to find on the internet, but every person who posted the answer on a forum or MSDN article was making an assumption that I knew something already that I didn't know in order to arrive at the solution, and so that missing piece of knowledge was keeping me from joining the ranks of those who knew how to solve this problem. What can I say, I'm a novice programmer.

I'm using Visual Studio 2010, and I have created a C# project. I'm using Windows 7 64bit. This project that I have created has the word "install" in the name. Apparently, any time that Windows Vista or 7 see the user executing a program that has the word "setup" or "install" in it, it triggers something deep within the bowels of Windows to cough up this incisive message:

appcompat*Thank you that's very helpful now go away*

I don't like the principle behind this behavior. I have read that this box will only pop up if you have the magic word in your executable name and that executable does not add an entry to the Add/Remove Programs list by the time it exits, which could indicate a failed installation. Or it could indicate nothing went wrong at all, which from my experience is the case 100% of the time. In fact I'd be scared to hit that "Reinstall using recommended settings" button, because I definitely have no idea what that might do. Furthermore I've read that some install applications do put a new entry in the Add/Remove Programs list and yet it still generates this popup.

I've been using Windows Vista and Windows 7 for a long time, and I have never once found this to be helpful in any way. But now this behavior has really gone and annoyed me by popping up every time I test during my development.

So I started researching the problem and I was immediately led to believe that this could be easily solved by editing the manifest file in my application's project in Visual Studio. Here is what you add to your manifest file to make it not show that Program Compatibility popup:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
   <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
   </application>
</compatibility>

OK... I can't find my manifest file. I've looked through all the menus and tabs and buttons here in Visual Studio... hrm... maybe I just need to edit this installer.manifest file that's sitting in the same output directory as my application and then rebuild it! Nope, that didn't work. It just seems to wipe out my changes and revert the file to default every time I build the solution... my project settings were set to "Embed manifest with default settings."  So even though the default manifest was there in the output directory, any modifications you make to it just get wiped out.

Finally, I realized that I just need to generate a new manifest file for myself. In the Solution Explorer pane, right-click your project and choose "Add --> New Item..." and add an "Application Manifest File." It should pop up under the Resources folder in your project, whether you already had one or not. Now you can edit that manifest to your heart's content, and the changes will not get wiped out. You'll notice that the section of XML I pasted above sort of already exists in your new manifest file, so just use your head and paste in only the couple of relevant lines in the right places. ;)  You will also notice that if you go back to your Project's properties, you should see it pointing at the manifest file you just created, instead of saying "Embed manifest with default settings."

No more "Program Compatibility Assistant" popup!  I feel like an idiot sometimes...

Now  that you know about creating and editing your own application manifest file, you are well on your way to doing other things with it, such as having the application request its own administrator access from UAC, instead of, say, simply checking to see whether the current user is an administrator or not, and then having the application say "Sorry, you're not an administrator so I won't run.  Please try executing the program again by right-clicking on my icon and choosing 'Run as administrator...'" Which unfortunately I have seen too many times. Follow up with this article.