GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 58.7% 88 / 0 / 150
Functions: 50.0% 4 / 0 / 8
Branches: 29.3% 78 / 0 / 266

memory/allocators/persist_loop_slab_allocator.cc
Line Branch Exec Source
1 #include "memory/allocators/persist_loop_slab_allocator.h"
2
3 #include <algorithm>
4 #include <iostream>
5
6 DEFINE_double(shm_malloc_healthy_rate, 0.95, "shm malloc healthy rate");
7
8 DECLARE_double(shm_malloc_healthy_rate);
9
10 namespace base {
11 282 PersistLoopShmMalloc::PersistLoopShmMalloc(
12
2/4
✓ Branch 5 taken 282 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 282 times.
✗ Branch 9 not taken.
282 const std::string& filename, int64 memory_size, std::string medium) {
13 282 block_num_ = 0;
14 282 while (((block_num_ + 64) >> 3) + (block_num_ + 64) * sizeof(uint64) <=
15
2/2
✓ Branch 0 taken 46770950 times.
✓ Branch 1 taken 282 times.
46771232 memory_size) {
16 46770950 block_num_ += 64;
17 }
18 282 healthy_used_ = block_num_ * FLAGS_shm_malloc_healthy_rate;
19
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 bool file_exists = base::file_util::PathExists(filename);
20
2/4
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 282 times.
✗ Branch 5 not taken.
564 shm_file_ = ShmFile::New(ShmFile::ConfigForMedium(
21 282 medium, filename, memory_size));
22
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 282 times.
282 if (!shm_file_) {
23 file_exists = false;
24 CHECK(base::file_util::Delete(filename, false));
25 shm_file_ = ShmFile::New(ShmFile::ConfigForMedium(
26 medium, filename, memory_size));
27 CHECK(shm_file_) << filename << " " << memory_size;
28 }
29
30 282 used_bits_ = reinterpret_cast<uint64*>(shm_file_->Data());
31 282 data_ = shm_file_->Data() + (block_num_ >> 3);
32 282 load_success_ = file_exists;
33
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 Initialize();
34
1/2
✓ Branch 0 taken 282 times.
✗ Branch 1 not taken.
282 if (!file_exists) {
35
3/6
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 282 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 282 times.
✗ Branch 8 not taken.
282 LOG(INFO) << "PersistLoopShmMalloc: first initialization.";
36 } else {
37 LOG(INFO) << "PersistLoopShmMalloc: Recovery from shutdown.";
38 }
39 282 }
40
41 void PersistLoopShmMalloc::AddMallocs4Recovery(int64_t shm_offset) {
42 // NOTE(xieminhui) use atomic instr to reduce conflict between threads.
43 // But the code below has redundancy with the function UseBlock
44 __sync_fetch_and_add(&total_malloc_, 1); // NOLINT
45 int64_t offset = shm_offset;
46 CHECK_GE(offset, 0);
47 CHECK_LT(offset, block_num_ * 8L);
48 int memory_size = GetMallocSize(offset);
49 int memory_block_num = BlockNum(memory_size);
50
51 __sync_fetch_and_add(&total_used_, memory_block_num + 1); // NOLINT
52 int64_t sizeBlockIdx = BlockIndex(offset) - 1;
53
54 for (int i = 1; i <= memory_block_num; i++) {
55 int64 index = sizeBlockIdx + i;
56 // Use Block [index]
57 uint64 temp;
58 do {
59 temp = used_bits_[index >> 6];
60 } while (!__sync_bool_compare_and_swap(
61 &used_bits_[index >> 6], // NOLINT
62 temp,
63 temp | (1ul << (index & 63))));
64 }
65 }
66
67 52148 bool PersistLoopShmMalloc::UnusedMemoryValid(int64 block_index) const {
68 52148 int64 memory_block_num = BlockNum(Block()[block_index]);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52148 times.
52148 if (memory_block_num < 0) {
70 LOG(ERROR) << "memory_block_num < 0";
71 return false;
72 }
73 52148 block_index++;
74
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52148 times.
52148 if (block_index + memory_block_num > block_num_) {
75 LOG(ERROR) << "block_index + memory_block_num > block_num_";
76 return false;
77 }
78
2/2
✓ Branch 0 taken 833872 times.
✓ Branch 1 taken 52148 times.
886020 for (int i = 0; i < memory_block_num; ++i) {
79
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 833872 times.
833872 if (!Used(block_index + i)) {
80 // LOG(ERROR) << "!Used(block_index + i)\t"
81 // << "block_index=" << block_index << "; i=" << i;
82 return false;
83 }
84 }
85 52148 return true;
86 }
87
88 void PersistLoopShmMalloc::GetMallocsAppend(
89 std::vector<char*>* mallocs_data) const {
90 for (int64 i = 0; i < block_num_ - 1; ++i) {
91 if (!Used(i) && Used(i + 1)) {
92 CHECK_GT(Block()[i], 0) << "block id = " << i;
93 mallocs_data->push_back(data_ + ((i + 1) << 3));
94 }
95 }
96 }
97
98 void PersistLoopShmMalloc::GetMallocsAppend(
99 std::vector<int64>* mallocs_offset) const {
100 for (int64 i = 0; i < block_num_ - 1; ++i) {
101 if (!Used(i) && Used(i + 1)) {
102 CHECK_GT(Block()[i], 0) << "block id = " << i;
103 mallocs_offset->push_back((i + 1) << 3);
104 }
105 }
106 }
107
108 bool PersistLoopShmMalloc::MemoryValid() const {
109 int64 block_index = 0;
110 while (block_index < block_num_) {
111 if (Used(block_index))
112 return false;
113 if (!UnusedMemoryValid(block_index))
114 return false;
115 block_index += 1 + BlockNum(Block()[block_index]);
116 }
117 return block_index == block_num_;
118 }
119
120 111882 char* PersistLoopShmMalloc::New(int memory_size) {
121
2/8
✓ Branch 3 taken 111882 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 111882 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
111882 CHECK_GE(memory_size, 0);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111882 times.
111882 if (memory_size == 0) {
123 return data_ + sizeof(uint64) * block_num_;
124 }
125
1/2
✓ Branch 1 taken 111882 times.
✗ Branch 2 not taken.
111882 base::AutoLock lock(lock_);
126 111882 int memory_block_num = BlockNum(memory_size);
127
1/2
✓ Branch 1 taken 111882 times.
✗ Branch 2 not taken.
111882 auto fast_malloc_list = fast_malloc_lists_.Get(memory_block_num);
128
3/4
✓ Branch 0 taken 54644 times.
✓ Branch 1 taken 57238 times.
✓ Branch 2 taken 54644 times.
✗ Branch 3 not taken.
111882 if (fast_malloc_list && enable_fast_malloc_) {
129 // 先尝试从刚回收的内存块中分配
130
2/2
✓ Branch 1 taken 49624 times.
✓ Branch 2 taken 5020 times.
54644 while (fast_malloc_list->size()) {
131 49624 int64 malloc_block = fast_malloc_list->front();
132 49624 fast_malloc_list->pop_front();
133 49624 bool malloc_success = true;
134
2/2
✓ Branch 0 taken 843608 times.
✓ Branch 1 taken 49624 times.
893232 for (int i = 0; i < memory_block_num + 1; ++i) {
135 // if (Used(malloc_block + i) && !Used(malloc_block + i + 1)) {
136
3/6
✓ Branch 1 taken 843608 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 843608 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 843608 times.
843608 if (!Used(malloc_block + i) && Used(malloc_block + i + 1)) {
137 malloc_success = false;
138 break;
139 }
140 }
141
1/2
✓ Branch 0 taken 49624 times.
✗ Branch 1 not taken.
49624 if (malloc_success) {
142 49624 Block()[malloc_block] = memory_size;
143
2/2
✓ Branch 0 taken 793984 times.
✓ Branch 1 taken 49624 times.
843608 for (int i = 1; i < memory_block_num + 1; ++i)
144 793984 UseBlock(malloc_block + i);
145 49624 total_used_ += memory_block_num + 1;
146 49624 total_malloc_++;
147
1/2
✓ Branch 1 taken 49624 times.
✗ Branch 2 not taken.
49624 total_fast_malloc_.Inc(1);
148
1/2
✓ Branch 2 taken 49624 times.
✗ Branch 3 not taken.
49624 clflushopt_range(&Block()[malloc_block], sizeof(uint64));
149 49624 return data_ + sizeof(uint64) * (malloc_block + 1);
150 }
151 }
152 }
153 62258 int64 offset = 0;
154 62258 int64 malloc_block = last_malloc_block_;
155
1/2
✓ Branch 0 taken 62258 times.
✗ Branch 1 not taken.
62258 while (offset < block_num_) {
156
1/2
✓ Branch 0 taken 62258 times.
✗ Branch 1 not taken.
62258 if (malloc_block + memory_block_num + 1 <= block_num_) {
157
2/2
✓ Branch 0 taken 1056922 times.
✓ Branch 1 taken 62258 times.
1119180 for (int i = 0; i < memory_block_num + 1; ++i) {
158
3/6
✓ Branch 1 taken 1056922 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1056922 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1056922 times.
1056922 if (Used(malloc_block + i) || Used(malloc_block + i + 1)) {
159 malloc_block += i;
160 offset += i;
161 break;
162 }
163 }
164 // NOTE(xieminhui) remove Block()[malloc_block] == 0, because we only use
165 // bitmap to check if a block has been used.
166
3/6
✓ Branch 1 taken 62258 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 62258 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 62258 times.
✗ Branch 7 not taken.
62258 if (!Used(malloc_block) && !Used(malloc_block + 1)) {
167 62258 Block()[malloc_block] = memory_size;
168
2/2
✓ Branch 0 taken 994664 times.
✓ Branch 1 taken 62258 times.
1056922 for (int i = 1; i < memory_block_num + 1; ++i) {
169
2/12
✗ Branch 1 not taken.
✓ Branch 2 taken 994664 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 994664 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
994664 CHECK(!Used(malloc_block + i));
170 994664 UseBlock(malloc_block + i);
171 }
172 62258 last_malloc_block_ = (malloc_block + memory_block_num + 1) % block_num_;
173 62258 total_used_ += memory_block_num + 1;
174 62258 total_malloc_++;
175
1/2
✓ Branch 1 taken 62258 times.
✗ Branch 2 not taken.
62258 total_loop_malloc_.Inc(1);
176 // persist the value first
177 // clflushopt_range(sync_data - sizeof(uint64), size + sizeof(uint64));
178 // warning(xieminhui) Now we only clflush the !!!!!value_len!!!!!
179
1/2
✓ Branch 2 taken 62258 times.
✗ Branch 3 not taken.
62258 clflushopt_range(&Block()[malloc_block], sizeof(uint64));
180 62258 return data_ + sizeof(uint64) * (malloc_block + 1);
181 }
182 malloc_block++;
183 offset++;
184 } else {
185 offset += block_num_ - malloc_block;
186 malloc_block = 0;
187 }
188 }
189 // LOG(INFO) << "persist memory has no mem!";
190 return NULL;
191 111882 }
192
193 52148 bool PersistLoopShmMalloc::Free(void* memory_data) {
194 52148 auto data = reinterpret_cast<const char*>(memory_data);
195
1/2
✓ Branch 1 taken 52148 times.
✗ Branch 2 not taken.
52148 int64 offset = GetMallocOffset(data);
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52148 times.
52148 if (offset < 0)
197 return false;
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52148 times.
52148 if (offset == sizeof(uint64) * block_num_)
199 return true;
200
1/2
✓ Branch 1 taken 52148 times.
✗ Branch 2 not taken.
52148 base::AutoLock lock(lock_);
201 52148 int64 block_index = BlockIndex(offset) - 1;
202
4/8
✓ Branch 1 taken 52148 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 52148 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 52148 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 52148 times.
✗ Branch 9 not taken.
52148 if (!Used(block_index) && UnusedMemoryValid(block_index)) {
203 52148 int memory_block_num = BlockNum(Block()[block_index]);
204
1/2
✓ Branch 0 taken 52148 times.
✗ Branch 1 not taken.
52148 if (enable_fast_malloc_) {
205
1/2
✓ Branch 1 taken 52148 times.
✗ Branch 2 not taken.
52148 auto fast_malloc_list = fast_malloc_lists_.Get(memory_block_num);
206
5/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 52088 times.
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 60 times.
✓ Branch 6 taken 52088 times.
52148 if (!fast_malloc_list && fast_malloc_lists_.size() < max_fast_list_type) {
207
2/4
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
60 fast_malloc_list = new std::deque<int64>();
208
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 fast_malloc_lists_.Insert(memory_block_num, fast_malloc_list);
209 }
210
3/6
✓ Branch 0 taken 52148 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 52148 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 52148 times.
✗ Branch 6 not taken.
52148 if (fast_malloc_list && fast_malloc_list->size() < max_fast_list_num) {
211
1/2
✓ Branch 1 taken 52148 times.
✗ Branch 2 not taken.
52148 fast_malloc_list->push_back(block_index);
212 }
213 }
214
2/2
✓ Branch 0 taken 886020 times.
✓ Branch 1 taken 52148 times.
938168 for (int i = 0; i < memory_block_num + 1; ++i) {
215 886020 FreeBlock(block_index + i);
216 }
217 52148 total_used_ -= memory_block_num + 1;
218 52148 total_malloc_--;
219 52148 return true;
220 }
221 // NOTE(xieminhui): this block already be freed by other thread
222
223 // LOG(ERROR) << "block_index= " << block_index
224 // << ", Used(block_index)= " << Used(block_index)
225 // << ", UnusedMemoryValid(block_index)= "
226 // << UnusedMemoryValid(block_index);
227 return false;
228 52148 }
229
230 } // namespace base
231