WINCE CPU内存的占用率计算

在进程的性能数据采集过程中,经常用到的一个性能指标就是进程的cpu占用率,下面给出它的计算方法及示例代码。
1、CPU占用率的定义
CPU占用率:指进程在一个时间段内消耗的CPU时间与该时间段长度的比值。
 
2、CPU占用率计算方法
根据上述定义,可以得到进程CPU占用率计算公式如下:
进程消耗的CPU时间 = 进程消耗的内核态时间 + 进程消耗的用户态时间,即 costTime = kernelTime + UserTime
进程的CPU占用率 = 进程消耗的CPU时间 / 刷新周期(总耗时)



void McuUsageThread::run(){
    THREADENTRY32 te32 = {0};
    FILETIME    ftTimeCreation = {0};
    FILETIME    ftTimeExit = {0};
    FILETIME    ftTimeKernel = {0};
    FILETIME    ftTimeUser = {0};
    FILETIME    ftLastTimeKernel = {0};
    FILETIME    ftLastTimeUser = {0};
    HANDLE      hSnap = NULL;
    LARGE_INTEGER    liPerfFreq = {0};
    LARGE_INTEGER    liPerfCountLast = {0};
    LARGE_INTEGER    liPerfCountCur = {0};
    LONGLONG    llPerfDelta = 0;
    LONGLONG    llUserCur = 0;
    LONGLONG    llKernelCur = 0;
    LONGLONG    llUserLast = 0;
    LONGLONG    llKernelLast = 0;
    LONGLONG    llKernelDelta = 0;
    LONGLONG    llUserDelta = 0;


    if (!QueryPerformanceFrequency((LARGE_INTEGER*)&liPerfFreq))
    { //类型:Win32API
//原型:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
//作用:返回硬件支持的高精度计数器的频率。
//返回值:非零,硬件支持高精度计数器;零,硬件不支持,读取失败
//liPerfFreq 为获取的时钟频率
        return;
    }


    CeSetThreadPriority(GetCurrentThread(), 100);
//设置线程的优先级,GetCurrentThread()线程的句柄,第二个参数是线程的优先级
    while (1)
    {
        Sleep(m_u32SampleTime_ms);


        llKernelCur = 0;
        llUserCur = 0;


        hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
//建立一个快照,获取进程列表
//参数1,用来指定快照中需要返回的对象,
//参数2,一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取 当前进程快照时可以设为0
//具体看下一篇博文,


        if (hSnap != INVALID_HANDLE_VALUE)
        {
            te32.dwSize = sizeof(te32);
            if (Thread32First(hSnap, &te32)) //获取快照中第一个线程信息
            {
                do
                {
                    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
                    if (hThread)
                    {
                        GetThreadTimes(hThread, &ftTimeCreation,
                                       &ftTimeExit, &ftTimeKernel, &ftTimeUser);
//获取线程时间
//参数1,线程句柄;参数2:创建时间;参数3:退出时间;参数4:内核时间;参数5:用户时间
                        llKernelCur += *((LONGLONG*)(&ftTimeKernel)) - *((LONGLONG*)(&ftLastTimeKernel));
                        llUserCur += *((LONGLONG*)(&ftTimeUser)) - *((LONGLONG*)(&ftLastTimeUser));
                        CloseHandle(hThread);
                    }
                } while (Thread32Next(hSnap, &te32));//获取快照中下一个线程信息
            }
            CloseToolhelp32Snapshot(hSnap);//关闭快照
        }

        QueryPerformanceCounter(&liPerfCountCur);
        llPerfDelta = liPerfCountCur.QuadPart - liPerfCountLast.QuadPart; //计数
        llPerfDelta = 10000000 * llPerfDelta/liPerfFreq.QuadPart; //转化为时间,10000000是飞秒单位换算出来的
//总耗时=时钟数/频率 =时钟数*(一个时钟数的时间1/频率);
        liPerfCountLast = liPerfCountCur;

        llKernelDelta = llKernelCur - llKernelLast; //内核消耗的时间
        llUserDelta = llUserCur - llUserLast;       //用户消耗的时间
        llKernelLast = llKernelCur;
        llUserLast = llUserCur;

        INT32 dCPUKernel; dCPUKernel = MATH_MAX(0, MATH_MIN(100.0, 100.0 * llKernelDelta/llPerfDelta));
//内核消耗的时间的百分比
        INT32 dCPUsage; dCPUsage = MATH_MAX(dCPUKernel, MATH_MIN(100.0, 100.0 * (llUserDelta + llKernelDelta)/llPerfDelta));
//用户消耗加内核消耗时间百分比


        MEMORYSTATUS    memStatus;
        memStatus.dwLength = sizeof(MEMORYSTATUS);
        GlobalMemoryStatus(&memStatus);//获取内存信息

//MEMORYSTATUS结构体分析
/*
typedef struct _MEMORYSTATUS {
    DWORD dwLength; //本结构体的长度
    DWORD dwMemoryLoad; //已用内存的百分比
    DWORD dwTotalPhys;  //物理内存总量
    DWORD dwAvailPhys;  //可用物理内存
    DWORD dwTotalPageFile; //交换文件总的大小
    DWORD dwAvailPageFile; //交换文件中空闲部分的大小
    DWORD dwTotalVirtual;  //用户可用的地址空间
    DWORD dwAvailVirtual;  //当前空闲的地址空间
} MEMORYSTATUS, *LPMEMORYSTATUS;


*/


        PRINTF_MSG("@@@@@@@@@@@======================== dCPUsage is %d , dCPUKernel is %d  ", dCPUsage, dCPUKernel);
        PRINTF_MSG("@@@@@@@@@@@======================== UsageMem is %s, TotalMem is %s  ", FormatMemory_toString(memStatus.dwTotalPhys - memStatus.dwAvailPhys).toUtf8().data(), FormatMemory_toString(memStatus.dwTotalPhys).toUtf8().data());
    }
}



QString McuUsageThread::FormatMemory_toString(quint32 f_u32BytesNum) {//打印需要的
    quint32 t_u32bt = f_u32BytesNum & 0x2FF;
    quint32 t_u32Kb = (f_u32BytesNum>>10) & 0x2FF;
    quint32 t_u32Mb = (f_u32BytesNum>>20);
    return QString::number(t_u32Mb) + "Mb " + QString::number(t_u32Kb) + "Kb " + QString::number(t_u32bt) + "byte";
}
/******************************************************************************************************/
class McuUsageThread : public QThread //创建线程用于获取打印cpu内存的占用率
{
public:
    quint32 m_u32SampleTime_ms;
    McuUsageThread(){
        m_u32SampleTime_ms = 3500;
    }
    QString FormatMemory_toString(quint32 f_u32BytesNum);


public:
    void run();
};

/******************************************************************************************************/

总结:整个代码的思路就是:

1.获取系统时钟频率

2.设置单前线程的优先级(觉得可以不用,没有验证不设置的正确性)

3.创建一个线程快照遍历,

4.根据快照获取线程的相关时间,并计算所有线程的耗时。

5.获取计时器的值,(高精度硬件支持的计时器)。

6.通过获取到的计时器的值和系统时钟频率计算出总耗时.

7.分别计算出内核耗时百分比,和用户耗时百分比。


内存的占用计算比较简单就不多说了,看代码都能懂。



猜你喜欢

转载自blog.csdn.net/DreamSonGO/article/details/78469841