contributed by < ambersun1234
>
上述 union 大小總共 16 bytes,其中 data[16] 與 另外兩個 struct 共用這個 16 bytes;
根據講解,長度 的字串會存放在 stack,長度 的字串會放在 heap,但是我們可以很明顯地觀察到 data 總共擁有 16 bytes,多的那個 1 個 bytes 則是為了要讓 space_left
, is_ptr
, flag1
, flag2
, flag3
用的,而其中 filler[15] 是為了要對齊 data 前 15 bytes 所用,避免更改到資料部分
注意到 union 中 bit field
的用法,根據 C 語言規格書 §6.7.2.1 - 8
A member of a structure or union may have any object type other than a variably modified type.105) In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any). Such a member is called a bit-field; 106) its width is preceded by a colon.
bit field 可以定義該欄位需要多少 bits,在空間利用上,這是一個很好的技巧
這個函式主要在取得對應的指標,分別有放在短字串的 x->data
、中字串的 x->ptr
以及長字串的 x->ptr + OFF
根據註解 /* The extra 4 bytes are used to store the reference count */
我們可以得知 OFF 為 4 bytes
取出小於等於 n 的 power of 2,考慮
距離 13 最近的 power of 2 為 16() 在位置 4 上面
因為 power of 2 在二進位的表示上,都只會有一個 bit
13 的二進位上,只有4個 bit 有值,而使用 clz 我們可以很輕易的取得前方有多少位元空著的,透過簡單的減法運算可以得到 4(32 - clz(n))
又因為這個函式是要取 lowerbound ,所以必須在 - 1
也可以用 ctz 進行改寫
變成
NNN 為 16,因為大於 16 就必定需要用到 heap 進行存取
該 function 為 trim,也就是去除特定字元,所以不難猜測到 check_bit 是用於檢查是否有一樣的字元,而 set_bit 則是將要去除字元寫入 mask
值得注意的是,解答給了一個我覺得很神奇的解法
根據 ASCII 的定義,它包含了 128 個字元 (可用 8 個 bits 表示)
解答採用的方式是,用一個 map 去對應,前 5 個 bits 是 index,後 3 個 bits 是 value
在 value 的方面,也不是簡單的儲存 bits,而是把它當作 shift amount
因為,可想而知,如果直接採用後 3 bits,一定會遇到 000
的情況,變成再比對的時候,條件會一直成立,即使沒有把該字元寫入 trimset (因為一開始就把 mask 初始化為 0)
也就是說,value 的值會從 2 (1 << 1
) ~ 128 (1 << 7
)
輸出如下
實作 Copy on Write - CoW 時要注意長字串還有 reference count 需要修正。
以時間效率來說,根據 Stack vs Heap Memory Allocation 中指出,stack memory allocation 中的操作由編譯器事先規劃,而且記憶體區段是連續的,也因此相較於 heap memory allocation 來說,存取速度會比 heap 還要快
空間效率的部分。C++ std::string 只能使用一半的大小,詳見以下實驗
參照 Exploring std::string 做了一個實驗(實作程式碼: linux2021q1 quiz3/stdstringTest.cpp)
得到的測試結果如下
由上可得知,std::string 僅能使用一半的空間
考慮空間效率實驗,詳見 linux2021q1 quiz3/spaceTest.cpp
針對字串大小為 的 massif 輸出
針對字串大小為 的 massif 輸出
綠色的部分是 xs
本身的佔用空間,黃色的部分是 std::string
,青色的部分是 xs heap
的部分
根據 的輸出 (上圖) 可以得知,xs 的空間隨著字串大小越來越大,直到 43.0KB
(綠色部分),後來就換成青色的部分,也就是 heap (malloc) 的部分
接著考慮 的輸出 (下圖),可以發現,黃色的部分 (std::string
) 相比青色 (xs heap
),增長的更快,也就是說,xs 的實作相比 std::string
來說確實可以減少記憶體使用量
linux2021