ARST打卡第266周
lc3040_相同分数的最大操作数目II USENIX ATC ‘23 - RubbleDB:CPU-Efficient Replication with NVMe-oF 链抽象/互操作性/全链 raft_apply慢导致业务不可用的情况分析
Algorithm
lc3040_相同分数的最大操作数目II
思路:
这里把删除看成左右双指针移动。
然后最开始有3种操作选择导致有3种值,选择了值之后, 后面的操作都根据值来选定记忆回溯即可。
|
|
其中一开始报错:
Line 2: Char 40: note: default constructor of ‘Solution’ is implicitly deleted because field ‘cache’ has a deleted default constructor 2 | unordered_map<pair<int, int>, int> cache;
问GPT4o:
The error you’re encountering arises because the default constructor of
unordered_map
cannot handle thepair<int, int>
type directly as a key without a custom hash function. This issue can be resolved by defining a custom hash function for thepair<int, int>
.Here’s how you can resolve this:
- Define a custom hash function for
pair<int, int>
.- Specify this custom hash function in the
unordered_map
.Here’s an example of how you can do it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#include <iostream> #include <unordered_map> #include <utility> // For std::pair #include <functional> // For std::hash // Define a custom hash function for pair<int, int> struct pair_hash { template <class T1, class T2> std::size_t operator() (const std::pair<T1, T2> &pair) const { return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second); } }; class Solution { public: std::unordered_map<std::pair<int, int>, int, pair_hash> cache; Solution() = default; // Other member functions... }; int main() { Solution sol; // Example usage sol.cache[std::make_pair(1, 2)] = 42; std::cout << sol.cache[std::make_pair(1, 2)] << std::endl; return 0; }
In this example,
pair_hash
is defined to hash astd::pair<int, int>
. This hash function is then used in theunordered_map
declaration in theSolution
class. This way, theunordered_map
can properly handlepair<int, int>
keys, and the default constructor ofSolution
will work correctly.Explanation:
pair_hash
: A custom hash function struct that uses thestd::hash
functions for the elements of the pair and combines them with XOR.cache
: Declared as anunordered_map
withstd::pair<int, int>
as the key type andint
as the value type, usingpair_hash
for hashing.Solution() = default
: Explicitly defaulted constructor forSolution
class.By applying this custom hash function, you enable the
unordered_map
to handlestd::pair<int, int>
keys properly, resolving the compilation error.
后面 TLE 了… 全是 1000.. 确实没有考虑到这种 corner case.
超出时间限制 : 520 / 549 个通过的测试用例
最后执行的输入: nums = [1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
感觉这个 cornor case 在提醒我,是不是可以服用一下缓存?
先试一下不严谨的假设所有的 l,r
的 key 都是相同的 sum.
不行,还是 TLE 在这里,所以不用尝试 l,r,sum
的 key 的 cache 了。
看了答案,发现差不了太多,所以再剪枝试试。
吐血,因为用容器导致卡 TLE 了,然后用数组就能过…基本和题解一样,但还是学习一下题解写法
|
|
Review
USENIX ATC ‘23 - RubbleDB:CPU-Efficient Replication with NVMe-oF
通过 Nvme-oF 远程复制其他副本的 rocksdb 的 compaction 完成的 SST 来节约 CPU 和 CPU-IO.
也就是通过更复杂的管理程序+网络IO来换取 CPU 和 CPU-IO.
在 CPU 限制的复制集群是有效的。
但是在 IO 限制的集群,可能效果不是那么明显。
而且个人认为对于 Raft + Rocksdb 3副本的场景。 这种虽然有点像 Install Snapshot,但是又好像需要和 Rocksdb 内部状态进行耦合,导致了更复杂的管理问题。 并且让三副本的独立性变得关联起来了,对网络故障的抗风险能力估计又得重新评估了。
因此个人决定性能提升不是很大,以及CPU不是瓶颈的话,还是不建议采用这种方案。 但是这种方案的探索,用网络IO换取CPU和CPU-IO的行为和思路还是值得肯定和学习的。
Tips
其实本质还是统一平台。
Share
raft apply慢导致业务不可用的情况分析
如果 raft 中 leader 因为一些因素导致程序运行很慢,可能 apply 比 follower 慢 (follower,leader 一起异步 apply ),导致业务写超时。
但是这种情况又不会产生 leader 转换,因此需要及时排查其他卡慢因素(cpu被其他程序占用等), 防止因 leader apply 慢而出现的业务不可用的现象。