Làm thế nào để giải quyết vấn đề bộ nhớ này một cách duyên dáng?


10

Tôi có một máy tính xách tay Linux (kiểm tra Debian) tiêu chuẩn, có phân vùng trao đổi.

Tôi làm rất nhiều thí nghiệm với nó. Một số người trong số họ thực sự đói bộ nhớ và cách Linux hành xử theo mặc định là một vấn đề đối với tôi ... Hãy đưa ra một ví dụ ngu ngốc:

  1. Ngồi trước máy tính xách tay
  2. Mở một thiết bị đầu cuối
  3. python, rồia = [0]*100000000

Bây giờ rất có thể bạn sẽ không có đủ RAM để xử lý danh sách lớn đó. Linux sẽ lấp đầy RAM, sau đó trao đổi và vài phút sau, kẻ giết người OOM sẽ được kích hoạt và giết (gần như) các dịch vụ ngẫu nhiên và hy vọng, nếu bạn nhấn Ctrl + C vào thời điểm tốt pythonvà nếu thiết bị đầu cuối vẫn tập trung, máy tính sẽ trở lại phản hồi.

Tôi muốn thực thi một số giới hạn bộ nhớ để tránh việc hoán đổi không mong muốn đó và từ chối xử lý quyền phân bổ nhiều bộ nhớ hơn mức tôi có (trong RAM). Nếu nhu cầu bộ nhớ dưới một giới hạn nhất định hoặc được yêu cầu bởi root, thì chỉ cần giết quá trình đói bộ nhớ nhất của bất kỳ người dùng nào ngoại trừ root.

ulimit -Sv [mem] Tôi nghe thấy ở phía sau!

Hồ Hồ! "Sử dụng cgroupsthông qua cgexec!" ai đó nói ở hàng đầu tiên!

Vâng, bạn đã đúng: đây thực sự là những giải pháp rất tốt. Nhưng:

  • Họ không áp dụng toàn hệ thống
  • Các giới hạn được đặt cho mỗi quy trình
  • Các giới hạn là tĩnh, không tính đến số lượng thực RAM miễn phí (AFAIK)
  • Ở đâyđó , họ nói rằng đây không thực sự là một giải pháp tốt để thực thi các giới hạn cứng.

Điều tôi muốn là kernel nói: "Bạn thuộc về người dùng foo (không phải root), bạn sử dụng rất nhiều bộ nhớ và chúng tôi sẽ hết bộ nhớ. Xin lỗi anh bạn ... chết ngay bây giờ!"

Hoặc: "Bạn đang làm cái quái gì vậy? Bạn cần x MB và chỉ có y MB. Có, SWAP trống, nhưng bạn không có ý định sử dụng SWAP để thực hiện công việc bẩn thỉu của mình, phải không? nói không! Không có ký ức cho bạn! Nếu bạn khăng khăng, bạn sẽ chết! "


2
Đã có một thuật toán được mô tả trong bài viết này giúp kẻ giết người OOM chọn đúng quy trình. Thay đổi /proc/sys/vm/overcommit_memoryảnh hưởng đến hành vi kernel trên bộ nhớ thấp.
jofel

1
Có, nhưng overcommit_memorytệp đặc biệt sử dụng RAM + SWAP làm bộ nhớ có thể sử dụng. Tôi vẫn sẽ trao đổi :)

1
Bạn cũng cần giải thích làm thế nào đây không phải là một bản sao của điều này: unix.stackexchange.com/questions 432334 /. Điều này mâu thuẫn với các nhóm WRT và người dùng cá nhân của bạn. Tái bút Nếu bạn không muốn trao đổi, hãy tắt trao đổi .
goldilocks

1
Tôi muốn trao đổi! Tôi muốn ngủ đông, tôi muốn các byte không sử dụng được lưu trữ! Nhưng tôi không muốn sử dụng byte được lưu trữ ở đó. Về liên kết, ulimitslà một ý tưởng tồi như được hiển thị ở hầu hết mọi nơi vì nó là một giới hạn cho mỗi quy trình ... Tôi biết bạn biết :) Về cgroups, điều này chắc chắn tốt hơn nhưng thiếu một cái gì đó chung chung hơn: Tôi đang nói về máy tính xách tay của mình nhưng tôi cũng sở hữu một máy chủ "tính toán" mà chúng tôi là ba để chia sẻ. Nếu tôi thực thi các giới hạn người dùng như vậy, tôi sẽ bị giới hạn bởi trường hợp xấu nhất, phải không?

1
các nhóm được áp dụng cho bất kỳ quy trình nào bạn quyết định - đưa tất cả các quy trình của người dùng vào một nhóm riêng biệt và nó sẽ làm những gì bạn muốn.
peterph

Câu trả lời:


4

Ai đó đề nghị trong phiên điều trần của bạn cgroups. Chà, cố gắng tìm kiếm hướng đó vì nó có thể cung cấp cho bạn:

  • áp dụng cho một nhóm tác vụ bạn chọn (do đó không phải toàn hệ thống nhưng không phải cho mỗi quy trình)
  • các giới hạn được đặt cho nhóm
  • các giới hạn là tĩnh
  • họ có thể thực thi giới hạn cứng đối với bộ nhớ và / hoặc bộ nhớ + trao đổi

Một cái gì đó như thế có thể mang bạn đến gần hơn với mục tiêu của bạn :

group limited {
  memory {
    memory.limit_in_bytes = 50M;
    memory.memsw.limit_in_bytes = 50M;
  }
}

Điều này cho biết rằng các tác vụ trong nhóm này có thể chỉ sử dụng tối đa 50M bộ nhớ và 50M bộ nhớ + trao đổi, vì vậy khi bộ nhớ đầy, nó sẽ không trao đổi, nhưng nếu bộ nhớ không đầy và một số dữ liệu có thể được ánh xạ trao đổi, điều này có thể được cho phép.

Đây là một đoạn trích từ tài liệu bộ nhớ của cgroup :

Bằng cách sử dụng giới hạn memsw, bạn có thể tránh OOM hệ thống có thể gây ra do thiếu hụt hoán đổi.


Vẫn không chính xác những gì tôi đã mong đợi. Nhưng sự khác biệt giữa những gì tôi mong đợi và thực tế thường khá lớn :) Trong trường hợp này, tôi muốn chắc chắn rằng tôi đã không bỏ lỡ bất cứ điều gì như overcommit_memorybiến nhân. Cảm ơn tất cả.

0

Tôi gặp vấn đề tương tự thường xuyên. Quy trình công việc chung của tôi liên quan đến tính toán nặng nề trong MATLAB. Thỉnh thoảng tôi sẽ vô tình cố gắng phân bổ một biến mới vượt quá dung lượng bộ nhớ khả dụng. Hệ thống bị treo và tôi thường phải khởi động lại máy một cách khó khăn để hoạt động trở lại. : P

Trong trường hợp của tôi, và có vẻ như trong bạn cũng vậy, tôi không quá quan tâm đến việc giới hạn dung lượng bộ nhớ mà MATLAB sử dụng ở mức tĩnh - tôi quan tâm đến việc không có máy đông lạnh và tôi sẵn sàng hy sinh quy trình MATLAB của mình để bảo vệ hệ thống đáp ứng.

Lấy cảm hứng từ một phản hồi cho bài đăng này , tôi đã viết kịch bản sau đây (tôi gọi nó là watch_memory.sh):

#!/bin/bash

MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')

MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))

while :; do
    if [ "$MEM_PERC" -gt "95" ]
    then
        kill $1
        echo "$1 killed for using too much memory."
        exit
    fi
    sleep 1

    MONITOR=$(free | grep 'buffers/cache:')
    MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
    MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
    MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done

Kịch bản này kiểm tra mỗi giây cho phần trăm bộ nhớ trống. Khi hệ thống hết, pid "vật tế thần" của bạn (được truyền làm đối số cho tập lệnh) sẽ bị giết.

Không điều chỉnh mức độ ưu tiên (tính độc đáo) của tập lệnh, phải mất khoảng 10-20 giây để vật tế thần bị giết, nhưng nó vẫn hoạt động. Chạy tập lệnh có mức độ ưu tiên tiêu cực dẫn đến việc giết ngay lập tức sau khi vi phạm (11916 trong ví dụ này là mục đích tôi muốn giết nếu hết bộ nhớ):

sudo nice -n -5 bash watch_memory.sh 11916
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.