2021q1 Homework3 (quiz3)
contributed by < YoLinTsai
>
題目
- 先來看最重要的這段 union 結構,我的理解是, union 是共享一塊記憶體,根據 assign 進來的變數改變記憶體內容,利用這樣的特性,即便我們宣告了數種不同的 struct 結構,透過巧妙的記憶體空間安排,我們可以有效的共用一些記憶體的內容。
- 以下是記憶體安排的示意圖,特別注意這樣巧妙的安排,可以使不同的方式都能安全的調用 flag ,回顧 fbstring 中的特性,比方說我們把 filler 填滿,最後一個字元剛好是
0x00
, flag 的意義仍然正確。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
xs_new
xs_new
是 xs 剛宣告時會被呼叫來 allocate 記憶體的 function,如下段所示
NNN
為16的理由是當字串長度超過16時, xs 才會用 large_string 的 policy,接著來看ilog2
:
ilog2
是為了找最接近但不出過 n 的 2^k , 這裡用clz
來找 32 bits integer 中從右邊數過來第一個 1 之前有幾個 0,接著2^(ilog2(len) + 1)
即是 large_string 應該要 allocate 的記憶體空間。
xs_trim
- 如同 quiz3 中的說明,
xs_trim
的用途是將字串前後指定的字元刪除,我們先看判斷和刪除的部份
-
這裡的手法是做兩次 iteration ,一次從頭一次從尾,判斷好 trim 完的邊界後用 memmove
修剪完成。
-
值得注意的是這裡用來判斷是否為需要刪除字元的手法相當細緻,在 ascii 的編碼下,字元的值可能是 0~255,如此一來我們可以用一個 256 bits 的 mask 去表達哪幾個字元是要被刪除的。
-
我們假設指定刪除字元為 x:
set_bit(x): mask[ascii(x)] = 1
check_bit(x): return mask[ascii(x)] == 1
而 CCC 和 SSS 的 bit operation 正符合上述的邏輯。
xs_allocate_data
這段是當 xs_new
判斷字串長度超過 16 時,便會改成用 medium/large string 的 struct 去儲存,同時也會用 xs_allocate_data
去 malloc 記憶體,同時我們可以發現,當字串長度超過 LARGE_STRING_LEN (256)
時,會多申請 4 個 bits 用來紀錄 reference count。
xs_copy
- 這裡同時會解釋 CoW 和 Reference Count
- 首先 reference count 在的意義是: 有幾個 pointer 指著這塊記憶體,在 sso 當中的意含就是有幾個 Large String 的 ptr 指向同一塊記憶體。
- 那為什麼會發上述情形呢?因為 Copy on Write 的設計導致會有上述狀況, CoW 的使用情境是這樣:當我想 copy 一塊記憶體的時候,如果我接著沒有馬上要用,那我在 copy 的當下就去 allocate 似乎是個有點浪費空間和時間的作法
- 取而代之的,我們可以偷偷的把 pointer 指向被複製的 address ,一旦發現我真的要改他的時候,而且有複數個 pointer 指向該記憶體,再去申請一塊新的記憶體。
- 如上面那段 code ,我們先判斷是否為長字串,接著判斷是否為 large_string ,如果為真就用 CoW ,並調整 reference count (refcnt)。
gdb檢驗
- print copyString (after trim)
- 這邊檢查了 ptr 有正確指向 heap 位置,同時檢測 CoW 前後是否有確實 malloc 新的記憶體並將 ptr 指向新的位置,此外一併檢查了 refcnt 的正確性。
設計實驗
- 對比 strncpy 每次 copy 都去 malloc 一塊
- 可以發現 CoW 的手法會讓 cache-misses 的數量下降許多,其實這也符合 CoW 設計的手法,同時我們也可以發現 CoW 所花的時間是比較長的。(待確認原因)
- massif