如何得到本进程的CPU占用率?

我们的语音平台程序,需要运行在大线路并发环境,要求有很高的性能。
因为是多线程程序,在几百上千个线程同时加载脚本的时候,千军万马过独木桥,往往导致极大的CPU开销,比较好的办法就是在每个加载线程内对CPU占用进行判断,如果占用率小于某个值,就继续运行,否则就Sleep(),等候CPU占用的下降。

win32 API并没有提供直接得到CPU占用率的函数,但提供GetProcessTimes()函数可以得到进程占用的CPU时间,通过和实际时间的流逝相比,可以得到某进程占用CPU的比率。

好了,下面就是完整的C++代码。

//  得到当前进程的CPU占用率
class  GetCPUPercentage
{
  
private:
    CRITICAL_SECTION cs;  
// 供多线程同步的临界区变量
    HANDLE hd;    // 空闲进程的句柄
    DWORD t1;     // 时间戳
    int percent;  // 最近一次计算的CPU占用率

    __int64 oldp;
    __int64 FileTimeToInt64(
const FILETIME& time);
    
int GetTime(__int64& proc);  // 得到进程占用的CPU时间
  public:
    GetCPUPercentage();
    
~GetCPUPercentage();

    
int Get();  // 得到CPU占用率
}
;

GetCPUPercentage::GetCPUPercentage()
{
  InitializeCriticalSection(
&cs);  // 初始化线程临界区变量

  percent 
= 0;   // 初始的占用率

  DWORD pid 
= GetCurrentProcessId();   // 得到当前进程id
  hd  = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);  // 通过id得到进程的句柄
  if( hd==NULL ){
     
return;
  }


  
// 得到初始时刻的值
  GetTime(oldp);
  t1 
= GetTickCount();
}


GetCPUPercentage::
~ GetCPUPercentage()
{
  
if( hd!=NULL ){
     CloseHandle(hd);
  }

  DeleteCriticalSection(
&cs);
}


//  时间格式转换
__int64 GetCPUPercentage::FileTimeToInt64( const  FILETIME &  time)
{
  ULARGE_INTEGER tt;
  tt.LowPart 
= time.dwLowDateTime;
  tt.HighPart 
= time.dwHighDateTime;
  
return(tt.QuadPart);
}


//  得到进程占用的CPU时间 
int  GetCPUPercentage::GetTime(__int64 &  proc)
{
  FILETIME create;
  FILETIME exit;
  FILETIME ker;  
// 内核占用时间
  FILETIME user; // 用户占用时间
  FILETIME now;
  
if!GetProcessTimes(hd, &create, &exit, &ker, &user) ){
     
return(-1);
  }


  proc 
= (FileTimeToInt64(ker) + FileTimeToInt64(user))/10000;
  
return(0);
}


//  进行换算
int  GetCPUPercentage::Get()
{
  
if( hd==NULL )
     
return(0);

  EnterCriticalSection(
&cs);
    DWORD t2 
= GetTickCount();
    DWORD dt 
= t2 - t1;
    
if( dt>139 ){  // 毫秒数。用一个比较少的时间片作为计算单位,这个值可修改
       __int64 proc;
       GetTime(proc);

       percent 
= ((proc-oldp)*100)/dt;

       t1 
= t2;
       oldp 
= proc;
    }

  LeaveCriticalSection(
&cs);
  
return(percent);
}


//  定义一个全局变量
GetCPUPercentage _cpu;

//  下面是用C++Bulider写的测试例子:
//  --------------------------
//  在用一个时钟不停地显示当前的CPU占用率
void  __fastcall TForm1::Timer1Timer(TObject  * Sender)
{
  Label1
->Caption = _cpu.Get();
}


// ---------------------------------------------------------------------------
//  再弄个按钮
LRESULT WINAPI TestThread(LONG lParam)
{
  
int n = lParam;
  
for(int i=0 ;i<n; i++){
     Form1
->Label2->Caption = i;
     Sleep(
12);
  }

  
return(0);
}

//  点击这个按钮会创建一些线程来把CPU整的繁忙些
void  __fastcall TForm1::Button1Click(TObject  * Sender)
{
  
int n = atoi(Edit1->Text.c_str());
  DWORD dwThreadid;
  CreateThread(NULL, 
0, (LPTHREAD_START_ROUTINE)TestThread,
                (
void*)n, 0&dwThreadid);
}

// ---------------------------------------------------------------------------
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值