Làm thế nào một người có thể nhanh chóng rút tất cả bộ nhớ bị hoán đổi của quá trình ra khỏi trao đổi mà không ghi vào đĩa?
Bối cảnh về vấn đề này là tầm thường, vì vấn đề mang tính hệ thống đòi hỏi câu hỏi đang được xử lý bởi các bên khác. Tuy nhiên, ngay bây giờ, tôi có một vấn đề là tôi thường xuyên phải giải phóng không gian trao đổi trên một nút OpenVZ trong khi tải và chờ IO là cực kỳ cao.
Việc hoán đổi thường được tiêu thụ chủ yếu bởi một số ít các quy trình MySQL và clamd chạy trên các container riêng lẻ. Khởi động lại các dịch vụ này giải phóng trao đổi và giải quyết vấn đề trên nút, nhưng không mong muốn vì những lý do rõ ràng.
Tôi đang tìm cách để nhanh chóng giải phóng trao đổi khỏi các quy trình đó trong khi nút bị quá tải và cần một cái gì đó nhanh hơn phương thức hiện tại của tôi:
unswap(){ [[ $1 && $(ls /proc/$1/maps) ]] && ((gcore -o /tmp/deleteme $1 &>/dev/null; rm -fv /tmp/deleteme.$1)&) 2>/dev/null || echo "must provide valid pid";};unswap
Kết xuất lõi này buộc tất cả ram phải được truy cập và do đó thực hiện công việc rút nó ra khỏi trao đổi, nhưng tôi vẫn chưa tìm được cách nào để tránh việc ghi nó vào tập tin. Ngoài ra, có vẻ như quá trình sẽ nhanh hơn nếu tôi có thể cô lập phạm vi địa chỉ hiện đang hoán đổi và chỉ chuyển phần đó thành / dev / null, nhưng tôi vẫn chưa tìm ra cách để làm điều đó.
Đây là một nút rất lớn, vì vậy phương pháp hoán đổi / hoán đổi thông thường rất tốn thời gian và một lần nữa, cấu hình của nút không nằm trong tầm kiểm soát của tôi, vì vậy việc khắc phục nguyên nhân gốc không phải là một phần của câu hỏi này. Tuy nhiên, bất kỳ cái nhìn sâu sắc nào về cách tôi có thể giải phóng một phần đáng kể của trao đổi một cách nhanh chóng mà không giết / khởi động lại bất cứ điều gì sẽ được đánh giá cao.
Môi trường: CentOS 6.7 / OpenVZ
Cập nhật cho bất cứ ai có thể vấp ngã sau này:
Sử dụng đầu vào của Jlong, tôi đã tạo ra chức năng sau:
unswap(){ (awk -F'[ \t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>0{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;};
Nó hơi chậm, nhưng thực hiện chính xác những gì được yêu cầu ở đây. Có lẽ có thể cải thiện tốc độ bằng cách chỉ tìm phạm vi địa chỉ lớn nhất trong trao đổi và bỏ qua các lần lặp cho các khu vực nhỏ tầm thường, nhưng tiền đề là âm thanh.
Ví dụ làm việc:
#Find the process with the highest swap use
[~]# grep VmSwap /proc/*/status 2>/dev/null | sort -nk2 | tail -n1 | while read line; do fp=$(echo $line | cut -d: -f1); echo $line" "$(stat --format="%U" $fp)" "$(grep -oP "(?<=NameS).*" $fp); done | column -t
/proc/6225/status:VmSwap: 230700 kB root mysqld
#Dump the swapped address ranges and observe the swap use of the proc over time
[~]# unswap(){ (awk -F'[ t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>0{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;}; unswap 6225; while true; do grep VmSwap /proc/6225/status; sleep 1; done
VmSwap: 230700 kB
VmSwap: 230700 kB
VmSwap: 230676 kB
VmSwap: 229824 kB
VmSwap: 227564 kB
... 36 lines omitted for brevity ...
VmSwap: 9564 kB
VmSwap: 3212 kB
VmSwap: 1876 kB
VmSwap: 44 kB
VmSwap: 0 kB
Giải pháp cuối cùng cho việc bán phá giá hàng loạt chỉ là những khối lớn của bộ nhớ bị tráo đổi:
unswap(){ (awk -F'[ \t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>1000{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;}; grep VmSwap /proc/*/status 2>/dev/null | sort -nk2 | tail -n20 | cut -d/ -f3 | while read line; do unswap $line; done;echo "Dumps Free(m)"; rcount=10; while [[ $rcount -gt 0 ]]; do rcount=$(ps fauxww | grep "dump memory" | grep -v grep | wc -l); echo "$rcount $(free -m | awk '/Swap/{print $4}')"; sleep 1; done
Tôi vẫn chưa xác định liệu phương pháp này có gây rủi ro cho sức khỏe của quy trình hoặc hệ thống hay không, đặc biệt là khi lặp qua nhiều quy trình đồng thời. Nếu bất cứ ai có cái nhìn sâu sắc về bất kỳ hiệu ứng tiềm năng nào có thể có trên các quy trình hoặc hệ thống, xin vui lòng bình luận.
gdb
trường hợp song song nếu quá trình được hoán đổi có nhiều đoạn bị tráo đổi. Kịch bản sẽ khởi chạygdb
thể hiện song song cho mỗi đoạn được hoán đổi (lớn) cho 20 quy trình lớn nhất. Tôi nghĩ ít nhất người ta nên thêm| tail -n20
vào sauawk
khi chuyển kết quả vàowhile
vòng lặp để giới hạn các quy trình tương đương tối đa đến 400.