Length of a Thread Quantum

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 Internalexplained 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.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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 timeAdjustment = 0;
   DWORD clockInterval100Ns = 0;
   BOOL timeAdjustmentDisabled = 0;
 
   // Step 3: Get the frequency of the clock interrupt. This value is
   // dependent on your processor type.
   GetSystemTimeAdjustment(
     &timeAdjustment,
     &clockInterval100Ns,
     &timeAdjustmentDisabled);
 
   // 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;
}
?
1
2
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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值