Ouch… It hertz!

June 30th, 2007 by ken

Often times, you want to change your program’s behavior based on available CPU Mhz (or GHz as is more common nowadays). For example, Call Recorder won’t default to using AAC encoding for audio recording if your Mac is under 800 Mhz.

So let’s say you want to find out the current CPU speed. It’s common to use the ancient but useful sysctl call.

int args[] = {CTL_HW, HW_CPU_FREQ};
int freq = 0;
size_t len = sizeof(freq);
if (sysctl(args, 2, &freq, &len, NULL, 0) == 0)
     printf(”It’s %d Hz\n”, freq);

gold-star.jpgA Gold Star if you can see what’s wrong with that code.

Wait for it…

Since sysctl returns the clock speed in tiny little old Hz (1 billionth of a GHz), we’re quickly running out of space in our 32-bit int. We’d overflow an unsigned int when we hit 4,294,967,296 Hz and we’ll overflow the signed int we used in the code above at only 2,147,483,648 Hz.

But that’s only 2.14 Ghz.

So on my 2.33 Ghz MacBook Pro, the code above will return:
It’s -1,964,967,296 Hz.
Oops…

Obviously, using an unsigned int instead of a normal int would have been wiser. However, even that will overflow when clock speeds double (in 2 years if you trust Moore’s law.)

Indeed, the solution is to use a long long or int64 (whichever camp you’re from.)

Here’s better code, using sysctlbyname instead, which is the recommended way to do it nowadays:

uint64_t freq = 0;
size_t size = sizeof( freq );
if (sysctlbyname( "hw.cpufrequency_max", &freq, &size, NULL, 0 ) == 0)
     printf("It's %lld Hz\n", freq);

This introduces a new overflow point when CPU speeds exceed 18,446,744,073 Ghz.

Interestingly, if you believe that Moore’s law will continue to hold, we should reach these speeds around 2071. That is, of course, assuming that the human race survives the Year 2038 Problem which will cause a similar overflow issue with the way OS X keeps track of the date seconds in an unsigned int.

20061222_star.jpgSwitching the date seconds to an int64 will cause a new problem in about 290 billion years.
However, due to predicted changes to the Solar System, it is not widely regarded as a pressing issue.

Also, don’t forget about good old OS 9’s Gestalt routine. You can’t use gestaltProcClkSpeed anymore for the same reason. (It returns a long.) But Gestalt also has a selector gestaltProcClkSpeedMHz, which drops the six useless zeros.


2 Responses to “Ouch… It hertz!”

  1. Nick M Says:

    Moore’s law says that the number of transistors per unit area will double every 18 months, not clock speed. Looking at only the last few years, clock speed seems to have hit a bit of a wall. That’s ok, because transistor doubling continues in the form of multi-core processors.

  2. scooby Says:

    What we need is a function that takes log(clockSpeed), where log could be base 2 or natural log.

Leave a Reply