2022-09-17

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,才能删除元素,而现在,我们拿到了该锁,删除元素与否掌握在我们手里。

  1. rcu_read_lock保证 元素不被释放
  2. 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