CMU15445-project1-满分收获总结

CMU15445-project1-满分收获总结

        • TASK #0 gradescope
          • 0.0 关于线上测试的天坑
        • TASK #1 - LRU REPLACEMENT POLICY
          • 1.1线程安全
          • 1.2 upin 和 pin 如何理解
          • 1.3 优化搜索效率
        • TASK #2 - BUFFER POOL MANAGER INSTANCE
          • 2.1 frame_id和page_id的关系
          • 2.2 天坑:DeletePgImp() 的返回值问题
          • 2.3 UnpinPgImp() 注意事项,dirty()测试跑不通
        • TASK #3 - PARALLEL BUFFER POOL MANAGER
          • 3.1 线程安全


CMU15445-project1-满分收获总结_第1张图片

CMU15445-project1-满分收获总结_第2张图片

TASK #0 gradescope

0.0 关于线上测试的天坑

在gradescope上测试代码时,没有通过的案例如果显示的是超时,那不一定是因为死锁或者死循环!

  1. 我没有写线程安全的代码,显示的是超时
  2. 我代码有的部分会造成内存泄漏,显示的还是超时
  3. 死锁或者replacer复杂度太高确实有可能造成超时

TASK #1 - LRU REPLACEMENT POLICY

1.1线程安全

要求了线程安全但又没有说具体怎么做,以至于在最后才回来考虑上锁的问题。

其实很简单,在头文件内声明一个锁。在实现的每个函数开头上锁,结尾释放就行。

// 头文件
#include
// 声明
std::mutex lock_;
//上锁(请求锁),释放锁
lock_.lock();
lock_.unlock();

注意事项:
1.每个return之前都要记得释放锁
2.关于死锁,如果都是开头上锁结尾解锁,根本不会有产生死锁的条件(请求并保持)。
3.如果在一个函数里调用了另一个使用lock的函数,百分百会卡死,因为这个函数的lock还未释放,调用的函数就会一直等待lock。解决办法:在函数调用前释放锁,调用后申请锁。(但这个project可其实以避免这种调用关系)

1.2 upin 和 pin 如何理解

pin():就理解成有人正在使用这个页面,不能用来作为牺牲了,故需要删除当前frame_id(而不是放在末尾)
unpin():lru_relpacer不需要考虑什么时候需要unpin,直接理解成当前frame_id可以作为牺牲id,装入队列就行。

1.3 优化搜索效率

使用STL自带的unsord_map()作为hash表,keyframe_idvaluelist内对应元素的指针(迭代器),这样对frame_id对应的元素的操作只需要O(1)级别复杂度。
(对应的leetcode题,代码相似度很高)

//初始化
std::list<frame_id_t> page_list_;
std::unordered_map<frame_id_t, std::list<frame_id_t>::iterator> frame_table_;

// 使用示例
auto it = frame_table_.find(frame_id);
if (it != frame_table_.end()) {  // exist
  page_list_.erase(it->second);
  frame_table_.erase(it);
}

TASK #2 - BUFFER POOL MANAGER INSTANCE

2.1 frame_id和page_id的关系
  • 每一个BPLI(BUFFER POOL MANAGER INSTANCE)都会被分配一个固定的pool_size_,根据pool_size_ 新建的pages_数组实际上就是BPLI用来存放页面的盒子。
  • 直观上来看,frame_id就是是pages_数组的下标,而page_id指的放入盒子(数组)的page号。
  • 所以replacer管理的是frame_id的分配,BPLI 的工作就是负责分配frame_id(实则是分配盒子)给pages
2.2 天坑:DeletePgImp() 的返回值问题

这个坑卡了我一下午的时间debug,就一个返回值让我从62分跳到了96分。
CMU15445-project1-满分收获总结_第3张图片
按道理找不到页面应该返回false,这里却要求的是true。虽然也的确是审题不当,但这个着实把我坑惨了。

2.3 UnpinPgImp() 注意事项,dirty()测试跑不通

这个函数没有太多注解,所以有的地方都是靠上传测试摸索出来的,感觉实在没必要。
1.对于pin_count_大于1的情况,是减一,而不是清零。
2.不需要对脏页面进行写回磁盘,只需要把脏标记在对应page上就行。

TASK #3 - PARALLEL BUFFER POOL MANAGER

这部分其实看了需求就会知道,是最简单的一部分,只需要对之前两部分进行调用就行了,没有太大问题。

3.1 线程安全

这个管理器不需要设置锁,只需要在replacerbpli设置锁就行。

你可能感兴趣的:(数据库,C++,多线程,操作系统,数据库开发)