Skip to content

Commit 4078d4b

Browse files
ChrisLaspiasChris Laspias
and
Chris Laspias
authored
Spring 2025: P2 Updated Contention Test (#804)
* Spring 2025: P2 Updated Contention test * fix lint error * Spring 2025: Fix the clang-tidy in contention --------- Co-authored-by: Chris Laspias <claspias@andrew.cmu.edu>
1 parent 4539192 commit 4078d4b

File tree

1 file changed

+45
-94
lines changed

1 file changed

+45
-94
lines changed

test/storage/b_plus_tree_contention_test.cpp

+45-94
Original file line numberDiff line numberDiff line change
@@ -29,150 +29,101 @@
2929

3030
namespace bustub {
3131

32-
bool BPlusTreeLockBenchmarkCall(size_t num_threads, int leaf_node_size, bool with_global_mutex) {
33-
bool success = true;
34-
std::vector<int64_t> insert_keys;
35-
32+
size_t BPlusTreeLockBenchmarkCall(size_t num_threads, bool with_global_mutex) {
3633
// create KeyComparator and index schema
3734
auto key_schema = ParseCreateStatement("a bigint");
3835
GenericComparator<8> comparator(key_schema.get());
39-
auto *disk_manager = new DiskManagerMemory(256 << 10); // 1GB
40-
auto *bpm = new BufferPoolManager(64, disk_manager);
36+
37+
// create lightweight BPM
38+
const size_t bpm_size = 256 << 10; // 1GB
39+
DiskManagerMemory disk_manager(bpm_size);
40+
BufferPoolManager bpm(bpm_size, &disk_manager);
4141

4242
// allocate header_page
43-
page_id_t page_id = bpm->NewPage();
43+
page_id_t page_id = bpm.NewPage();
4444

4545
// create b+ tree
46-
BPlusTree<GenericKey<8>, RID, GenericComparator<8>> tree("foo_pk", page_id, bpm, comparator, leaf_node_size, 10);
46+
const int node_size = 20;
47+
BPlusTree<GenericKey<8>, RID, GenericComparator<8>> tree("foo_pk", page_id, &bpm, comparator, node_size, node_size);
4748

4849
std::vector<std::thread> threads;
4950

50-
const int keys_per_thread = 20000 / num_threads;
51-
const int keys_stride = 100000;
51+
const int keys_per_stride = 160000 / num_threads;
52+
const int key_stride = 6400000;
5253
std::mutex mtx;
5354

54-
for (size_t i = 0; i < num_threads; i++) {
55-
auto func = [&tree, &mtx, i, keys_per_thread, with_global_mutex]() {
56-
GenericKey<8> index_key;
57-
RID rid;
58-
const auto end_key = keys_stride * i + keys_per_thread;
59-
for (auto key = i * keys_stride; key < end_key; key++) {
60-
int64_t value = key & 0xFFFFFFFF;
61-
rid.Set(static_cast<int32_t>(key >> 32), value);
62-
index_key.SetFromInteger(key);
63-
if (with_global_mutex) {
64-
mtx.lock();
65-
}
66-
tree.Insert(index_key, rid);
67-
if (with_global_mutex) {
68-
mtx.unlock();
69-
}
55+
auto insert_keys = [&](const int64_t start_key, const int64_t end_key) {
56+
GenericKey<8> index_key;
57+
RID rid;
58+
for (auto key = start_key; key < end_key; key++) {
59+
int64_t value = key & 0xFFFFFFFF;
60+
rid.Set(static_cast<int32_t>(key >> 32), value);
61+
index_key.SetFromInteger(key);
62+
if (with_global_mutex) {
63+
mtx.lock();
7064
}
71-
};
72-
auto t = std::thread(std::move(func));
73-
threads.emplace_back(std::move(t));
74-
}
65+
tree.Insert(index_key, rid);
66+
if (with_global_mutex) {
67+
mtx.unlock();
68+
}
69+
}
70+
};
7571

72+
// Measure
73+
auto start_time = std::chrono::system_clock::now();
74+
for (size_t i = 0; i < num_threads; i++) {
75+
const auto start_key = i * key_stride;
76+
threads.emplace_back(insert_keys, start_key, start_key + keys_per_stride);
77+
}
7678
for (auto &thread : threads) {
7779
thread.join();
7880
}
81+
auto end_time = std::chrono::system_clock::now();
7982

80-
delete disk_manager;
81-
delete bpm;
82-
83-
return success;
83+
return std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
8484
}
8585

8686
TEST(BPlusTreeContentionTest, BPlusTreeContentionBenchmark) { // NOLINT
8787
std::cout << "This test will see how your B+ tree performance differs with and without contention." << std::endl;
8888
std::cout << "If your submission timeout, segfault, or didn't implement lock crabbing, we will manually deduct all "
8989
"concurrent test points (maximum 25)."
9090
<< std::endl;
91-
std::cout << "left_node_size = 2" << std::endl;
9291

9392
std::vector<size_t> time_ms_with_mutex;
9493
std::vector<size_t> time_ms_wo_mutex;
95-
for (size_t iter = 0; iter < 20; iter++) {
94+
for (size_t iter = 0; iter < 10; iter++) {
9695
bool enable_mutex = iter % 2 == 0;
97-
auto clock_start = std::chrono::system_clock::now();
98-
ASSERT_TRUE(BPlusTreeLockBenchmarkCall(32, 2, enable_mutex));
99-
auto clock_end = std::chrono::system_clock::now();
100-
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(clock_end - clock_start);
96+
auto time = BPlusTreeLockBenchmarkCall(4, enable_mutex);
10197
if (enable_mutex) {
102-
time_ms_with_mutex.push_back(dur.count());
98+
time_ms_with_mutex.push_back(time);
10399
} else {
104-
time_ms_wo_mutex.push_back(dur.count());
100+
time_ms_wo_mutex.push_back(time);
105101
}
106102
}
107103

108104
std::cout << "<<< BEGIN" << std::endl;
109-
std::cout << "Normal Access Time: ";
110-
double ratio_1 = 0;
111-
double ratio_2 = 0;
105+
std::cout << "Multithreaded Access Time: ";
106+
double sum_1 = 0;
107+
double sum_2 = 0;
112108
for (auto x : time_ms_wo_mutex) {
113109
std::cout << x << " ";
114-
ratio_1 += x;
110+
sum_1 += x;
115111
}
116112
std::cout << std::endl;
117113

118114
std::cout << "Serialized Access Time: ";
119115
for (auto x : time_ms_with_mutex) {
120116
std::cout << x << " ";
121-
ratio_2 += x;
117+
sum_2 += x;
122118
}
123119
std::cout << std::endl;
124-
std::cout << "Ratio: " << ratio_1 / ratio_2 << std::endl;
120+
double speedup = sum_2 / sum_1;
121+
std::cout << "Speedup: " << speedup << std::endl;
125122
std::cout << ">>> END" << std::endl;
126123
std::cout << "If your above data is an outlier in all submissions (based on statistics and probably some "
127124
"machine-learning), TAs will manually inspect your code to ensure you are implementing lock crabbing "
128125
"correctly."
129126
<< std::endl;
130127
}
131128

132-
TEST(BPlusTreeContentionTest, BPlusTreeContentionBenchmark2) { // NOLINT
133-
std::cout << "This test will see how your B+ tree performance differs with and without contention." << std::endl;
134-
std::cout << "If your submission timeout, segfault, or didn't implement lock crabbing, we will manually deduct all "
135-
"concurrent test points (maximum 25)."
136-
<< std::endl;
137-
std::cout << "left_node_size = 10" << std::endl;
138-
139-
std::vector<size_t> time_ms_with_mutex;
140-
std::vector<size_t> time_ms_wo_mutex;
141-
for (size_t iter = 0; iter < 20; iter++) {
142-
bool enable_mutex = iter % 2 == 0;
143-
auto clock_start = std::chrono::system_clock::now();
144-
ASSERT_TRUE(BPlusTreeLockBenchmarkCall(32, 10, enable_mutex));
145-
auto clock_end = std::chrono::system_clock::now();
146-
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(clock_end - clock_start);
147-
if (enable_mutex) {
148-
time_ms_with_mutex.push_back(dur.count());
149-
} else {
150-
time_ms_wo_mutex.push_back(dur.count());
151-
}
152-
}
153-
154-
std::cout << "<<< BEGIN2" << std::endl;
155-
std::cout << "Normal Access Time: ";
156-
double ratio_1 = 0;
157-
double ratio_2 = 0;
158-
for (auto x : time_ms_wo_mutex) {
159-
std::cout << x << " ";
160-
ratio_1 += x;
161-
}
162-
std::cout << std::endl;
163-
164-
std::cout << "Serialized Access Time: ";
165-
for (auto x : time_ms_with_mutex) {
166-
std::cout << x << " ";
167-
ratio_2 += x;
168-
}
169-
std::cout << std::endl;
170-
std::cout << "Ratio: " << ratio_1 / ratio_2 << std::endl;
171-
std::cout << ">>> END2" << std::endl;
172-
std::cout << "If your above data is an outlier in all submissions (based on statistics and probably some "
173-
"machine-learning), TAs will manually inspect your code to ensure you are implementing lock crabbing "
174-
"correctly."
175-
<< std::endl;
176-
}
177-
178129
} // namespace bustub

0 commit comments

Comments
 (0)