SSD(固態硬碟)的優化是個老議題了,不外乎就是4K對齊、減少寫入次數並清理「髒掉的」磁區。那麼這些事項在Linux作業系統下要如何進行呢?



4K對齊

使用SSD在切割分割區時,因SSD內部最小的寫入單位是4KB(1 page),要注意分割區一定得4K對齊,不然會嚴重影響到SSD的存取效能和壽命。Linux的磁碟分割軟體,在預設情況下切割出來的分割區就已經有4K對齊了。

如果不放心的話,可以利用fdisk工具在終端機內查看SSD分割區的起始位置的磁區數量是否能整除8。查看的指令如下:

sudo fdisk -lu

linux-ssd-optimization

為什麼SSD分割區的起始位置磁區數能整除8就有4K對齊?

實際上磁區還分為真實體磁區(Physical Sector)和邏輯磁區(Logical Sector),會有這樣的區別跟後來出現的「先進格式(Advanced Format)」有關。簡單來說,以前1個磁區只有512個位元組,但是後來往上增加了,作業系統必須也要有支援邏輯磁區的功能才能正常使用。為了使得新規格的硬碟可以相容於舊的作業系統上,於是廠商便直接把「邏輯磁區」這種模擬技術直接做在硬碟上了。有了這樣的技術就可以將4K大小的磁區模擬成8個512位元組的磁區,這就是為什麼我們要讓磁區數量能整除8啦!

減少寫入次數

SSD顆粒的寫入次數是有限的,因此若我們想辦法減少SSD的寫入次數,就可以延長SSD的生命。

關閉上次存取時間的記錄

現代的檔案系統幾乎都有記錄檔案最後一次被開啟的時間的功能,也就是說,每當檔案被讀取一次,硬碟也要跟著被寫入一次,這對SSD的壽命來說是十分不友善的。在Linux下,我們可以在掛載檔案系統時,替檔案系統加上noatime參數,來關閉「存取時間」(Access Time)的功能。

如下圖,便是直接在/etc/fstab設定檔的options欄位中加上noatime參數。

linux-ssd-optimization

有些人在加入noatime參數時會連nodiratime參數也一併加入,這是不必要的,因為noatime參數已經包含了nodiratime參數的功能。

我們原先可以利用ls或是ll指令,加上-u參數,來查看檔案的上次存取時間。在加入noatime參數之後,檔案的上次存取時間就不會被更新了。

linux-ssd-optimization

啟用硬碟寫入快取(Write Caching)功能

Linux作業系統有內建硬碟寫入快取的功能,可以增加硬碟表面上的寫入速度,應該也可以減少硬碟的寫入次數。

hdparm指令工具可以取得或是設定SATA或是IDE裝置的參數。注意,它不能支援NVME硬碟。

Debian系的Linux發行版安裝hdparm的指令如下:

sudo apt install hdparm

紅帽系的Linux發行版安裝hdparm的指令如下:

sudo dnf install hdparm

hdparm指令的-W參數可以用來查看或臨時修改該裝置是否要開啟寫入快取功能,如下圖:

linux-ssd-optimization

如果要永久更改設定,比較推薦用發行版的桌面環境自帶的工具來設定。

linux-ssd-optimization

開啟寫入快取功能後要注意電腦不能隨便斷電,因為斷電很可能會造成檔案毀損。

/tmp掛在RAMDisk上

/tmp是Linux作業系統用來存放暫存檔案的目錄,是專門給程式讀寫檔案用的位置,使用者一般不需要將這個目錄裡的檔案保存下來。將/tmp掛在RAMDisk上,就可以直接把這些暫存檔存到記憶體中,不會寫入硬碟,而耗損硬碟的壽命,也能起到加速的作用。

紅帽系的Linux發行版似乎預設就會將/tmp掛在RAMDisk上,如果Debian系的Linux發行版也要這樣做的話,可以使用其自帶的systemd mount unit設定檔,用法如以下指令:

sudo cp /usr/share/systemd/tmp.mount /etc/systemd/system/ && sudo systemctl enable tmp.mount

清理「髒掉的」磁區

Linux常用的檔案系統為Ext4、Btrfs、XFS,它們都支援SSD的Trim功能,Trim可以使作業系統主動通知SSD哪些區塊(block)是不要的,SSD會在閒置的情況時將不要的區塊給擦除成0。為什麼要這樣做呢?因為SSD只能將資料寫入至完全淨空的Page中,如果沒有Trim,SSD在寫入資料前,不像HDD可以直接覆寫資料,它必須先擦除掉原先早已刪掉不要的的資料,而且SSD只能以區塊為單位,區塊為許多個pages組成,可能有64 pages或更多,SSD緩慢的擦除效率會連帶讓寫入效率下降,這也就是為什麼SSD用久了就愈慢的原因(變髒啦)。

就算檔案系統有支援,預設的情況下,Linux並不會開啟SSD的Trim功能,因為老實說它似乎並不是那麼的穩定,可能會有資料毀損的問題。

如果我們還是想要啟用SSD的Trim功能,可以選用以下兩種方式之一。

fstrim

fstrim是Linux作業系統自帶的指令工具,可以將檔案系統中沒有用到的區塊進行擦除的動作。搭配systemd來使用,可以實現自動每週一次進行完整擦除的功能。

Linux發行版大多會內建fstrim.timerfstrim.service這兩個systemd unit設定檔,且通常預設是啟用的。我們可以利用以下指令來判斷我們的fstrim.timer有無被啟用了:

sudo systemctl status fstrim.timer

linux-ssd-optimization

如果沒有啟用的話,可以用以下指令來永久啟用。

sudo systemctl enable fstrim.timer
sudo systemctl start fstrim.timer

如果想要立刻進行擦除的話,可以直接使用以下指令:

fstrim -av

discard

替檔案系統加上discard參數,可以在刪除檔案時就去觸發SSD的Trim功能。在絕大部分的情況下,這個作法都是不被推薦的,因為會讓SSD的壽命快速減少。

如下圖,便是直接在/etc/fstab設定檔的options欄位中加上discard參數。注意這邊有也替SWAP分割區加上discard參數哦!

linux-ssd-optimization

驗證Trim功能是否有成功擦除磁區

如何驗證Trim功能是否有成功擦除磁區?很簡單,就是查看被刪除的檔案原本在硬碟內的位置是不是已經被清空為0,可以使用以下方式來測試。

首先使用dd指令,建立一個亂數產生的檔案,檔名為magictest,檔案大小為512K x 100也就是50MiB。

dd if=/dev/urandom of=magictest count=100 bs=512K oflag=direct

linux-ssd-optimization

如果是SATA或是IDE硬碟,就可用hdparm指令查詢這個檔案在硬碟中的位置,實際上查到的是LBA(邏輯區塊位址, Logical Block Address),輸入以下指令:

sudo hdparm --fibmap magictest

linux-ssd-optimization

記下第一行,byte_offset0begin_LBA,這就是magictest這個檔案的開始位址。

如果您還不知道自己的SSD裝置是在哪個路徑下,可以用以下指令查看。

df .

linux-ssd-optimization

接著輸入以下指令,查看指定位址下硬碟存放的內容。

sudo hdparm --read-sector LGA位址 硬碟路徑

以筆者的為例:

sudo hdparm --read-sector 307891200 /dev/sda

如果執行成功,應該會看到一堆以16進制表示的數值,這就是檔案內容了。

linux-ssd-optimization

接著輸入以下指令將magictest檔案刪除:

rm magictest

如果您並不是使用discard參數的方式來使用Trim功能,那麼在刪除magictest檔案檔案之後要手動執行一次fstrim

因為Linux作業系統可能會使用記憶體來暫存實際硬碟的資料,需要使用以下指令來建議Linux作業系統將所有更變寫入至硬碟:

sync

linux-ssd-optimization

接著再一次使用相同的hdparm指令查看剛才的LBA位址下的檔案內容。

linux-ssd-optimization

如果Trim開啟成功,應該會顯示出一堆0。如果沒有的話也不必擔心,可能是SSD尚未執行Trim功能,也可能是SSD已經執行Trim功能了,但這塊空間又在短時間內被其他檔案佔用,所以可以重做幾遍看看。