使用Sleep降低CPU能耗同时配合QueryPerformanceFrequency做高精度帧率控制

最近做项目,遇到了需要毫秒级别的定时刷新界面,Windows上的高精度定时器网上实现的方式不外乎三种,一种是以WM_TIMER队列机制实现的,一种是timeSetEvent,还有一种是QueryPerformanceFrequency&QueryPerformanceCounter,当然还有一种是直接Sleep,

以上方式的精度排列,以我多年的经验看:

QueryPerformanceFrequency > timeSetEvent > SetTimer > Sleep

Sleep是最不准确的,timeSetEvent勉强精确到毫秒级别,但是不太准确,QueryPerformanceFrequency是最精确的,用来做硬件定时中断或其他高精度us级别的消息发送就选QueryPerformanceFrequency,用来做精确到1ms级别是必然选择,但光用QueryPerformanceFrequency又不行,网上很多都是用QueryPerformanceFrequency,但是cpu飙高,所以自然就需要Sleep或yields cpu来降低cpu的耗能,在参考了Windows实现高精度定时器的三种方法 - 灰信网(软件开发博客聚合)这篇文章,我加了Sleep把cpu消耗降了下来,当然也可以选择其他不太精确的毫秒级别的sleep函数,上代码:

//定义1ms和2s时钟间隔,以ms为单位
#define ONE_MILLI_SECOND    17//1000/17=58.8fps
#define ONE_US_SECOND    (ONE_MILLI_SECOND * 1000.0f)

void MSleep(long lTime)
{
    LARGE_INTEGER litmp;
    LONGLONG QPart1, QPart2;
    double dfMinus, dfFreq, dfTim, dfSpec;
    QueryPerformanceFrequency(&litmp);
    dfFreq = (double)litmp.QuadPart;
    QueryPerformanceCounter(&litmp);
    QPart1 = litmp.QuadPart;
    dfSpec = 0.000001 * lTime;

    do
    {
        QueryPerformanceCounter(&litmp);
        QPart2 = litmp.QuadPart;
        dfMinus = (double)(QPart2 - QPart1);
        dfTim = dfMinus / dfFreq;
    } while (dfTim < dfSpec);
}

void  BasicWidget::TimerMsgProc(LPVOID dwUser)
{
    double        dtime = 0.0f, dtime2 = 0.0f, value;
    int count;

    count = 0;
    QueryPerformanceFrequency(&g_xliPerfFreq);
    QueryPerformanceCounter(&g_xliPerfStart);
    while (!threadExit) {

        QueryPerformanceCounter(&g_xliPerfNow);
        dtime = ((double)(g_xliPerfNow.QuadPart - g_xliPerfStart.QuadPart) * 1000000.0f) / (double)g_xliPerfFreq.QuadPart;//微秒
        if (dtime < ONE_US_SECOND)//1秒=1000毫秒=1000000.0f微秒
        {
            value = (ONE_US_SECOND - dtime) / 1000.0f;//有多少毫秒
            if (value >= 1.0f)//大于等于1毫秒
            {
                Sleep(((int)value));//转int,小于2毫秒就是Sleep(0)

                QueryPerformanceCounter(&g_xliPerfNow);
                dtime2 = ((double)(g_xliPerfNow.QuadPart - g_xliPerfStart.QuadPart) * 1000000.0f) / (double)g_xliPerfFreq.QuadPart;
                if (dtime2 < ONE_US_SECOND)
                {
                    MSleep((ONE_US_SECOND - dtime2));
                }
            }
            else
            {
                MSleep(ONE_US_SECOND - dtime);
            }
        }

        QueryPerformanceCounter(&g_xliPerfNow);
        dtime = ((double)(g_xliPerfNow.QuadPart - g_xliPerfStart.QuadPart) * 1000000.0f) / (double)g_xliPerfFreq.QuadPart;


        printf("[%04d] %.9f us\n", ++count, dtime);

        

        memset(&g_xliPerfNow, 0x00, sizeof(LARGE_INTEGER));
        memset(&g_xliPerfStart, 0x00, sizeof(LARGE_INTEGER));

        //QueryPerformanceFrequency(&g_xliPerfFreq);
        QueryPerformanceCounter(&g_xliPerfStart);
    }
}
 

ONE_US_SECOND定义为17就可以达到肉眼无法分辨的帧率大概58fps,设为17然后进行子线程测试:

窗口里面渲染100个文本+100个矩形,cpu一直保持在7%左右,工程中使用D2D绘制,达到项目选型要求,使用QueryPerformanceCounter精确测得执行一次的实际刚好17ms

......

.......

[6483] 17000.200000000 us
[6484] 17000.500000000 us
[6485] 17000.300000000 us
[6486] 17000.300000000 us
[6487] 17000.200000000 us
[6488] 17000.700000000 us
[6489] 17001.000000000 us
[6490] 17017.900000000 us
[6491] 17000.400000000 us
[6492] 17000.600000000 us
[6493] 17000.500000000 us
[6494] 17000.800000000 us
[6495] 17000.200000000 us
[6496] 17000.100000000 us
[6497] 17000.700000000 us
[6498] 17000.900000000 us
[6499] 17001.100000000 us
[6500] 17000.300000000 us
[6501] 16999.800000000 us
[6502] 17000.300000000 us
[6503] 16999.900000000 us
[6504] 17000.000000000 us
[6505] 17002.300000000 us
[6506] 17001.200000000 us
[6507] 17000.600000000 us
[6508] 17056.000000000 us
[6509] 17000.700000000 us
[6510] 16999.800000000 us
[6511] 16999.800000000 us
[6512] 17000.000000000 us
[6513] 17000.400000000 us
[6514] 17000.500000000 us
[6515] 17001.600000000 us
[6516] 17029.400000000 us
[6517] 17048.400000000 us
[6518] 17001.000000000 us
[6519] 17000.700000000 us
[6520] 17000.600000000 us
[6521] 17002.100000000 us
[6522] 17000.200000000 us
[6523] 17000.100000000 us
[6524] 16999.900000000 us
[6525] 17000.600000000 us
[6526] 17000.100000000 us
[6527] 17000.600000000 us
[6528] 17000.200000000 us
[6529] 17000.900000000 us
[6530] 17053.800000000 us
[6531] 17000.400000000 us
[6532] 17001.100000000 us
[6533] 17085.600000000 us
[6534] 17163.000000000 us
[6535] 17010.100000000 us
[6536] 17000.200000000 us
[6537] 17000.100000000 us
[6538] 16999.900000000 us
[6539] 17000.800000000 us
[6540] 17001.300000000 us
[6541] 17206.600000000 us
[6542] 17000.100000000 us
[6543] 17000.500000000 us
[6544] 16999.900000000 us
[6545] 17000.500000000 us
[6546] 17000.200000000 us
[6547] 17000.200000000 us
[6548] 17000.400000000 us
[6549] 17000.700000000 us
[6550] 17000.700000000 us
[6551] 17000.600000000 us
[6552] 17000.400000000 us
[6553] 17092.000000000 us
[6554] 17000.700000000 us
[6555] 17000.200000000 us
[6556] 17000.700000000 us
[6557] 16999.900000000 us
[6558] 17000.200000000 us
[6559] 17001.000000000 us
[6560] 17018.000000000 us
[6561] 17000.700000000 us
[6562] 16999.800000000 us
[6563] 17000.700000000 us
[6564] 17000.100000000 us
[6565] 17000.100000000 us
[6566] 17000.100000000 us
[6567] 17000.000000000 us
[6568] 17011.800000000 us
[6569] 16999.800000000 us
[6570] 17000.100000000 us
[6571] 17000.400000000 us
[6572] 17000.300000000 us
[6573] 17000.100000000 us
[6574] 17000.600000000 us
[6575] 17000.600000000 us
[6576] 17000.300000000 us
[6577] 17000.300000000 us
[6578] 17000.700000000 us
[6579] 17000.400000000 us
[6580] 17000.700000000 us
[6581] 16999.900000000 us
[6582] 17000.400000000 us
[6583] 17000.500000000 us
[6584] 17000.900000000 us
[6585] 17000.800000000 us
[6586] 17001.400000000 us
[6587] 17000.600000000 us
[6588] 17074.300000000 us
[6589] 16999.900000000 us
[6590] 17000.000000000 us
[6591] 16999.900000000 us
[6592] 17000.700000000 us
[6593] 17000.600000000 us
[6594] 17000.700000000 us
[6595] 17000.100000000 us
[6596] 17000.600000000 us
[6597] 17000.900000000 us
[6598] 17000.200000000 us
[6599] 17000.300000000 us
[6600] 17008.800000000 us
[6601] 17000.500000000 us
[6602] 17000.700000000 us
[6603] 17000.600000000 us
[6604] 17000.400000000 us
[6605] 17000.900000000 us
[6606] 17000.500000000 us
[6607] 17000.700000000 us
[6608] 17000.300000000 us
[6609] 17000.900000000 us
[6610] 17007.800000000 us
[6611] 17000.100000000 us
[6612] 17001.000000000 us
[6613] 17000.200000000 us
[6614] 17000.000000000 us
[6615] 17002.700000000 us
[6616] 16999.900000000 us
[6617] 17000.700000000 us
[6618] 16999.900000000 us
[6619] 17000.600000000 us
[6620] 17001.300000000 us
[6621] 17000.900000000 us
[6622] 17000.200000000 us
[6623] 17000.700000000 us
[6624] 17000.800000000 us
[6625] 17000.700000000 us
[6626] 16999.800000000 us
[6627] 16999.900000000 us
[6628] 17000.000000000 us
[6629] 17000.000000000 us
[6630] 17000.400000000 us
[6631] 17000.100000000 us
[6632] 17000.000000000 us
[6633] 16999.900000000 us
[6634] 17000.900000000 us
[6635] 16999.900000000 us
[6636] 17948.100000000 us
[6637] 17000.200000000 us
[6638] 17000.300000000 us
[6639] 17000.700000000 us
[6640] 17000.900000000 us
[6641] 17000.000000000 us
[6642] 17001.200000000 us
[6643] 17001.000000000 us
[6644] 17000.600000000 us
[6645] 17000.200000000 us
[6646] 17000.900000000 us
[6647] 17000.200000000 us
[6648] 17000.400000000 us
[6649] 17000.400000000 us
[6650] 17000.400000000 us
[6651] 16999.900000000 us
[6652] 16999.900000000 us
[6653] 17000.200000000 us
[6654] 17000.700000000 us
[6655] 17000.800000000 us
[6656] 17000.400000000 us
[6657] 17000.900000000 us
[6658] 17002.900000000 us
[6659] 17000.300000000 us
[6660] 17000.200000000 us
[6661] 17000.700000000 us
[6662] 17000.400000000 us

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值