Skip to contentSkip to conversation

interesting behaviour in cpu utilization accounting

DISCUSSION Chris Friesen 1 participant 1 message Nov 6, 2002

lore
Share & tools
lore
#0 lore raw

I was playing around with a tool to use a certain amount of cpu time. The way it does this is to take a timestamp, sleep for a tick, take another timestamp, and then busy-loop until the desired cpu utilization is reached, at which point it sleeps again.

I was very confused when the running tool didn't seem to show the right utilization in "top", so I made it print out how much time it spent sleeping and how much time it spent busy-waiting. It looked okay, but the "top" numbers didn't match.

Then I wrote another tool that busy-loops and prints out an index of how fast it busy-loops. If you run this tool on and idle system and then while its being loaded it gives an accurate picture of the real system load. Sure enough, the cpu utilization tool was working fine.

It looks like the pattern of behaviour of the cpu utilization tool is such that it minimizes how often it gets counted by the tick counter. This means that even though it really takes 20% of the cpu, it only registers 4-5% in top.

I'd love to hear what kind of results others get with these to programs or alternate explanations of what's going on, and whether this kind of thing is something we should worry about when doing sampling-based cpu utilization calculations.

Chris

//bsyloop
//adjust INTERVAL to change the printing interval
//adjust CONSTANT to give a convenient index
#include <iostream>
#include <asm/msr.h>
#define INTERVAL 100000000
#define CONSTANT 10
int main()
{
double counter = 0;
unsigned long long begin, end;
rdtscll(begin);
while(1)

   {
      counter++;
      if (counter == INTERVAL)
      {
         rdtscll(end);
         cout << "index: " << counter*CONSTANT / (end - begin) << endl;
         counter = 0;
         rdtscll(begin);
      }

}
}

//cpu utilization program
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <sched.h>
#include <asm/msr.h>

void chewcpu(double percent)
{
int blah;

   //handle 100% case first
   if (percent > 99.99)
   {
      while(1)
      {
         blah++;
      }
   }

cout << "want to be busy " << percent << " percent" << endl;

   sched_param param;
   param.sched_priority = 50;
   sched_setscheduler(getpid(), SCHED_RR, &param);

//anything other than 100%
while(1)

   {
      unsigned long long begin, aftersleep, end, current;
      unsigned long long busytime;
      struct timeval delay;

      rdtscll(begin);
      delay.tv_sec = 0;
      delay.tv_usec = 10000;

      //sleep one hundredth of a second
      //this is the smallest amount possible

      select(0, NULL, NULL, NULL, &delay);

      rdtscll(aftersleep);

      //now figure out how long we need to be busy to give the desired 
percentage
      busytime = (aftersleep - begin)/(100/percent - 1);

      //cout << "want to be busy " << busytime << " ticks" << endl;

      end = aftersleep + busytime;

      do{ rdtscll(current); } while(current < end);

      //cout << "slept " << (aftersleep - begin) << " ticks" << endl;
      //cout << "busy " << (current - aftersleep) << " ticks" << endl;

}
}

void usage(char *name)
{
cout << "usage: " << name << " <percentage>" << endl; exit (-1);
}

int main(int argc, char** argv)
{
if (argc < 2)

      usage(*argv);
   char *endptr = 0;
   double percent = strtod(argv[1],&endptr);

   if (endptr == argv[1])
   {
      cout << "died on strtod" << endl;
      usage(*argv);
   }

chewcpu(percent);
return 0;
}

Signature · 4 lines
Chris Friesen                    | MailStop: 043/33/F10
Nortel Networks                  | work: (613) 765-0557
3500 Carling Avenue              | fax:  (613) 765-2986
Nepean, ON K2H 8E9 Canada        | email: [email protected]