Unstable CPU usage

378 views Asked by At

I am currently writing application in C in which I intend to simulate CPU load in ubuntu less than 100%. I used factorials algorithm to stress my CPU and nanosleep function to regulate CPU usage. The goal is to have steady CPU usage with reasonable tolerance which can be varied in steps, i.e. 20%, 30% etc. The problem is when I start my app I get bouncing load 45-53% which where I want to have load with 50% CPU usage. Because of my research I need to get stable CPU usage where I calculate response time by tracking timestamp between two executions.

EDIT I'm using VmWare Workstation with Ubuntu 14.04 VM for my research. Here is the code

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>

int main(void)
{
    struct timeval t1;

    int milisec = 5; // length of time to sleep, in miliseconds
    struct timespec req = {0};
    req.tv_sec = 0;
    req.tv_nsec = milisec * 1000000L;

    FILE *file; 
    file = fopen("trace.txt", "w");
    //int j = 0;
    while(1)
    {
        gettimeofday(&t1, NULL);        
        int i;
        int res = 1;
        for(i = 0; i < 580000; i++)
        {   
            res = res*i;    
        }



        nanosleep(&req, (struct timespec *)NULL);


        fprintf(file, "%llu%llu\n", (unsigned long long)t1.tv_sec, (unsigned long long)t1.tv_usec);
        fflush(file);
        //j++;
    }
}
1

There are 1 answers

4
Tony Delroy On

Here's my take on it - seems pretty good in my light testing. Basic idea's to use getrusage to track how much CPU time the program's had, divide that by wallclock elapsed time, and yield if it's over the target ratio. You can see if it gives more stable results than your own code.

(NOTE: the question was tagged C++ and not C initially... code can trivially be ported to C)

#include <iostream>
#include <sstream>
#include <sys/time.h>
#include <sys/resource.h>

void usage_exit(const char* argv0)
{
    std::cerr << "usage " << argv0 << " <target>\n"
        "   spin burning <target> proportion of one CPU (e.g. 0.5 = 50%)\n";
    exit(1);
}

int main(int argc, const char* argv[])
{
    if (argc != 2)
        usage_exit(argv[0]);
    std::istringstream iss(argv[1]);
    double target;
    if (!(iss >> target))
        usage_exit(argv[0]);

    struct timeval start, now;
    gettimeofday(&start, 0);

    struct rusage usage;
    while (getrusage(RUSAGE_SELF, &usage) == 0)
    {
        gettimeofday(&now, 0);
        double running = usage.ru_utime.tv_sec + usage.ru_utime.tv_usec * 1E-6 +
                         usage.ru_stime.tv_sec + usage.ru_stime.tv_usec * 1E-6;
        double elapsed = now.tv_sec - start.tv_sec +
                         now.tv_usec * 1E-6 - start.tv_usec * 1E-6;
        if (running / elapsed > target)
            pthread_yield();
    }
}