cmu15445 2023spring Project #2 - B+Tree

B+Tree索引

插入与删除

主要需要注意分裂与合并。分裂时,叶子节点是先分裂再插入数据,而内部节点需要先插入再分裂。
删除时,先删除,如果size小于minsize则需要向左右兄弟节点借数据,如果还不行则合并。

有一个特殊情况就是没有兄弟节点,尽管这在真实索引使用中是不可能的,但是在在线测试中,有些测试中internal_max_size = 3,这就会发生没有兄弟节点的情况。对于这种情况,笔者的处理是只删除数据不删除节点,但是在使用迭代器时,需要对operator++进行特殊处理。

迭代器

笔者的数据成员如下

  BufferPoolManager *bpm_{nullptr};
  page_id_t leaf_page_id_{INVALID_PAGE_ID};
  int index_{0};

而在operator++中需要跳过一些空节点,核心代码如下

while (leaf_page_id_ != INVALID_PAGE_ID && index_ >= leaf_page_ptr_->GetSize()) {
  index_ = 0;
  leaf_page_id_ = leaf_page_ptr_->GetNextPageId();
  read_guard_page = bpm_->FetchPageRead(leaf_page_id_);
  leaf_page_ptr_ = read_guard_page.As<BPlusTreeLeafPage<KeyType, ValueType, KeyComparator>>();
}

并发

笔者的并发策略基于这样的一个判断:发生分裂/合并的插入/删除操作占比较小。因此,对于插入操作,第一次插入,只获取叶子节点的写锁,如果不需要分裂,则插入后返回,否则进行第二次插入。
第二次插入,获取根节点到页子节点的写锁,从叶子往上,进行递归插入。
删除操作同理。
这样做的好处是,对于第一次插入,不会阻塞读操作,同时也能支持对不同叶子节点的插入操作。

debug

对于本地测试,可以使用vscode debug。比较难的是并发的debug,这里说下笔者印象较深的bug,就是是FetchWritePage中,bpm锁、pin_count和page写锁的管理,最后通过的代码是:先获取bpm锁,然后pin_count++,然后释放bpm锁,再申请page写锁。
除了互斥资源,锁的释放如果被阻塞了,也可能引发死锁。

对于在线测试,笔者只会用经典方式:cout,打印一些信息来推测大概哪里出问题。

测试与总结

到提交为止(2023-05-13),gradescope上有42人完成了project2。由于缓冲区管理用的是全局锁,笔者的B+树并发性能算是一般。
在这里插入图片描述

笔者之前也写过B+Tree,但是是单线程内存B+Tree,这次多线程磁盘B+Tree还是挺困难的。
相较于内存索引,磁盘索引还需要管理缓存区。
另外两者的I/O粒度也不同,前者是cpu cacheline,后者是磁盘页/块。这导致两者在设计的着重点也不同,内存B+Tree的节点较小,需要充分利用每一个字节。

总之,这次实验增加了对面向磁盘B+Tree的理解,积累了并发编程以及debug的经验。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CMU 15445 课程的 Project 0 是一个调试练习,旨在帮助学生熟悉调试工具和技术。在这个项目中,你将开始使用 GDB 和 Valgrind 这两个常用的调试工具,以及一些其他辅助工具。以下是一些问题和步骤,帮助你完成这个练习: 1. 你需要查看项目中提供的代码,并了解它的结构和功能,这样你才能更好地理解程序的逻辑和可能出现的 bug。 2. 接下来,你需要编译项目,并确保没有编译错误。如果出现错误,你需要修复它们,这可能需要检查一些语法错误或缺失的库。 3. 一旦成功编译项目,你就可以使用 GDB 进行调试了。GDB 是一个强大的调试器,可以帮助你找出程序中的错误。你可以使用 GDB 来单步执行代码、设置断点、查看变量的值等等。通过使用 GDB,你可以逐步查看代码运行的路径,并找出程序崩溃或产生错误的原因。 4. 在使用 GDB 进行调试时,你可以通过设置断点来暂停程序的执行,并查看变量的值和程序的状态。你可以使用“break”命令在程序中设置断点,并通过“run”命令启动程序。当程序到达这个断点时,它会停止执行,你可以使用“print”命令查看变量的值,或者“step”命令逐步执行代码。 5. 另一个常用的调试工具是 Valgrind。Valgrind 可以帮助你检测内存泄漏和错误的访问方式。你可以使用“valgrind”命令来运行程序,并查看 Valgrind 的输出。它会告诉你有关程序中任何潜在问题的信息,例如未初始化的变量、访问越界等。 6. 最后,当你发现 bug 并修复它们后,可以运行各种测试用例来验证程序的正确性。测试用例可以帮助你确定程序是否按预期工作,并且在修改代码后,它们可以帮助你确保你的修复没有引入新的错误。 通过完成 CMU 15445 项目 0 的调试练习,你将掌握一些重要的调试技巧和工具,这对于进一步开发和调试软件应用程序将非常有用。希望上述步骤和建议对你有所帮助,祝你顺利完成这个项目!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值