• github上star较多的三个c++ 内存池memory pool分析


    前言

    笔者在写libuv的时候遇到太多uv_type_t和buffer需要维护了.
    如果不通过内存池维护,一个是new delete效率非常低,另一个是这种callback和作用域所有权互相耦合的场景,即便是很好的维护了new delete,也会使得libuv运行的环境变得非常混乱.
    所以笔者决定去github上考察一下c++内存池,目前已知的几个如下:

    cacay/MemoryPool

    star最多的,最简洁的,可以很方便的嵌入到程序里,只包含一个.h和一个.tcc文件,完全可以自己把他们揉在一起.
    跨平台
    采用MIT协议.
    不再维护
    非线程安全
    可以构造参数传递
    创建用时大概是new的50%,delete就要节约更多啦
    包含c++98和c++11两个版本,和c++版本强耦合的,都包含了一些在后面被decrepit的写法所以版本不一致时可能需要自己改一点点.
    c++11的版本中支持了std::forword等,支持使用对象的构造方法,支持绕过构造方法(malloc形式).
    支持与std::allocate语法兼容,比如可以直接这样使用:

    std::vector< int, MemoryPool< int > > v;
    
    • 1

    默认池大小为4096可以在源码里调整.通过成员函数申请失败时由返回值表征.
    通过std::allocate语法兼容申请时,在超过可用空间后只会直接报错.
    不要试图很紧巴的使用这个内存池,且不要试图通过blockSize估计可以放置的元素数量,因为它代码里实际的maxSize在计算时如果blockSize较大是会有一些误差的.

    推荐场景

    小项目且内存比较充裕,直接给个很大的BlockSize怎么用都没事.如果你想这里不出问题,BlockSize需要大于这个池子可能容纳的对象的所有字节数的上界.

    lenonk/memorypool

    线程安全
    无锁
    cacay/MemoryPool接口基本一致,接口设计还是不错的.
    这个作者本来想把上面那个拿来开发一个线程安全的版本,但是他发现上面那个在改线程安全时各种奇怪错误太多了.上面那个写的确实不美.
    然后他基本推到从写了一个线程安全的.效率比起来当然低很多.

    DevShiftTeam/AppShift-MemoryPool

    面向数据 跨平台 写作方法也比较现代,也很精巧,只需要吧.h和.cpp复制进去就行,还有自己的命名空间 个人最推荐的库.
    非线程安全
    详细的文档和benchmark
    可以构造参数传递
    创建用时大概是new的3/4,delete就要节约更多啦
    样例丰富
    性能在win下比较好,因为win下new和delete成本比较高,linux下性能一般.

    是APPShift库的一部分,另外,在我写完这篇的时候点进官网看了一下,进去直接是希伯来语给我整傻了,希伯来语看上去真奇怪啊.

    推荐场景

    项目比较大比较复杂的时候,这个库的接口设计个人觉得不如最上面那个,但是也没有一些奇怪的写法.不会导致突然的error.同时维护比较积极,后面还会添加无锁的版本.

    测试代码

    
    #include "MemoryPool.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    class A
    {
    public:
        // A()
        // {
        //     std::random_device rd;
        //     a = rd();
        // }
        // A(){};
        // A( int a, int b, int c ) {}
    
        int a;
        std::string b;
    };
    constexpr int REPETTIMES = 10000000;
    int main( int argc, char** argv )
    {
        decltype( clock() ) timeBegin;
        decltype( clock() ) timeEnd;
        {
            timeBegin = clock();
            std::vector< A > as;
            for ( int i = 0; i < REPETTIMES; ++i ) {
                as.emplace_back( *new A );
            }
    
            timeEnd = clock();
            std::cout << "use emplace_back&&new cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        {
            timeBegin = clock();
            std::vector< A > as;
            for ( int i = 0; i < REPETTIMES; ++i ) {
                A temp;
                as.emplace_back( temp );
            }
    
            timeEnd = clock();
            std::cout << "use emplace_back&&stack cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        {
            timeBegin = clock();
            std::vector< A > as;
            for ( int i = 0; i < REPETTIMES; ++i ) {
                as.push_back( *new A );
            }
    
            timeEnd = clock();
            std::cout << "use push_back&&new cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        {
            timeBegin = clock();
            std::vector< A > as;
            for ( int i = 0; i < REPETTIMES; ++i ) {
                A temp;
                as.push_back( temp );
            }
    
            timeEnd = clock();
            std::cout << "use push_back&&stack cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
    
        {
            timeBegin = clock();
            for ( int i = 0; i < REPETTIMES; ++i ) {
                auto a = new A;
            }
    
            timeEnd = clock();
            std::cout << "use new cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        {
            timeBegin = clock();
            auto mp = new MemoryPool< A, REPETTIMES + 1000 >;
            for ( int i = 0; i < REPETTIMES; ++i ) {
                auto a = mp->newElement();
            }
            timeEnd = clock();
            std::cout << "use app cacay memory pool cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        //请添加.cpp作为头文件
        // {
        //     timeBegin = clock();
        //     auto mp = new AppShift::Memory::MemoryPool( ( REPETTIMES + 100 ) * sizeof( A ) );
        //     for ( int i = 0; i < REPETTIMES; ++i ) {
        //         auto a = new ( mp ) A;
        //     }
        //     timeEnd = clock();
        //     std::cout << "use app shift memory pool cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        // }
        {
            timeBegin = clock();
            for ( int i = 0; i < REPETTIMES; ++i ) {
                A temp;
            }
            timeEnd = clock();
            std::cout << "use stack cost=" << ( timeEnd - timeBegin ) / ( CLOCKS_PER_SEC / 1000 ) << std::endl;
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
  • 相关阅读:
    所见即所得的动画效果:Animate.css
    库克“一语成谶”:又有 30 万台安卓设备被“感染”了
    solidity 合约转java
    Linearization
    企业级优化
    多御安全浏览器安卓版迎来重大更新:新增分享二维码功能
    实验室超声波清洗机应具备哪些特点
    SolidKits.BOMs高级BOM及属性批量导入工具个人版上线了
    电脑重装系统word从第二页开始有页眉页脚如何设置
    OrangePi Kunpeng Pro 开发板测评 | AI 边缘计算 & 大模型部署
  • 原文地址:https://blog.csdn.net/weixin_43950087/article/details/126320446