内存池项目求教?

2023-04-11 15:24:22 +08:00
 0littleboy

项目链接: https://github.com/cs-moushuai/MemoryPool

这是巨弱在简历上的一个项目,在面试的时候问到如何实现线程安全,回答是 C++11 新标准保证的

然后面试官说这样直接锁住 instance 了,性能太低,有没有老哥了解的

// Get the single memory pool instance
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>&
MemoryPool<T, BlockSize>::getInstance()
{
    static MemoryPool instance;
    return instance;
}

下面是简历里的介绍

C++ 实现高性能内存池

C++, 数据结构, 测试 个人项目

  • 内容:设计了一个链表形式的区块链及空闲元素链以实现高性能的内存池,并实现相应的空间配 置器,内部使用单例模式获取内存池且实现线程安全,使用 assert 来除错
  • 测试:使用链表实现的栈来测试,通过频繁的 push 及 pop 操作,计算得到 STL 中 allocator 需要 58.65 s ,而内存池实现的 Allocator 只需要 12.09 s 即可
2487 次点击
所在节点    C++
15 条回复
jones2000
2023-04-11 15:33:19 +08:00
给每个线程一个分配一个独立的线程池, 这个就不用锁了。
0littleboy
2023-04-11 15:38:58 +08:00
@jones2000 意思是给每个线程一个分配一个独立的*内存池*吗,可这就达不到内存池的效果了,内存池就应该所有线程共享一个实例,这也是为什么使用的单例模式
Yeen
2023-04-11 15:48:43 +08:00
@0littleboy 我觉得你对内存池和共享内存是不是还有误解。内存池最初的初衷是解决频繁 new delete 的语言开销,以及从系统堆分配内存的系统 API 开销带来的性能损失,所以预先分配内存。然后在应用代码中自己管理。
共享内存才是多线程 /进程公用的内存。
这两个没有关联。
duke807
2023-04-11 16:31:33 +08:00
你这一点性能提升看起来只是为了跑分,实际带来的风险远大于收益吧


我很多年前写有一个 ipc 项目,使用 PI-futex 保证线程安全:

https://github.com/dukelec/cdipc


另外我常用的裸机代码,也是用链表管理内存:

这个文件开头,把数组所占内存转成列表进行管理:
https://github.com/dukelec/stepper_motor_controller/blob/master/mdrv_fw/usr/app_main.c

这个文件,定义了多线程获取内存链表的函数:
https://github.com/dukelec/cdnet/blob/master/dispatch/cdnet_dispatch.h

这个文件,最终使用 local_irq_save 加锁:
https://github.com/dukelec/cdnet/blob/master/utils/cd_list.h
fournoas
2023-04-11 16:41:31 +08:00
@0littleboy 谁跟你说内存池必须所有线程共享的,牺牲空间换取性能才是常规操作
Nazz
2023-04-11 16:42:17 +08:00
用 stack 性能更好, 线程安全加锁就是了
artnowben
2023-04-11 16:45:25 +08:00
尽量每个线程独立,另外可以参考一下 DPDK 的内存池。
hankai17
2023-04-11 16:50:11 +08:00
全局的 instance 必须加锁或者用原子操作
内存池还得做 "local 化" 就是每个线程维护各自线程池
内存池还得做 回收操作
yingxiangyu
2023-04-11 16:50:35 +08:00
thread local , 基本降低并发竞争都离不开 thread local
jones2000
2023-04-11 17:45:14 +08:00
@0littleboy 共享就需要上锁, 一个牺牲内存提供性能, 一个是节省内存牺牲性能。 具体看项目需求了。
Yggdroot
2023-04-11 18:03:30 +08:00
面试官说的不对。
XSDo
2023-04-11 18:14:34 +08:00
又要共享又要不加锁 既要又要,想提升性能就减少竞争,比如只有一个池所有线程去争,改成每个线程自己用自己的池,内存不足,就一组线程用一个池这样也是减少竞争 提升性能。
changnet
2023-04-11 19:18:04 +08:00
我都搞不清楚到底说的是哪个线程安全

C++ 11 是有保证 local static 变量的初始化是安全的,因此 getInstance()这个函数是线程安全的

但是整个库都没有用到锁,因此在操作内存的时候,这个库不是线程安全的。

“面试官说这样直接锁住 instance ” 这里我没搞懂哪里会锁住 instance 。
SenseHu
2023-04-12 08:56:11 +08:00
读一下 tcmalloc 或者 jemalloc 吧
newmlp
2023-04-12 14:15:35 +08:00
参考下 mimalloc 吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/931611

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX