项目链接: 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 即可
1
jones2000 2023-04-11 15:33:19 +08:00
给每个线程一个分配一个独立的线程池, 这个就不用锁了。
|
2
0littleboy OP @jones2000 意思是给每个线程一个分配一个独立的*内存池*吗,可这就达不到内存池的效果了,内存池就应该所有线程共享一个实例,这也是为什么使用的单例模式
|
3
Yeen 2023-04-11 15:48:43 +08:00
@0littleboy 我觉得你对内存池和共享内存是不是还有误解。内存池最初的初衷是解决频繁 new delete 的语言开销,以及从系统堆分配内存的系统 API 开销带来的性能损失,所以预先分配内存。然后在应用代码中自己管理。
共享内存才是多线程 /进程公用的内存。 这两个没有关联。 |
4
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 |
5
fournoas 2023-04-11 16:41:31 +08:00
@0littleboy 谁跟你说内存池必须所有线程共享的,牺牲空间换取性能才是常规操作
|
6
Nazz 2023-04-11 16:42:17 +08:00
用 stack 性能更好, 线程安全加锁就是了
|
7
artnowben 2023-04-11 16:45:25 +08:00
尽量每个线程独立,另外可以参考一下 DPDK 的内存池。
|
8
hankai17 2023-04-11 16:50:11 +08:00
全局的 instance 必须加锁或者用原子操作
内存池还得做 "local 化" 就是每个线程维护各自线程池 内存池还得做 回收操作 |
9
yingxiangyu 2023-04-11 16:50:35 +08:00
thread local , 基本降低并发竞争都离不开 thread local
|
10
jones2000 2023-04-11 17:45:14 +08:00
@0littleboy 共享就需要上锁, 一个牺牲内存提供性能, 一个是节省内存牺牲性能。 具体看项目需求了。
|
11
Yggdroot 2023-04-11 18:03:30 +08:00
面试官说的不对。
|
12
XSDo 2023-04-11 18:14:34 +08:00
又要共享又要不加锁 既要又要,想提升性能就减少竞争,比如只有一个池所有线程去争,改成每个线程自己用自己的池,内存不足,就一组线程用一个池这样也是减少竞争 提升性能。
|
13
changnet 2023-04-11 19:18:04 +08:00
我都搞不清楚到底说的是哪个线程安全
C++ 11 是有保证 local static 变量的初始化是安全的,因此 getInstance()这个函数是线程安全的 但是整个库都没有用到锁,因此在操作内存的时候,这个库不是线程安全的。 “面试官说这样直接锁住 instance ” 这里我没搞懂哪里会锁住 instance 。 |
14
SenseHu 2023-04-12 08:56:11 +08:00
读一下 tcmalloc 或者 jemalloc 吧
|
15
newmlp 2023-04-12 14:15:35 +08:00
参考下 mimalloc 吧
|