Lab 7 Lock
Re-designing code to increase parallelism
Introduction
Youāll gain experience in re-designing code to increase parallelism. A common symptom of poor parallelism on multi-core machines is high lock contention. Improving parallelism often involves changing both data structures and locking strategies in order to reduce contention. Youāll do this for the xv6 memory allocator and block cache.
Task 1: Memory Allocator
The program user/kalloctest stresses xv6ās memory allocator: three processes grow and shrink their address spaces, resulting in many calls to kalloc and kfree. kalloc and kfree obtain kmem.lock. kalloctest prints the number of test-and-sets that did not succeed in acquiring the kmem lock (and some other locks), which is a rough measure of contention:
$ **kalloctest**
start test0
test0 results:
=== lock kmem/bcache stats
lock: kmem: #test-and-set 161724 #acquire() 433008
lock: bcache: #test-and-set 0 #acquire() 812
=== top 5 contended locks:
lock: kmem: #test-and-set 161724 #acquire() 433008
lock: proc: #test-and-set 290 #acquire() 961
lock: proc: #test-and-set 240 #acquire() 962
lock: proc: #test-and-set 72 #acquire() 907
lock: proc: #test-and-set 68 #acquire() 907
test0 FAIL
start test1
total allocated number of pages: 200000 (out of 32768)
test1 OKThe root cause of lock contention in kalloctest is that kalloc() has a single free list, protected by a single lock.
Your job
To remove lock contention, you will have to redesign the memory allocator to avoid a single lock and list. The basic idea is to maintain a free list per CPU, each list with its own lock.
Solution
In kalloc
kallocTry to get free memory from process own free list.
Steal free memory from other processā free list.
Use lock when access free list.
Donāt hold more than one lock. Avoid deadlock.
Task 2: Buffer Cache
The Problem
If multiple processes use the file system intensively, they will likely contend for bcache.lock, which protects the disk block cache in kernel/bio.c. bcachetest creates several processes that repeatedly read different files in order to generate contention on bcache.lock.
Your Task
Modify the block cache so that the number of test-and-sets for all locks in the bcache is close to zero when running bcachetest. Ideally the sum of test-and-sets of all locks involved in the block cache should be zero, but itās OK if the sum is less than 500. Modify bget and brelse so that concurrent lookups and releases for different blocks that are in the bcache are unlikely to conflict on locks (e.g., donāt all have to wait for bcache.lock). You must maintain the invariant that at most one copy of a block is cached.
Solution
Instead of using linked list, look up block numbers in the cache with a hash table that has a lock per hash bucket.
Implement hashable
Modify bget to use hash table
bget to use hash tablebrelse doesnāt need to acquire the bcache lock
brelse doesnāt need to acquire the bcache lockThoughts
Lock contention is a hard to solve problem. My buffer cache solution is a little bit hack, since the actual optimal solution is to have a concurrent hash table, each bucket is a linked list. Also another list to track least significant use. Similar to LRU cache.
Result
All tests except writebig and bigdir tests have passed.
åæå¾
éēēå¾é¾ļ¼concurrencyę“é¾ļ¼čæäøē« ęåŖę„触äŗå°å±±äøč§ļ¼ä½ęÆęē„éęÆäøäøŖååŖęčø©čæęä¼ę·±å»ļ¼ęäŗäŗŗēēéļ¼åæ é”»čŖå·±ęč½č§£å¼ć
Last updated
Was this helpful?