What does QueryThreadCycleTime actually count?


A customer wanted some clarification on the Query­Thread­Cycle­Time function.

Based on the name, it suggests that it counts CPU cycles, but they observed that when the power profile is set to Balanced (which lets the CPU run at low frequencies when there is low demand), the thread cycle time increases twice as fast as when the power profile is set to High Performance (which sets the CPU to run at full speed all the time), even though the same code is executing in both scenarios. If it's the same code, shouldn't the cycle times be comparable? The function appears to be measuring elapsed time, not cycle time.

The documentation for the Query­Thread­Cycle­Time function function contains this caveat:

Do not attempt to convert the CPU clock cycles returned by Query­Thread­Cycle­Time to elapsed time. This function uses timer services provided by the CPU, which can vary in implementation. For example, some CPUs will vary the frequency of the timer when changing the frequency at which the CPU runs and others will leave it at a fixed rate. The behavior of each CPU is described in the documentation provided by the CPU vendor.

This function uses the CPU's cycle counter instruction. For x86 and x64 processors, this means RDTSC. And according to Wikipedia, recent Intel processors fall into the second category, where the time stamp counter runs at a fixed rate regardless of CPU speed. This means that when the CPU is running at reduced speed, it can execute fewer instructions per counter. From the point of view of the program, it looks like the time stamp counter is running at a higher rate.

So what does Query­Thread­Cycle­Time actually count?

The answer is "Whatever the CPU wants."

Comments (17)
  1. Brian_EE says:

    Then the customer followed up with this question: "How do we programmatically determine what type of timer implementation the CPU has?"

    1. pc says:

      Well, that's easy enough, just do it the way Raymond did. Do a CPUID, and programatically download the referenced Wikipedia page. Use an appropriate English knowledge-parsing AI to read it and determine what your CPU does.

      1. Cristi says:

        Or do a cpuid and parse the result yourself because a certain bit in a certain leaf is set if the CPU supports invariant TSC.

  2. 12BitSlab says:

    Which devs would need this knowledge -- game developers???

    1. DWalker says:

      I wondered the same thing.

      "Don't try to interpret this information. You do not need to know what type of timer implementation the CPU has."

      The CPU timer implementation could change from one minute to the next.

  3. Ray Koopa says:

    So it's basically what the Windows 8+ task manager displays in App History > CPU Time column?

    1. Josh B says:

      RDTSC is what every Task Manager since 2000 has displayed in the CPU Time column. NT4 might've use RDTSC or the system clock, I'm not sure, but it also had CPU Time. The OS itself does the tracking, by keeping track of RDTSC (originally via regular QueryPerformanceCounter/QueryPerformanceFrequency calls, now inserted into all context switches) per-application and dealing with all of the necessary calculations to figure out what it means, except in Vista/2008, where it was changed to use the chipset HPET or ACPI timers, which are high-latency but always constant. 7/2008R2 and up will now use _either_ RDTSC or the chipset timer, after determining whether RDTSC is now constant or not on startup. (Or maybe it has a giant list of hardware, I don't know.) 8 and 10 haven't changed this.

      1. Ray Koopa says:

        Thanks for the info; I forgot about that column in pre-8 task manager and just focussed on this new "App History" tab.

  4. Ivan K says:

    I'd be worried about negatively impacting performance over using those api's.

    1. If performance > accuracy, then QueryThreadCycleTime should be "good enough" as long as you understand the gotchas. If accuracy > performance, then the performance counters make more sense.

  5. Killer{R} says:

    IMHO the name of this function contains 2 errors since its not about thread and its not about CPU cycles. So Instead of Query­Thread­Cycle­Time it should be called QueryCPUTimeStamp

    1. Killer{R} says:

      hm, sorry. Its about thread, so then it should be QueryThreadCPUTimeStamp, like rdtsc is actually

      1. Osxpert says:

        Wiki says tsc counts numer of CPU cycles since reset, som how is this related to threads?

      2. That's still not quite right, because QueryThreadCPUTimeStamp sounds like it gets the absolute timestamp for the CPU the thread is currently on. But really, it gets the cumulative timestamp for all of the CPUs the thread has run on, for the time the thread was running on that CPU. (Also, naming the function after the rdtsc instruction works only for CPUs that have a rdtsc instruction in the first place, and only for machines where rdtsc is in fact the source of the cycle counter.) The existing name is wrong but it's least wrong.

        1. smf says:

          >The existing name is wrong but it’s least wrong.

          The existing name cannot be removed in any case, so it's a moot point. Einstein proved that time is not constant, so it's fine :-)

  6. BZ says:

    So what purpose does this function serve?

    1. smf says:

      The msdn article refers to Thread32First and Thread32Next, so I assume it's useful in limited debugging situations.

Comments are closed.

Skip to main content