perfbook 01 摘录
perfbook 指的是 Is Parallel Programming Hard, And, If So, What Can You Do About It? pdf 版本可以从如下网址获取: https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html
5.4.6 Applying Exact Limit Counters
Quick Quiz 5.58: This is ridiculous! We are read-acquiring a reader-writer lock to update the counter? What are you playing at?
答: 这里要强调的是 读锁 允许 多人同时持有,写锁只允许单人持有。 跟 是否进行 读写操作没有必然关系。
Chapter 6 Partitioning and Synchronization Design
一种强制锁范围不重叠的办法。两个单独的双端队列串联在一起,每个队列用自己的锁保护。这意味着数据偶尔会从一个双端队列跑到另一个双端队列。此时必须同时持有两把锁。
awakening-fong: 妙
"哈希永远是分割一个数据结构的最简单和最有效的方法。"
awakening-fong: 这样,每个元素就都有 自己所属的 bucket了.
在10核系统上运行的程序只能在关键的临界区上花费小于1/10的时间,这样以后才能有效地扩展。
awakening-fong注释: 10核时, 其中的单个线程耗时t,如果单个线程消耗在临界区的时间>=t/10,那么,10核后,加更多cpu也无益。
RCU使用
“宽限期”(grace period)
awakening-fong: 类比 还钱,宽限 几天。宽限期 即 债务的缓延偿还 期间。 还钱 好比 是释放内存,将内存归还给系统。
Listing 9.21: Existence Guarantees Enable Per-Element Locking
//这里假定没有hash冲突
1 int delete(int key)
2 {
3 struct element *p;
4 int b;
5
6 b = hashfunction(key);
7 rcu_read_lock();
8 p = rcu_dereference(hashtable[b]);
9 if (p == NULL || p->key != key) {
10 rcu_read_unlock();
11 return 0;
12 }
13 spin_lock(&p->lock);
14 if (hashtable[b] == p && p->key == key) {
15 rcu_read_unlock();
16 rcu_assign_pointer(hashtable[b], NULL);
17 spin_unlock(&p->lock);
18 synchronize_rcu();
19 kfree(p);
20 return 1;
21 }
22 spin_unlock(&p->lock);
23 rcu_read_unlock();
24 return 0;
25 }
Quick Quiz 9.33: Why is it OK to exit the RCU read-side critical section on line 15 of Listing 9.21 before releasing the lock on line 17?
答:
7 rcu_read_lock();
8 p = rcu_dereference(hashtable[b]);
。。。
13 spin_lock(&p->lock);
14 if (hashtable[b] == p && p->key == key) {
15 rcu_read_unlock();
处于rcu read保护范围,有引用计数的效果,解引用的 元素 不会被释放,至少在 rcu_read_unlock() 执行前。
13 spin_lock(&p->lock);
14 if (hashtable[b] == p && p->key == key) {
因为获得了spin lock,才能删除元素,而现在,我们拿到了该锁,删除元素与否掌握在我们手里。
rcu_read_lock
保证 元素不被释放- spin+key判断(14行)保证 拿到了元素的释放权, rcu担心的事情不存在了, 所以,只需要一个锁。
小问题9.34:为什么图9.32第23行不能在第22行释放锁之前就退出RCU读端临界区?
答: 或者说, 为何 22行 不能和 23 行 对调
cpu0 cpu1
rcu read
spin lock
key==
rcu read
spin lock
修改指针
spin unlock
key!=
rcu unlock
sync rcu
free(p)
spin unkock(&p->lock)
注意,最后cpu0的free(p)参数是p, cpu1的spin unlock参数也是p相关的。 cpu1对一个已经被释放掉的内存进行 unlock, 故,BUG。
11章 验证
假设一个特定测试有10%的失败几率。你需要运行多少次测试用例,才能导致失败的几率超过99%?毕竟,如果我们将测试用例运行足够次数,使得至少有一次失败的几率达到99%,如果此时并没有失败,那么仅仅只有1%的几率表明这是由于好运气所导致。
公式11.6
所需的测试次数是 n = log (1 − Fn )/log(1− f)将f=0.1及Fn=0.99代入公式11.6,得到结果43.7,这表示我们需要44次连续成功运行测试用例,才能有99%的把握确保对故障的修复真的生效。
本文地址: https://awakening-fong.github.io/posts/perf/perfbook-01
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.
blog comments powered by Disqus