VM hypervisor使用內核相同內存頁合并(Kernel Same-page Merging, KSM)功能,再不同的KVM guest虛擬機中共享相同內存頁。這些共享頁面通常是 公共庫 (common libraries) 或者其他相同的高使用率數據。
KSM通過避免虛擬機之間的內存重復,可以減少每個虛擬機所使用的內存空間,從而提高虛擬機密度。具體來說,KSM可以將多個虛擬機之間的相同內存頁面合并為一個頁面,并在需要時進行復制,從而減少了每個虛擬機所需的內存空間,從而可以在相同的物理主機上運行更多的虛擬機。
"虛擬機密度"(Virtual Machine Density)是指在物理主機上可以同時運行多少個虛擬機的數量。通常情況下,虛擬機越多,虛擬化技術的效益就越高,因為可以更好地利用物理主機的資源。
KSM使用內核檢查兩個或者更多的已經運行的程序,并比校它們的內存。如果任何內存區域或者頁面相同,則KSM會將多個相同的內存頁面減少為一個頁面,隨后該頁面會標記為寫時復制。如果內存頁面的內容被guest虛擬機修改,則會為該guest創建一個新的頁面。
Red Hat在 qemu-kvm
軟件包中包含了 ksm
服務。當 ksm
沒有啟動時,KSM(Kernel same-page merging)只共享2000個內存頁。這個默認設置只能提供悠閑地內存節約。
當啟動 ksm
服務時,KSM將共享主機系統內存的一半,也就是說啟動 ksm
服務,能夠讓KSM共享更多內存
啟動 ksm
服務:
systemctl start ksm
激活 ksm
服務:
systemctl enable ksm
我們可以看下這個systemd的service內容
[root@master ~]# cat /usr/lib/systemd/system/ksm.service
[Unit]
Description=Kernel Samepage Merging
ConditionPathExists=/sys/kernel/mm/ksm
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/sysconfig/ksm
ExecStart=/usr/libexec/ksmctl start
ExecStop=/usr/libexec/ksmctl stop
[Install]
WantedBy=multi-user.target
ksm的運行情況記錄在/sys/kernel/mm/ksm
目錄下
[root@master ~]# ll /sys/kernel/mm/ksm
總用量 0
-r--r--r-- 1 root root 4096 4月 27 11:07 full_scans
-rw-r--r-- 1 root root 4096 4月 27 11:07 max_page_sharing
-rw-r--r-- 1 root root 4096 4月 27 11:07 merge_across_nodes
-r--r--r-- 1 root root 4096 4月 27 11:07 pages_shared
-r--r--r-- 1 root root 4096 4月 27 11:07 pages_sharing
-rw-r--r-- 1 root root 4096 4月 27 11:07 pages_to_scan
-r--r--r-- 1 root root 4096 4月 27 11:07 pages_unshared
-r--r--r-- 1 root root 4096 4月 27 11:07 pages_volatile
-rw-r--r-- 1 root root 4096 4月 27 16:48 run
-rw-r--r-- 1 root root 4096 4月 27 11:07 sleep_millisecs
-r--r--r-- 1 root root 4096 4月 27 11:07 stable_node_chains
-rw-r--r-- 1 root root 4096 4月 27 11:07 stable_node_chains_prune_millisecs
-r--r--r-- 1 root root 4096 4月 27 11:07 stable_node_dups
full_scans :文件表明已經執行的全區域掃描的次數。
max_page_sharing: 單個KSM頁面允許的最大共享站點數。這將強制執行重復數據消除限制,以避免涉 及遍歷共享KSM頁面的虛擬映射的虛擬內存操作的高延遲。最小值為2,因為新創 建的KSM頁面將至少有兩個共享者。該值越高,KSM合并內存的速度越快,去重 因子也越高,但是對于任何給定的KSM頁面,虛擬映射的最壞情況遍歷的速度也會 越慢。減慢了這種遍歷速度就意味著在交換、壓縮、NUMA平衡和頁面遷移期間, 某些虛擬內存操作將有更高的延遲,從而降低這些虛擬內存操作調用者的響應能力。 其他任務如果不涉及執行虛擬映射遍歷的VM操作,其任務調度延遲不受此參數的影 響,因為這些遍歷本身是調度友好的。
merge_across_nodes: 指定是否可以合并來自不同NUMA節點的頁面。當設置為0時,ksm僅合并在物理上位 于同一NUMA節點的內存區域中的頁面。這降低了訪問共享頁面的延遲。在有明顯的 NUMA距離上,具有更多節點的系統可能受益于設置該值為0時的更低延遲。而對于 需要對內存使用量最小化的較小系統來說,設置該值為1(默認設置)則可能會受 益于更大共享頁面。在決定使用哪種設置之前,您可能希望比較系統在每種設置下 的性能。 merge_across_nodes
僅當系統中沒有ksm共享頁面時,才能被更改設 置:首先將接口run
設置為2從而對頁進行去合并,然后在修改 merge_across_nodes
后再將‘run’又設置為1,以根據新設置來重新合并。
pages_shared:表示多少共享頁正在被使用
pages_sharing:表示還有多少站點正在共享這些共享頁,即節省了多少
pages_unshared:顯示 KSM 目前未共享的頁面數。
pages_volatile:表示有多少頁因變化太快而無法放在tree中
run :默認值:0(必須設置為1才能激活KSM,除非禁用了CONFIG_SYSFS)
echo 1 > /sys/kernel/mm/ksm/run
,sleep_millisecs :ksmd在下次掃描前應休眠多少毫秒。
stable_node_chains:達到 max_page_sharing
限制的KSM頁數。
stable_node_chains_prune_millisecs:指定KSM檢查特定頁面的元數據的頻率(即那些達到過時信息數據去重限制標準的 頁面)單位是毫秒。較小的毫秒值將以更低的延遲來釋放KSM元數據,但它們將使 ksmd在掃描期間使用更多CPU。如果還沒有一個KSM頁面達到 max_page_sharing
標準,那就沒有什么用。
stable_node_dups:重復的KSM頁數
只有pages_to_scan、sleep_millisecs、run這三個文件對root用戶是可讀可寫的
general_profit=~ pages_sharing * sizeof(page) - (all_rmap_items) * sizeof(rmap_item);
pages_sharing
表示共享的頁面數sizeof(page)
表示每個頁面占用的空間大小all_rmap_items
表示正在使用該頁面的進程個數(對 pages_sharing
、 pages_shared
、 pages_unshared
和 pages_volatile
的求和)sizeof(rmap_item)
表示每個進程占用的 rmap 數據結構大小process_profit=~ ksm_merging_pages * sizeof(page) - ksm_rmap_items * sizeof(rmap_item).
ksm_merging_pages顯示在 /proc/<pid>/
目錄下,而ksm_rmap_items 顯示在 /proc/<pid>/ksm_stat
pages_sharing的值越大,說明KSM節省的內存越多,KSM的效果越好。如下命令也可以計算節省的內存數量
echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024))MB"
在QEMU/KVM中,一個虛擬機客戶端就是一個QEMU進程,所以使用KSM也可以實現多個客戶機之間的相同內存合并。而且,如果同一宿主機上的多個客戶機運行的是相同的操作系統或者應用程序,則客戶機之間相同內存頁的數量就可能比較大,這種情況下KSM的作用會更加明顯,在KVM環境下使用KSM,還允許KVM請求哪些相同的內存頁是可以被共享而合并的,所以KSM只會識別并合并那些不會干擾客戶機運行且不會影響宿主機或客戶機運行的安全內存頁。可見,在KVM虛擬環境當中,KSM能夠提高內存的速度和使用效率,具體可以通過下述兩個方面來理解:
我們簡單來測下QEMU/KVM下,KSM所帶來的效果,這是我們的測試腳本,在腳本開始的位置,我們關閉了ksm,然后創建了四臺8G的windows虛擬機,之后打印當前的內存情況,開啟ksm和ksmtuned,等待十分鐘,再查看內存情況
[root@localhost kvm]# cat ksm-test.sh
#!/bin/bash
# file: ksm-test.sh
echo "echo ----stoping service: ksm and ksmtuned"
systemctl stop ksm
systemctl stop ksmtuned
echo "----'free -m -h' command output before starting any guest"
free -m -h
# start 4 Linux guest
for i in $(seq 1 4)
do
let "vnc_port=${i}+10"
/usr/libexec/qemu-kvm -enable-kvm -m 8G -smp 4 -drive file=/home/images/windows10.raw,format=raw,if=virtio -device virtio-net-pci,netdev=net0 -netdev tap,id=net0 -usb -usbdevice tablet -snapshot -name windows10_${i} -vnc 0.0.0.0:${vnc_port} -daemonize
echo "starting the No.${i} guest...."
sleep 5
done
echo "----Wait 2 minutes for guest bootup ..."
sleep 120
echo "--- 'free -m -h' command output with serveral guests running ."
free -m -h
echo "staring service: ksm and ksmtuned ..."
systemctl start ksm
systemctl start ksmtuned
echo "----Wait 10 minutes for KSM to take effect ..."
sleep 600
echo "----'free -m -h' command output with ksm and ksmtuned running."
free -m -h
[root@localhost kvm]# sh ksm-test.sh
echo ----stoping service: ksm and ksmtuned
----'free -m -h' command output before starting any guest
total used free shared buff/cache available
Mem: 125G 5.6G 75G 10M 44G 119G
Swap: 4.0G 0B 4.0G
starting the No.1 guest....
starting the No.2 guest....
starting the No.3 guest....
starting the No.4 guest....
----Wait 2 minutes for guest bootup ...
--- 'free -m -h' command output with serveral guests running .
total used free shared buff/cache available
Mem: 125G 37G 42G 10M 45G 87G
Swap: 4.0G 0B 4.0G
staring service: ksm and ksmtuned ...
----Wait 10 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
total used free shared buff/cache available
Mem: 125G 37G 26G 10M 61G 87G
Swap: 4.0G 5.8M 4.0G
可以看到此時開啟ksmtuned并沒有讓內存降下來,空閑內存更是從42G掉到了26G,我們查看一下ksm的日志
[root@localhost kvm]# cat /var/log/ksmtuned
Sat Apr 29 13:28:29 EDT 2023: committed 38147384 free 90883040
Sat Apr 29 13:28:29 EDT 2023: 64498382 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:29:29 EDT 2023: committed 38147244 free 90894920
Sat Apr 29 13:29:29 EDT 2023: 64498242 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:30:29 EDT 2023: committed 38147496 free 90896352
Sat Apr 29 13:30:29 EDT 2023: 64498494 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:31:29 EDT 2023: committed 38147516 free 90893164
Sat Apr 29 13:31:29 EDT 2023: 64498514 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:32:30 EDT 2023: committed 38141272 free 90898188
Sat Apr 29 13:32:30 EDT 2023: 64492270 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:33:30 EDT 2023: committed 38141252 free 90894708
Sat Apr 29 13:33:30 EDT 2023: 64492250 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:34:30 EDT 2023: committed 38141160 free 90894016
Sat Apr 29 13:34:30 EDT 2023: 64492158 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:35:30 EDT 2023: committed 38141160 free 90894080
Sat Apr 29 13:35:30 EDT 2023: 64492158 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:36:30 EDT 2023: committed 38137940 free 90547068
Sat Apr 29 13:36:30 EDT 2023: 64488938 < 131754992 and free > 26350998, stop ksm
Sat Apr 29 13:37:31 EDT 2023: committed 38137860 free 90529460
Sat Apr 29 13:37:31 EDT 2023: 64488858 < 131754992 and free > 26350998, stop ksm
需要開啟ksmtuned的debug模式和日志記錄
[root@localhost kvm]# cat /etc/ksmtuned.conf
# Configuration file for ksmtuned.
# How long ksmtuned should sleep between tuning adjustments
# KSM_MONITOR_INTERVAL=60
# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# KSM_SLEEP_MSEC=10
# KSM_NPAGES_BOOST=300
# KSM_NPAGES_DECAY=-50
# KSM_NPAGES_MIN=64
# KSM_NPAGES_MAX=1250
# KSM_THRES_COEF=20
# KSM_THRES_CONST=2048
# uncomment the following if you want ksmtuned debug info
LOGFILE=/var/log/ksmtuned
DEBUG=1
通過日志我們可以看到此時的內存還未達到ksmtuned啟動ksm的條件,我們需要改一下KSM_THRES_COEF,重新執行一下腳本(啟動腳本之前先停掉ksmtuned ksm)
[root@localhost kvm]# systemctl stop ksmtuned ksm
[root@localhost kvm]# cat /etc/ksmtuned.conf
# Configuration file for ksmtuned.
# How long ksmtuned should sleep between tuning adjustments
# KSM_MONITOR_INTERVAL=60
# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# KSM_SLEEP_MSEC=10
# KSM_NPAGES_BOOST=300
# KSM_NPAGES_DECAY=-50
# KSM_NPAGES_MIN=64
# KSM_NPAGES_MAX=1250
KSM_THRES_COEF=95
# KSM_THRES_CONST=2048
# uncomment the following if you want ksmtuned debug info
LOGFILE=/var/log/ksmtuned
DEBUG=1
執行測試腳本
[root@localhost kvm]# sh ksm-test.sh
echo ----stoping service: ksm and ksmtuned
----'free -m -h' command output before starting any guest
total used free shared buff/cache available
Mem: 125G 5.4G 77G 10M 43G 119G
Swap: 4.0G 2.3M 4.0G
starting the No.1 guest....
starting the No.2 guest....
starting the No.3 guest....
starting the No.4 guest....
----Wait 2 minutes for guest bootup ...
--- 'free -m -h' command output with serveral guests running .
total used free shared buff/cache available
Mem: 125G 37G 44G 10M 43G 87G
Swap: 4.0G 2.3M 4.0G
staring service: ksm and ksmtuned ...
----Wait 10 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
total used free shared buff/cache available
Mem: 125G 11G 52G 10M 61G 113G
Swap: 4.0G 2.3M 4.0G
從實驗數據上來看,啟動KVM虛擬機之前可用內存從119G下降到了87G(4*8G等于32G),這個沒問題。
在啟動ksm 和 ksmtuned 之后,可用內存從87G上升到了113G,節省了26G的內存空間,我們可以通過之前的計算公式打印出來。
[root@localhost kvm]# echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024))MB"
KSM saved: 26983MB
可以看到,計算得出的數據也與上述描述的結果符合。
qemu對KSM的控制默認是打開的,在我們的啟動命令當中,可以加入-M或者是-machine參數的mem-merge=on/off來控制,也就是是否允許內存合并(默認是開啟的)。
感興趣的朋友可以試一下加上-machine pc,mem-merge=off,重新執行腳本測試一下。
撰文:Groot
雖然鏈上的高度透明奠定了區塊鏈世界的信任基礎,但是隨著行業的快速發展,完全公開的數據難免引發了一些別有用心的「作惡者」的關注,在傳統互聯網行業中至今仍然沒有得到有效解決的隱私問題,正在區塊鏈世界中「復現」,并且也已經成為了 Web3 世界進一步發展必須要面對和解決的痛點。
Manta Network 是波卡首個鏈上隱私保護項目,通過密碼學技術 zkSNARK 為 DeFi 用戶提供鏈上隱私保護,旨在成為整個去中心化金融的隱私保護基礎設施。Manta 基于 Substrate 框架,可以為整個波卡生態提供即插即用的隱私保護服務。Manta 的創始團隊包括來自哈佛大學、麻省理工學院、Algorand 等背景的密碼學家、教授和加密貨幣資深人士,并得到了全球頂級投資機構的支持,在今年年初完成了由 Polychain 領投,三箭資本、Multicoin、Alameda、Hypersphere 等參與的種子輪融資。
Calamari 作為 Manta Network 的先行網絡,除了能夠為 Manta 上線新功能前提供測試和驗證的場景,也能夠為整個 Kusama 生態帶來類似的隱私保護功能。
Calamari Network 作為 Manta Network 的社區化先行網,是在 Kusama 上即插即用的隱私保護平行鏈,旨在為整個 Kusama 的 DeFi 網絡提供隱私服務。
Calamari 可以在滿足用戶鏈上隱私需求、抗審查需求的同時,保證系統內的隱私代幣在去中心化及互操作性等方面不受「干擾」的平臺。
Calamari 目前已經推出的產品包括隱私支付 MariPay 和隱私去中心化 AMM 交易平臺 MariSwap,其中 MariPay 支持 Kusama 及其平行鏈資產的隱私交易,用戶可以將封裝后的穩定幣、比特幣等主流資產隱私化,Calamari 的零知識證明技術會為這類封裝資產提供鏈上隱私保護。
MariSwap 可以為用戶提供隱私地址的平行鏈資產間交易功能,此外還推出了包括隱私流動性池等一列隱私保護相關的創新功能。
Calamari 的代幣 KMA 是首個社區主導的通縮型隱私功能性代幣,持幣用戶可以在協議的成長過程中獲得分紅激勵,比如前文提及的 MariPay 以及 MariSwap 產品使用中產生費用中的一部分就會用于回饋代幣持有者,此外 KMA 還承擔著生態內投票治理的憑證身份。
KMA 的初始發行總量為 100 億枚,在用于平行鏈插槽拍賣的儲備代幣消耗殆盡之前不會增發。KMA 的分配方式以社區為導向,會以公平分配的方式優先向早期參與者分發,團隊并不會預留代幣。
具體比例上來看,其中會有 30% 的代幣用于平行鏈插槽拍賣激勵,10% 用于平行鏈插槽拍賣儲備,20% 預留給流動性挖礦激勵,5% 用于市場營銷,15% 預留給開發基金,剩余 20% 用于鎖倉空投。
Calamari 將從第 6 個插槽,也就是即將在 9 月 1 日開啟的第二輪 Kusama 平行鏈插槽拍賣中正式參與競拍,將拍賣 8 個周期(48 周)的插槽。
持有 KSM 的用戶已經可以通過 Calamari 網站 參與眾貸,操作教程參考 此處 。
在眾貸活動中每投入一枚 KSM 可以獲得 10000 枚 KMA 代幣的獎勵,這也就保證了用戶收獲的代幣獎勵并不會因參與眾貸支持 Calamari 總資金量上升而下降。Calamari 計劃提供至多 30 億枚 KMA 代幣用于激勵幫助項目進行插槽競拍的 KSM 貢獻者,也就是說眾貸參與硬頂為 30 萬枚 KSM。
Calamari 在拍賣過程中將使用階梯硬頂的方式,第一個硬頂為最多 10 億 KMA 分給 KSM 貢獻者,也就意味著第一次的硬頂為籌集 10 萬枚 KSM。在籌集每一個硬頂過程中如果 Calamari 獲得了平行鏈插槽,則會提前結束眾籌,計劃中預留的 30 億枚代幣中剩余部分將會存入項目金庫用于租期結束后未來的插槽拍賣。如當達到第一個硬頂之后有更高競拍者獲得了插槽,則會開啟第二個硬頂,共計將 20 億 KMA 分給 KSM 貢獻者,也就意味著第二次的硬頂為籌集 20 萬枚 KSM,以此類推。
對于 KSM 貢獻者來說,除基礎獎勵以外,前 500 名 KSM 貢獻者會獲得額外 10% 的代幣獎勵,501-1000 名貢獻者會得到額外 5% 的代幣獎勵。而通過額外的邀請功能,邀請及被邀請雙方還會分別收到額外 2.5% 的代幣獎勵。
眾貸參與者投入的 KSM 會在拍賣開始后被鎖定,直至贏得插槽并且完整的租賃周期 48 周結束后才會解鎖。一旦 Calamari 順利贏得平行鏈插槽并開始正式運行,將會有 34% 的 KMA 獎勵一次性釋放給眾貸參與者,剩余 66% 的代幣會在未來每 8 周分 6 次釋放,每次釋放 11%。
Calamari 就像它的名字「魷魚」一樣具備很強的「偽裝」能力,這也表達出了該項目旨在保護用戶數據免遭濫用且避免被勒索者入侵攻擊的初衷。除此以外,Calamari 同樣具備 Kusama 先行網絡的探索創新精神,能夠依托項目更輕便快速的迭代,不斷地為 Manta 提供最優的創新功能及產品升級解決方案。