publicstaticvoidsolve() { inta= io.nextInt(), b = io.nextInt(); intx=1; for (inti=0; i < b; i++) { x *= a; } inty=1; for (inti=0; i < a; i++) { y *= b; } io.println(x + y); }
publicstaticvoidsolve() { intn=3, m = io.nextInt(); intans= Integer.MAX_VALUE; String[] s = newString[n]; for (inti=0; i < n; i++) { s[i] = io.next(); } for (inti=0; i < n * m; i++) { chara= s[0].charAt(i % m); for (intj=0; j < n * m; j++) { if (i == j) continue; charb= s[1].charAt(j % m); for (intk=0; k < n * m; k++) { if (i == k || j == k) continue; charc= s[2].charAt(k % m); if (a == b && b == c) { ans = Math.min(ans, Math.max(i, Math.max(j, k))); } } } } io.println(ans == Integer.MAX_VALUE ? -1 : ans); }
publicstaticvoidsolve() { intn= io.nextInt(), k = io.nextInt(); intans=0, i; for (i = 1; i + k - 1 <= n; i += k) { io.println("? " + i); io.flush(); ans ^= io.nextInt(); } for (; i <= n; i++) { io.println("? " + (i - k + 1)); io.flush(); ans ^= io.nextInt(); } io.println("! " + ans); io.flush(); }
② 在 Evict 的注释中有:If multiple frames have inf backward k-distance, then evict frame with earliest timestamp* based on LRU。我以为淘汰的是最后一次访问时间最早的 frame,结果淘汰的是第一次访问时间最早的 frame。
④ 在 RecordAccess 的注释中有:If frame id is invalid (ie. larger than replacer_size_), throw an exception。但其实应该是大于等于吧,因为 BufferPoolManager 构造函数的实现如下:
1 2 3 4 5 6 7 8
// we allocate a consecutive memory space for the buffer pool pages_ = new Page[pool_size_]; replacer_ = std::make_unique<LRUKReplacer>(pool_size, replacer_k);
// Initially, every page is in the free list. for (size_t i = 0; i < pool_size_; ++i) { free_list_.emplace_back(static_cast<int>(i)); }
LRU-K 和 LFU 的区别:LRU-K 有一个“老化”的概念,即只考虑对页面的最后 K 次引用,而 LFU 无法区分最近和过去的引用频率,因此无法应对不断变化的访问模式。
LRU-K 存在的问题:① Early Page Replacement,新加入缓冲池的页面因为访问次数不足 K(K≥2),所以相对于有 K 次访问历史的页面更容易被淘汰,但是该页面之后可能会有相关访问(原文是称作 Correlated References,并介绍了事务内、事务重试、进程内、进程间的相关访问);② Page Reference Retained Information Problem,当页面被淘汰时,它的访问历史需要保留一段时间,如果超时再进行删除操作。
实现
更新:以下内容存在一些错误,将会在下一节纠正。
① 初次提交,所有函数开头一把大锁。提交相同的代码,排名波动挺大的,可能是因为没优化的代码跑分都差不多,QPS 大概四五千左右。
#!/bin/bash make lru_k_replacer_test buffer_pool_manager_test page_guard_test -j$(nproc) ./test/lru_k_replacer_test ./test/buffer_pool_manager_test ./test/page_guard_test make format make check-lint make check-clang-tidy-p1 make submit-p1
项目小结
① 在做项目的时候,总是会想某个地方是不是有更优的写法,但是当时对整个项目结构不太清楚,以及代码实现是否正确也不清楚,所以基本上都是浪费时间。据此,我的收获就是先让代码跑起来,其他的之后再说。
② 虽然做的时候很艰辛,但是做完之后发现,好像也没有什么工作量,bpm 优化也就是简单减少锁的粒度,lru 的优化也完全是针对基准测试做的,感觉我的优化方式很烂,有没有更牛逼的优化方式啊。