|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI had a code that consists of a thread that was heavily CPU intensive. And I needed to limit its execution so that its CPU usage would not go above a particular limit, irrespective of the hardware/processor over which the program was running. Moreover we often come across a problem, in which we need to The Here is a class that will limit CPU usage of a thread to a specified limit and also help to control its execution. It can be said that it is a better alternative to Using the CodeThe core logic of this code is as follows. The main purpose of our code is to keep the average CPU usage of a thread to a specified limit. This limit is a percentage of sum of user and kernel time spent by the thread to that of sum of idle, user and kernel time spent by the system. So let's say at time So (Tn-To)/(Sn-So) <= R/100
=> (Tn-To) X 100<=(Sn-So) X R
=> (Tn-To) X 100 - (Sn-So) X R <= 0
So if this equation is greater then zero, then we can say that the limit is crossed. (Tn-To)/((Sn-So) + Z) = R/100
=> (Tn-To) X 100 = ((Sn-So) + Z) X R
=> (Tn-To) X 100 = (Sn-So) X R + Z X R
=> (Tn-To) X 100 - (Sn-So) X R = Z X R
=> (Tn-To) X (100/R) - (Sn-So) = Z
This shows how we are going to calculate the time period we need to sleep to keep processor usage within limits. The core class here is To fetch Thread and System CPU usage timing Here is the structure of const int DEFAULT_MAX_PERCENTAGE = 20;
/*
CPULimiter:
This class helps to limit the CPU usage/consumption by a thread involving
some kind of repetitive/polling kind of operation in a loop.
The limit can be set by a user through a function of this class.
*/
class CPULimiter
{
//This integer stores last total system time.
//total system time is sum of time spent by system
//in kernel, user and idle mode
LARGE_INTEGER m_lastTotalSystemTime;
//This integer stores last total time spent by this
//thread in kernel space and user space
LARGE_INTEGER m_lastThreadUsageTime;
//Variable used to store maximum thread CPU percentage
//relative to system total time.
int m_ratio;
public:
//Constructors
CPULimiter();
//Constructor with maximum thread cpu usage percentage
CPULimiter(int p_ratio);
//****************Main function.******************
//It evaluates CPU consumption by this thread since
//last call to this function, until now.
//Internally, it calculates if the thread has exceeded
//the maximum CPU usage percentage specified.
//if yes, it makes the thread sleep for a calculated
//time period, to average the total usage to the limit specified.
//Returns TRUE Successful, else FALSE
BOOL CalculateAndSleep();
//Inline setter function
inline void SetRatio(int p_ratio){m_ratio = p_ratio;}
};
And this is the BOOL CPULimiter::CalculateAndSleep()
{
//Declare variables;
FILETIME sysidle, kerusage, userusage, threadkern
, threaduser, threadcreat, threadexit;
LARGE_INTEGER tmpvar, thissystime, thisthreadtime;
//Get system kernel, user and idle times
if(!::GetSystemTimes(&sysidle, &kerusage, &userusage))
return FALSE;
//Get Thread user and kernel times
if(!::GetThreadTimes(GetCurrentThread(), &threadcreat, &threadexit
, &threadkern, &threaduser))
return FALSE;
//Calculates total system times
//This is sum of time used by system in kernel, user and idle mode.
tmpvar.LowPart = sysidle.dwLowDateTime;
tmpvar.HighPart = sysidle.dwHighDateTime;
thissystime.QuadPart = tmpvar.QuadPart;
tmpvar.LowPart = kerusage.dwLowDateTime;
tmpvar.HighPart = kerusage.dwHighDateTime;
thissystime.QuadPart = thissystime.QuadPart + tmpvar.QuadPart;
tmpvar.LowPart = userusage.dwLowDateTime;
tmpvar.HighPart = userusage.dwHighDateTime;
thissystime.QuadPart = thissystime.QuadPart + tmpvar.QuadPart;
//Calculates time spent by this thread in user and kernel mode.
tmpvar.LowPart = threadkern.dwLowDateTime;
tmpvar.HighPart = threadkern.dwHighDateTime;
thisthreadtime.QuadPart = tmpvar.QuadPart;
tmpvar.LowPart = threaduser.dwLowDateTime;
tmpvar.HighPart = threaduser.dwHighDateTime;
thisthreadtime.QuadPart = thisthreadtime.QuadPart + tmpvar.QuadPart;
//Check if this is first time this function is called
//if yes, escape rest after copying current system and thread time
//for further use
//Also check if the ratio of differences between current and previous times
//exceeds the specified ratio.
if( thisthreadtime.QuadPart != 0
&& (((thisthreadtime.QuadPart - m_lastThreadUsageTime.QuadPart)*100)
- ((thissystime.QuadPart - m_lastTotalSystemTime.QuadPart)*m_ratio)) > 0)
{
//Calculate the time interval to sleep for averaging the extra CPU usage
//by this thread.
LARGE_INTEGER timetosleepin100ns;
timetosleepin100ns.QuadPart = (((thisthreadtime.QuadPart
- m_lastThreadUsageTime.QuadPart)*100)/m_ratio)
- (thissystime.QuadPart
- m_lastTotalSystemTime.QuadPart);
//check if time is less than a millisecond, if yes, keep it for next time.
if((timetosleepin100ns.QuadPart/10000) <= 0)
return FALSE;
//Time to Sleep :)
Sleep(timetosleepin100ns.QuadPart/10000);
}
//Copy usage time values for next time calculations.
m_lastTotalSystemTime.QuadPart = thissystime.QuadPart;
m_lastThreadUsageTime.QuadPart = thisthreadtime.QuadPart;
return TRUE;
}
Here is a sample CPU intensive code using this class: int _tmain(int argc, _TCHAR* argv[])
{
std::cout<<"This is a cpu intensive program";
//define CPULimiter variable
//and limit cpu usage percentage to 5% here.
CPULimiter limiter = 5;
int a,b;
a = 78;
//Some CPU intensive code here....
while(1)
{
b = a;
//limit cpu usage here.
limiter.CalculateAndSleep();
}
return 0;
}
Note: Here we have confined the usage to 5%. If we hadn't, this would have consumed all the CPU. CPULimiter limiter = 5;
History
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||