基于对象的消息队列的性能优化checklist

系列文章导航:《新的职业目标,以及C++性能优化


基于对象的消息队列的性能优化checklist



一般的,消息队列的项要么采用添加type字段表示项类型,消息处理逻辑根据不同的type进入不同的分支,要么会以OO的思维使用多态的方法进行消息处理。
前者典型的如MFC的消息循环,后者就比如是reSIProcate。


対消息的处理逻辑不在本博客的讨论范围内。但就消息队列而言,影响性能的因素主要有两点,第一点是队列的同步,第二点是消息对象的分配销毁。
关于队列同步的优化,在以并发编程为主题的书籍或文章中有深入的讲解。


关于消息对象的分配销毁的优化,可以使用如下的方法进行优化:
(1)使用内存池块存储消息对象。
(2)定义类专属的new/delete操作符。
(3)使用指定分配地址的new操作符。


笔者在自己的台式机上进行对比测试,机器配置:win10-64位/16G*1内存/三星SSD硬盘/i5-6500处理器。

对比的结果非常明显,在指定位置调用new分配内存,比从OS获取内存的性能要高出2~3个数量级。以下是测试代码:


#include <Windows.h>
#include <iostream>

using namespace std;

/*
测试不同new的耗时。
(1)从指定地址new
(2)每次new都从OS获取地址
*/

void test_new_consume_on_heap()
{
    /*
    在我的台式机上测试结果如下:
    1000*100 new[1B]-on-heap consume  9709 ticks,avg        310.688    ns per new+delete
    1000*100 new[1k]-on-heap consume  10802 ticks,avg       345.664    ns per new+delete
    1000*100 new[4k]-on-heap consume  20785 ticks,avg       665.12     ns per new+delete
    1000*100 new[32k]-on-heap consume 60765 ticks,avg      1944.48     ns per new+delete
    1000*1 new[1M]-on-heap consume    1847939 ticks,avg  591340        ns per new+delete
    1000*1 new[4M]-on-heap consume    8043361 ticks,avg 2573875.520000 ns per new+delete

    看得出,当数组较小时,new+delete的耗时很小,数组越大越耗时。
    */
    LARGE_INTEGER start,stop,freqency;
    QueryPerformanceFrequency(&freqency);
    double ns_per_tick=1000*1000*1000/freqency.QuadPart,avg=0;
    int counters = 1000*10;

    char *pc=NULL;
    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[1];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[1B]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[1024];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[1k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[4096];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[4k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[32768];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[32k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    counters = 1000*1;
    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[1048576];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*1 new[1M]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new char[4194304];
        //do-something
        delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*1 new[4M]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<std::fixed <<avg<<" ns per new+delete"<<endl;
}

char c1B[1];
char c1k[1024];
char c4k[1024*4];
char c32k[1024*32];
char c1M[1024*1024];
char c4M[1024*1024*4];
void test_new_consume_on_stack()
{
    /*
    在我的台式机上测试结果如下:
    1000*100 new[1B]-on-heap consume 466 ticks,avg  14.912    ns per new+delete
    1000*100 new[1k]-on-heap consume 382 ticks,avg  12.224    ns per new+delete
    1000*100 new[4k]-on-heap consume 692 ticks,avg  22.144    ns per new+delete
    1000*100 new[32k]-on-heap consume 388 ticks,avg 12.416    ns per new+delete
    1000*100 new[1M]-on-heap consume 4178 ticks,avg 13.3696   ns per new+delete
    1000*100 new[4M]-on-heap consume 6245 ticks,avg 19.984000 ns per new+delete

    看得出,数组大小对分配耗时的操作并不大。
    但是需要注意的是,在指定位置调用new的内存不能使用delete销毁!!!
    */
    LARGE_INTEGER start,stop,freqency;
    QueryPerformanceFrequency(&freqency);
    double ns_per_tick=1000*1000*1000/freqency.QuadPart,avg=0;
    int counters = 1000*10;

    char *pc=NULL;
    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c1B) char[1];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[1B]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c1k) char[1024];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[1k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c4k) char[4096];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[4k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c32k) char[32768];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[32k]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    counters = 1000*100;
    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c1M) char[1048576];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[1M]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<avg<<" ns per new+delete"<<endl;


    QueryPerformanceCounter(&start);
    for(int i=0;i<counters;++i)
    {
        pc = new(c4M) char[4194304];
        //do-something
        //delete []pc;
    }
    QueryPerformanceCounter(&stop);
    avg = (stop.QuadPart-start.QuadPart)*ns_per_tick/counters;
    cout<<"1000*100 new[4M]-on-heap consume "<<(stop.QuadPart-start.QuadPart)<<" ticks,avg "<<std::fixed <<avg<<" ns per new+delete"<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值