還記得在剛到公司上班不久,就要處理產品的一個Bug。
這個問題是這樣的,從系統的日誌(Log)上看起來是因為應用程式的動態函式庫在執行期間因為無效的記憶體存取而造成Segment fault,最後從使用者這邊啟動的應用程式就發生閃退了。當時一度懷疑是 Houdini 的問題(這是經驗法則...= =),但是在開發初期到問題發生的中間 Houdini 並沒有版本更新,而且在前者程式卻沒有發生閃退。
所幸,最後是神人同事發現到開發過程中間有引進ZRAM的功能,閃退的原因是因為 ZRAM 的 alignment 問題造成程式對記憶體的超界存取。
問題解決後,資深老鳥要菜逼八本魯解釋什麼是 ZRAM....。
ZRAM是什麼?
ZRAM 是一種置換空間(Swap Space)的機制,但是相較於傳統的 Swap 是將從記憶體將分頁置換到硬碟中,ZRAM 則是將分頁置換到記憶體。但是這下又有問題了....
置換會發生不就是因為實體記憶體空間已經不夠用了,所以才要將分頁搬移到硬碟,那把分頁置換到記憶體不是在耍白痴嗎?
正是因為如此,所以要被置換出的分頁必須要經過LZO或LZ4演算法壓縮,才可以置換到記憶體。
ZRAM 於 Linux Kernel 3.14版本正式合併到主線,於3.15版加入LZ4壓縮演算法。
為什麼要ZRAM?
相較於PC, 我們的手機裝置上的記憶體容量多數是比較小的,為了要讓程式有更多的記憶體空間可以使用所以我們需要置換空間。PC可以用硬碟作置換空間,那手機呢?
當然聰明的人一定會想到,用手機的 eMMC 或是 SD 卡不就行了。
但是不幸的是,eMMC 和 SD卡 因為它們的物理特性,容許寫入的次數非常少。一旦讓 eMMC 和 SD 卡承受頻繁的寫入,那麼他們很快就會壞掉了。
所以,在早期的手機(Android KitKat 以前)是沒有置換空間的。也正因為如此,我們無法在手機上使用會大量消耗記憶體的應用程式,或是只能讓記憶體中存在有限的行程。
為了解決這項問題 ZRAM 便應運而生。
ZRAM與 Disk swap 相較的優缺點
優:
1. ZRAM 置換出的存儲媒體是 RAM 且 RAM 寫入的速度遠大於 Disk 或是快閃記憶體的寫入速度
2. 可以避免快閃記憶體的磨耗
缺:
寫入 RAM 之前必須經過壓縮,不像 Disk 或快閃記憶體一樣直接寫入即可
ZRAM與 快閃記憶體 swap 效能比較
在 beaglebone black 上寫一個無限迴圈,迴圈中的每一步都會 malloc 1MB 的記憶體,
一直執行到系統的 memory killer 被叫起來為止。並用 vmstat 每秒紀錄一筆資料。
flash:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 479180 1812 3136 0 0 107 4 58 112 0 6 93 1
0 0 0 479180 1812 3156 0 0 0 0 7 8 0 0 100 0
0 0 0 479180 1812 3156 0 0 0 0 39 54 0 1 99 0
0 0 0 479180 1812 3156 0 0 0 0 9 8 0 0 100 0
0 0 0 479180 1812 3156 0 0 0 0 7 10 0 0 100 0
1 0 0 169776 1816 3688 0 0 536 0 276 133 26 71 0 3
3 0 129228 3324 76 680 72 139600 1036 139692 913 869 5 36 0 59
0 2 144788 2628 76 984 24 5232 188 5236 116 123 2 12 0 86
1 1 185984 2752 76 900 0 41196 0 41196 161 162 1 35 0 64
0 2 198552 3360 76 888 0 12568 0 12568 108 132 0 9 0 91
0 2 198552 3496 76 888 0 0 0 0 53 61 0 2 0 98
0 2 198552 4092 76 888 0 0 0 0 89 70 0 5 0 95
0 3 198552 4600 76 888 0 0 0 0 83 73 0 6 0 94
0 3 239436 4620 92 868 0 40884 4 40912 738 965 3 19 0 79
1 2 247716 2648 96 880 0 8280 0 8288 101 113 1 17 0 82
1 1 259520 3476 96 880 0 11800 0 11800 128 140 2 29 0 69
3 0 262136 44508 76 412 0 2632 1148 2632 204 211 0 31 0 69
計算得到平均Swap out 速度每秒為 23830 bytes
ZRAM:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 0 472580 2364 7732 0 0 31 4 139 46 54 2 44 0
0 0 0 472596 2364 7736 0 0 0 0 9 12 0 0 100 0
0 0 0 472596 2364 7736 0 0 0 0 34 48 0 0 100 0
1 0 0 320532 2368 8268 0 0 536 0 200 132 18 41 40 2
3 0 2184 3212 84 940 132 4020 872 12 285 197 24 76 0 0
2 0 60992 2688 84 1208 0 57072 112 4 232 860 4 96 0 0
2 0 119288 2820 92 1112 0 58300 0 76 256 860 4 96 0 0
2 0 177652 2820 92 1112 0 58364 0 4 207 824 3 97 0 0
2 0 236628 2656 92 1108 0 58972 0 0 201 803 2 98 0 0
計算得到平均Swap out 速度每秒為 47325 bytes
結論:
雖然 ZRAM 要 Swap out 會因為壓縮使用掉一些 CPU 時間,但是因為 RAM 的寫入速度比快閃記憶體要快很多。所以可以看到 ZRAM swap out 的速度整體還是比較快。