# Length of a Thread Quantum

In Windows, threads run in units of “quantums”. After a thread completes its quantum, Windows may choose to run another thread based on priority or thread states.

This quantum settings is located in the registry called Win32PrioritySeparation. It is a wacky matrix that is represented in a bitfield.

Window XP and Vista uses short variable quantum settings. Thread owned by a process with a foreground window are assigned 18 quantums, and background window (e.g. services) are assigned 6 quantums. The Window Server edition uses 36 quantums for all threads.

So how long exactly is one quantum?

### One Quantum

Although the length of a quantum is not exposed to developers, Windows Internal explained that the value is located in a kernel variable called KiCyclesPerClockQuantum. You can extract the value through Windbg with a command “dd nt!KiCyclesPerClockQuantum  l1“.

Alternatively, the book devised a method to calculate the value manually. Below is a program I wrote following the described algorithm.

```try
{
CPdhQuery procInfo_frequency(std::tstring(
_T("\\Processor Information(0,0)\\Processor Frequency"))
);

// Step 1: Get the CPU speed in MHz
__int64 cpuSpeedHz = static_cast<__int64>(
procInfo_frequency.CollectSingleData()
);

// Step 2: Convert it to Hz
cpuSpeedHz *= 1000000;

DWORD clockInterval100Ns = 0;

// Step 3: Get the frequency of the clock interrupt. This value is
// dependent on your processor type.
&clockInterval100Ns,

// Step 4: Get the rate of the clock fires per second.
double clockIntervalPerSecond =
static_cast<double>(clockInterval100Ns)/10000000;

// Step 5: Get the number of cycles elapsed per clock interval.
double cyclesPerClockInterval = cpuSpeedHz * clockIntervalPerSecond;

// Step 6: A quantum is 1/3 of a clock interval.
__int64 clockCyclePerQuantum =
static_cast<__int64>(cyclesPerClockInterval / 3);

// Step 7: The quantum length in time
double quantumLengthSec =
static_cast<double>(clockCyclePerQuantum) /
static_cast<double>(cpuSpeedHz);

tcout
<< _T("Clock Cycles Per Quantum = ")
<< clockCyclePerQuantum
<< std::endl;

tcout
<< _T("Duration Per Quantum = ")
<< quantumLengthSec
<< _T(" second")
<< std::endl;
}
catch(CPdhQuery::CException const &e)
{
tcout << e.What() << std::endl;
}
```
```Clock Cycles Per Quantum = 13873688
Duration Per Quantum = 0.00520003 second
```

### Thoughts

The quantum value provides insight on how often a thread may be preempted.

This information can be surprising useful. I recently used it to roughly estimate a thread’s response time, and correctly determined a device driver issue.

The output of my program differs slightly (~3%) from the readings in the kernel. It appears that the processor frequency in performance counter is different from the reading in PRCB.