盡量減少 PostgreSQL 中的記憶體未命中?
您可以按照此處所述計算記憶體未命中。
但是,我感興趣的是如何在 x86_64-unknown-linux-gnu 上最小化 PostgreSQL 9.4.3 中的現象,由 gcc (Debian 4.9.2-10) 4.9.2,64 位編譯。我有一些基於雜湊表的算法,它們通過隨機訪問導致大量記憶體未命中。我對如何最大限度地減少 PostgreSQL 中的記憶體未命中感興趣。
如何通過設計最大限度地減少 PostgreSQL 中的記憶體未命中?
使用 PostgreSQL 保持記憶體是在您可以擁有的
shared_buffers
內容和您在文件系統記憶體中擁有的內容之間取得平衡,並避免兩者都被其他程序推出。你可以在 PostgreSQL 9.4 上做的第一件事是
huge_pages=on
在你的postgresql.conf
.這還涉及進行一些作業系統更改以允許 PostgreSQL 在啟用此功能的情況下啟動。適當的 sysctl 變數是
vm.nr_hugepages
vm.nr_hugepages
您可以使用以下 shell 腳本對您應該設置的內容進行快速而骯髒的計算。
echo $(grep ^VmPeak /proc/$(cat /var/run/postgresql/9.4-main.pid)/status | sed -e 's/VmPeak://' | sed -e 's/kB//' | sed -e 's/[ \t]//g')/$(grep Hugepagesize /proc/meminfo | sed -e 's/Hugepagesize://' | sed -e 's/kB//' | sed -e 's/[ \t]//g') | bc -l | awk '{print int($1+1)}'
這一行從執行的 PostgreSQL 程序中獲取 VmPeak
/proc/$pid/status
,它告訴您 PostgreSQL 程序的峰值虛擬記憶體大小。這個數字以 kB 為單位。它清理間距和額外輸出,然後獲取Hugepagesize
from的測量值/proc/memstat
(在我的情況下為 2048 kB),然後進行適當的除法,將輸出四捨五入為最接近的整數,然後為安全餘量加一。就我而言,它是 2147。
通過執行以下操作使其永久化:
echo "vm.nr_hugepages=2147" >>/etc/sysctl.d/postgresql.conf
這很重要,原因如下,摘自文件:
/proc/sys/vm/nr_hugepages 表示核心大頁面池中“持久”大頁面的目前數量。當任務釋放時,“持久”大頁面將返回到大頁面池。具有 root 權限的使用者可以通過增加或減少“nr_hugepages”的值來動態分配更多或釋放一些持久性大頁面。
用作大頁面的頁面保留在核心內部,不能用於其他目的。在記憶體壓力下無法換出大頁面。
因此,postgres 程序為 shared_buffers 抓取的頁面不會在記憶體壓力下被換出。而且您的處理器的 TLB 壓力也會更小。
之後,我們調整了 OOMKiller,因為隨機謀殺 postgres 程序的東西不是一個好公民。這些設置強烈鼓勵它不要觸發。
echo "vm.overcommit_memory=2" >>/etc/sysctl.d/postgresql.conf
echo "vm.overcommit_ratio=100" >>/etc/sysctl.d/postgresql.conf
接下來我們設置幾個核心調度器 sysctl:
echo "kernel.sched_autogroup_enabled=0" >>/etc/sysctl.d/postgresql.conf
echo "kernel.sched_migration_cost=5000000" >>/etc/sysctl.d/postgresql.conf
遷移成本是調度程序將考慮遷移程序“記憶體熱”的總時間,因此不太可能重新遷移。
啟用自動組基本上是通過 setsid() 對任務進行分組,因此提高了感知響應能力。但是在伺服器系統上,像 PostgreSQL 這樣的大型守護程序將從同一個 setsid() 啟動,並有效地阻塞 CPU 週期以支持不太重要的任務。
之後,我們可以調整swappiness,這是一個控制系統從物理記憶體中交換程序的程度的旋鈕。較大的數字會更積極地換出,而較小的數字會使文件系統記憶體中的內容更長。將此設置為零將增加在記憶體和 I/O 壓力下 OOM 殺死的機會。
echo "vm.swappiness=10" >>/etc/sysctl.d/postgresql.conf
這些控制臟數據從文件系統記憶體同步回磁碟的頻率。由於無法釋放頁面記憶體中的髒對象,因此更積極地回寫可以保持更多頁面可供使用,並有助於避免大量磁碟 IO 突發。
echo "vm.dirty_ratio=2" >>/etc/sysctl.d/postgresql.conf
echo "vm.dirty_background_ratio=1" >>/etc/sysctl.d/postgresql.conf
由於您的 PostgreSQL 版本輸出顯示 GCC 4.9,我假設您正在執行 Debian Jessie 或衍生產品,因此 3.16 核心將避免 3.2 核心所具有的一些真正可怕的 I/O 問題,所以這肯定是個好消息。
調整所有這些設置後,重新啟動系統。這將有助於確保巨頁在分配時不會碎片化。最好和最可靠的方法是將
hugepages=2147
(我在伺服器上需要的數字)放在/etc/default/grub
underGRUB_CMDLINE_LINUX
和 runupdate-grub
中,然後重新啟動。但我會測試這樣做的必要性,因為它比 sysctl.xml 更難更改。這些應該在文件系統記憶體和
shared_buffers
. 在此之後,確保在您的伺服器上執行的程序數量最少(因為它們都在競爭資源),應該會為您提供您正在尋找的大部分頁面記憶體未命中最小化。大頁面的進一步閱讀及其效果在hugetlbpage 文件中。
vm 設置及其效果在vm 文件中。
這是對 Linux 記憶體系統理解和優化記憶體使用率的一個非常平易近人的處理
PostgreSQL 文件在核心資源頁面底部詳細介紹了大頁面的影響
希望有幫助。=)