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;

默认池大小为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 <cstdint>
#include <ctime>
#include <iostream>
#include <random>
#include <string>
#include <vector>
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
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 1. vue:是一个用于构建用户界面的框架。它的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。它是最受欢迎的 JavaScript 框架之一,目前在 GitHub 上拥有超过 180k 的星标。 2. free-programming-books:这是一个收集免费编程书籍的项目。它包含了超过 500 本书,涵盖了各种编程语言和技术。该项目在 GitHub 上拥有超过 140k 的星标。 3. awesome:这是一个系列的项目,用于收集各种技术领域中优秀的资源。例如,awesome-python 收集了有关 Python 的优秀项目、库和文章,awesome-machine-learning 收集了有关机器学习的优秀资源等等。awesome 项目在 GitHub 上拥有超过 130k 的星标。 ### 回答2: Github上star最多的三个项目分别是: 1. freeCodeCamp:freeCodeCamp是一个完全免费的学习编码和成为全栈开发者的开源社区。它提供了大量的在线教育资源,包括学习编程语言、前端开发、后端开发等多个领域。这个项目的star数量超过了31万,说明它受到了广泛的关注和认可。 2. VS Code:VS Code(Visual Studio Code)是由微软开发的一款免费开源的代码编辑器。它具有丰富的功能和扩展性,支持多种编程语言,并且有活跃的开发者社区。这个项目的star数量超过了12万,它成为了广大开发者们的首选编辑器之一。 3. Flutter:Flutter是由Google开发的跨平台移动应用开发框架。它使用Dart语言编写,可以同时开发iOS和Android应用,并且有许多内置的UI组件和功能库,使开发者能够快速构建漂亮流畅的应用。Flutter的star数量超过了14万,显示了其在移动应用开发领域受到了广泛认可和采用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值