Skip to content

Commit 6245d0b

Browse files
authored
Merge pull request #8 from Icingworld/dev
Code review
2 parents 8f96efe + aadb160 commit 6245d0b

25 files changed

+2198
-417
lines changed

README.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
该项目是`WW`系列中,作为学习用途的内存池库
44

5-
## 特点
5+
## 一、特点
66

77
+ 采用`tcmalloc`的三层缓存架构,提高内存的分配效率
88

99
+ C++11风格,代码易读性强
1010

11-
## 结构
11+
## 二、结构
1212

1313
采用三层缓存的结构,其中
1414

@@ -18,31 +18,32 @@
1818

1919
+ 线程缓存`ThreadCache`: 管理少量的小块内存,负责从中心缓存中获取小块内存,并提供给应用程序使用
2020

21-
### 页缓存`PageCahce`
21+
### 1. 页缓存`PageCahce`
2222

2323
页缓存以页为单位管理内存,在中心缓存申请内存时,页缓存挑选合适的页段,然后将其切片成小块页段提供给中心缓存
2424

2525
![page_cache](doc/img/page_cache.png)
2626

27-
### 中心缓存`CentralCache`
27+
### 2. 中心缓存`CentralCache`
2828

2929
中心缓存从页缓存中获取合适大小的页段,然后根据需要的内存块大小,切割为一定数量的内存块,挂载到一个内存块链表上,供线程缓存使用
3030

3131
![central_cache](doc/img/central_cache.png)
3232

33-
### 线程缓存`ThreadCache`
33+
### 3. 线程缓存`ThreadCache`
3434

3535
线程缓存从中心缓存中批量获取内存块,供应用程序申请使用
3636

3737
![thread_cache](doc/img/thread_cache.png)
3838

39-
## 使用
39+
## 三、使用
4040

41-
### 要求
41+
### 1. 要求
4242

43-
+ 环境:`Linux x86_64`
43+
+ 操作系统:64位`Linux``Windows`
44+
+ C++:`C++11`或更高版本
4445

45-
### 直接使用
46+
### 2. 直接使用
4647

4748
直接操作线程缓存实例,示例见[threadcache_test.cpp](test/src/threadcache_test.cpp)
4849

@@ -64,7 +65,7 @@ int main()
6465
}
6566
```
6667

67-
### 封装使用
68+
### 3. 封装使用
6869

6970
将内存池封装为分配器等,示例见[memory_test.cpp](test/src/memory_test.cpp)
7071

@@ -89,3 +90,25 @@ void deallocate(pointer ptr, size_type n)
8990
thread_cache.deallocate(ptr, n * sizeof(T));
9091
}
9192
```
93+
94+
## 四、性能
95+
96+
基准测试位于[memory_benchmark.cpp](benchmark/src/memory_benchmark.cpp)
97+
98+
运行环境:
99+
100+
+ 操作系统:`Ubuntu 22.04 LTS`
101+
+ CPU:`12th Gen Intel(R) Core(TM) i7-12700`
102+
+ 核心/线程:4 核心 / 4 线程
103+
+ 内存:8 GB
104+
+ 虚拟化:`VMware`
105+
106+
### 1. 运行结果参考
107+
108+
![memory_benchmark](doc/img/memory_benchmark.png)
109+
110+
### 2. `perf`火焰图参考
111+
112+
火焰图来自基准测试中的[analyze_benchmark.cpp](benchmark/src/analyze_benchmark.cpp)
113+
114+
![flamegraph](doc/img/flamegraph.svg)

benchmark/CMakeLists.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,17 @@ target_include_directories(memory_benchmark PRIVATE
99

1010
target_link_libraries(memory_benchmark PRIVATE
1111
WW::memory
12-
)
12+
)
13+
14+
# analyze_benchmark.cpp
15+
add_executable(analyze_benchmark
16+
src/analyze_benchmark.cpp
17+
)
18+
19+
target_include_directories(analyze_benchmark PRIVATE
20+
${CMAKE_CURRENT_SOURCE_DIR}/include
21+
)
22+
23+
target_link_libraries(analyze_benchmark PRIVATE
24+
WW::memory
25+
)

benchmark/include/allocator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class allocator
3131

3232
public:
3333
allocator()
34-
: thread_cache(WW::ThreadCache::getThreadCache())
34+
: thread_cache(WW::ThreadCache::get_thread_cache())
3535
{
3636
}
3737

benchmark/src/analyze_benchmark.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <vector>
2+
#include <thread>
3+
4+
#include <allocator.h>
5+
6+
using namespace WW;
7+
8+
constexpr size_type THREAD = 2; // 线程数
9+
constexpr size_type ROUND = 1000; // 轮数
10+
constexpr size_type TIMES = 1000; // 单次测试操作次数
11+
12+
/**
13+
* @brief 测试结构
14+
*/
15+
template <size_type Size>
16+
class TestCase
17+
{
18+
public:
19+
char padding[Size];
20+
};
21+
22+
int main()
23+
{
24+
std::vector<std::thread> pool_threads;
25+
pool_threads.reserve(THREAD);
26+
27+
// 512bytes
28+
pool_threads.emplace_back([]() {
29+
allocator<TestCase<512>> alloc;
30+
31+
for (size_type j = 0; j < ROUND; ++j) {
32+
std::vector<TestCase<512> *> ptrs;
33+
ptrs.reserve(TIMES);
34+
35+
for (size_type k = 0; k < TIMES; ++k) {
36+
TestCase<512> * ptr = alloc.allocate(1);
37+
ptrs.emplace_back(ptr);
38+
}
39+
40+
for (size_type k = 0; k < TIMES; ++k) {
41+
alloc.deallocate(ptrs[k], 1);
42+
}
43+
}
44+
});
45+
46+
// 1024bytes
47+
pool_threads.emplace_back([]() {
48+
allocator<TestCase<1024>> alloc;
49+
50+
for (size_type j = 0; j < ROUND; ++j) {
51+
std::vector<TestCase<1024> *> ptrs;
52+
ptrs.reserve(TIMES);
53+
54+
for (size_type k = 0; k < TIMES; ++k) {
55+
TestCase<1024> * ptr = alloc.allocate(1);
56+
ptrs.emplace_back(ptr);
57+
}
58+
59+
for (size_type k = 0; k < TIMES; ++k) {
60+
alloc.deallocate(ptrs[k], 1);
61+
}
62+
}
63+
});
64+
65+
for (std::thread & thread : pool_threads) {
66+
thread.join();
67+
}
68+
}

0 commit comments

Comments
 (0)