TL; DR
Tạm thời ngắn / trả lời
- Dễ nhất : Có một phân vùng trao đổi nhỏ hơn và tránh hạt nhân cố gắng sống theo lời nói dối rằng không có giới hạn bộ nhớ bằng cách chạy các quy trình từ lưu trữ chậm.
- Với một sự hoán đổi lớn, OOM (người quản lý hết bộ nhớ) sẽ không sớm hành động. Thông thường, nó chiếm tài khoản theo bộ nhớ ảo và, theo kinh nghiệm trước đây của tôi, đã không giết chết mọi thứ cho đến khi toàn bộ trao đổi được lấp đầy, do đó hệ thống đập và bò ...
- Cần một trao đổi lớn cho ngủ đông?
- Đã thử / có vấn đề : Đặt một số lỗ hổng (ví dụ: kiểm tra
ulimit -v
và có thể đặt giới hạn cứng hoặc mềm bằng as
tùy chọn trong limits.conf
). Điều này được sử dụng để hoạt động đủ tốt, nhưng nhờ giới thiệu WebKit gigacage
, nhiều ứng dụng gnome hiện mong đợi không gian địa chỉ không giới hạn và không chạy được!
- Cố / vấn đề : Chính sách overcommit và tỷ lệ là một cách khác để cố gắng quản lý và giảm thiểu này (ví dụ
sysctl vm.overcommit_memory
, sysctl vm.overcommit_ratio
nhưng phương pháp này không làm việc ra cho tôi.
- Khó / phức tạp : Hãy thử áp dụng mức độ ưu tiên của nhóm cho các quy trình quan trọng nhất (ví dụ: ssh), nhưng điều này hiện có vẻ rườm rà đối với cgroup v1 (hy vọng v2 sẽ giúp việc này dễ dàng hơn) ...
Tôi cũng tìm thấy:
Giải pháp dài hạn
chờ đợi và hy vọng cho một số bản vá ngược dòng để có được vào hạt nhân distro ổn định. Cũng hy vọng rằng các nhà cung cấp phân phối điều chỉnh tốt hơn mặc định kernel và tận dụng tốt hơn các nhóm hệ thống để ưu tiên đáp ứng GUI trong các phiên bản máy tính để bàn.
Một số bản vá quan tâm:
Vì vậy, nó không chỉ là mã không gian người dùng xấu và distro config / mặc định đó là lỗi - kernel có thể xử lý việc này tốt hơn.
Nhận xét về các lựa chọn đã được xem xét
1) Vô hiệu hóa trao đổi
Cung cấp ít nhất một phân vùng trao đổi nhỏ được khuyến nghị ( Chúng ta có thực sự cần trao đổi trên các hệ thống hiện đại không? ). Vô hiệu hóa trao đổi không chỉ ngăn chặn trao đổi ra các trang không sử dụng, nhưng nó cũng có thể ảnh hưởng đến chiến lược overcommit heuristic, mặc định của kernel cho việc cấp phát bộ nhớ ( gì heuristics trong Overcommit_memory = 0 nghĩa là gì? ), Như dựa trên kinh nghiệm mà không đếm trên các trang trao đổi. Không có hoán đổi, overcommit vẫn có thể hoạt động ở chế độ heuristic (0) hoặc luôn luôn (1), nhưng sự kết hợp giữa không trao đổi và chiến lược overcommit không bao giờ (2) có thể là một ý tưởng tồi. Vì vậy, trong hầu hết các trường hợp, không có trao đổi sẽ có khả năng làm tổn thương hiệu suất.
Ví dụ, hãy nghĩ về một quá trình chạy dài ban đầu chạm vào bộ nhớ để làm việc một lần, nhưng sau đó không giải phóng bộ nhớ đó và tiếp tục chạy nền. Nhân sẽ phải sử dụng RAM cho đến khi quá trình kết thúc. Nếu không có bất kỳ sự hoán đổi nào, kernel không thể đưa nó ra một thứ khác thực sự muốn chủ động sử dụng RAM. Ngoài ra, hãy suy nghĩ về việc có bao nhiêu nhà phát triển lười biếng và không giải phóng bộ nhớ sau khi sử dụng.
3) thiết lập một ulimit bộ nhớ tối đa
Nó chỉ áp dụng cho mỗi quy trình và có lẽ đó là một giả định hợp lý rằng một quy trình không nên yêu cầu thêm bộ nhớ mà hệ thống có! Vì vậy, nó có thể hữu ích để ngăn chặn một quá trình điên rồ đơn độc kích hoạt đập trong khi vẫn được thiết lập rộng rãi.
4) giữ các chương trình quan trọng (X11, bash, kill, top, ...) trong bộ nhớ và không bao giờ trao đổi các chương trình đó
Ý tưởng hay, nhưng sau đó những chương trình đó sẽ khiến bộ nhớ họ không tích cực sử dụng. Nó có thể được chấp nhận nếu chương trình chỉ yêu cầu một lượng bộ nhớ khiêm tốn.
Bản phát hành systemd 232 vừa bổ sung một số tùy chọn giúp thực hiện điều này: Tôi nghĩ rằng người ta có thể sử dụng 'MemorySwapMax = 0' để ngăn chặn một đơn vị (dịch vụ) như ssh bị tráo đổi bộ nhớ.
Tuy nhiên, có thể ưu tiên truy cập bộ nhớ sẽ tốt hơn.
Giải thích dài
Hạt nhân linux được điều chỉnh nhiều hơn cho khối lượng công việc của máy chủ, do đó, khả năng đáp ứng GUI đáng lo ngại là mối quan tâm thứ yếu ... Các cài đặt quản lý bộ nhớ kernel trên phiên bản Desktop của Ubuntu 16.04 LTS dường như không khác với các phiên bản máy chủ khác. Nó thậm chí phù hợp với các mặc định trong RHEL / CentOS 7.2 thường được sử dụng làm máy chủ.
OOM, ulimit và đánh đổi tính toàn vẹn để đáp ứng
Hoán đổi trao đổi (khi bộ nhớ hoạt động, tức là các trang được đọc và ghi vào khung thời gian ngắn nhất định vượt quá RAM vật lý) sẽ luôn khóa I / O lưu trữ - không có thuật sĩ hạt nhân nào có thể lưu hệ thống khỏi điều này mà không làm hỏng quá trình hoặc hai...
Tôi hy vọng các tinh chỉnh OOM của Linux xuất hiện trong các hạt nhân gần đây hơn nhận ra bộ công việc này vượt quá tình trạng bộ nhớ vật lý và giết chết một tiến trình. Khi nó không xảy ra, vấn đề đập xảy ra. Vấn đề là, với một phân vùng trao đổi lớn, nó có thể trông như thể hệ thống vẫn có khoảng trống trong khi hạt nhân vui vẻ hơn và vẫn phục vụ các yêu cầu bộ nhớ, nhưng bộ làm việc có thể tràn vào trao đổi, cố gắng xử lý lưu trữ như thể đó là RAM.
Trên các máy chủ, nó chấp nhận hình phạt hiệu suất của việc đập để xác định, chậm, không mất dữ liệu, đánh đổi. Trên máy tính để bàn, sự đánh đổi là khác nhau và người dùng sẽ thích một chút mất dữ liệu (hy sinh quá trình) để giữ cho mọi thứ được đáp ứng.
Đây là một sự tương đồng hài hước về OOM : oom_pardon, aka đừng giết xlock của tôi
Ngẫu nhiên, OOMScoreAdjust
là một tùy chọn systemd khác để giúp cân và tránh các quá trình tiêu diệt OOM được coi là quan trọng hơn.
đệm viết
Tôi nghĩ rằng " Làm cho nền ghi không bị mất " sẽ giúp tránh một số vấn đề trong đó quá trình ăn mòn RAM gây ra sự hoán đổi khác (ghi vào đĩa) và ghi số lượng lớn vào đĩa để ngăn chặn mọi thứ khác muốn IO. Bản thân nó không phải là nguyên nhân gây ra sự cố, nhưng nó làm tăng thêm sự xuống cấp về khả năng đáp ứng.
hạn chế loét
Một vấn đề với ulimits là giới hạn kế toán áp dụng cho không gian địa chỉ bộ nhớ ảo (ngụ ý kết hợp cả không gian vật lý và không gian hoán đổi). Theo man limits.conf
:
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
Vì vậy, thiết lập một ulimit để chỉ áp dụng cho việc sử dụng RAM vật lý sẽ không còn sử dụng được nữa. Vì thế
as
address space limit (KB)
dường như là điều chỉnh duy nhất được tôn trọng.
Thật không may, như chi tiết hơn bằng ví dụ về WebKit / Gnome, một số ứng dụng không thể chạy nếu phân bổ không gian địa chỉ ảo bị hạn chế.
cgroups sẽ giúp gì trong tương lai?
Hiện tại, nó có vẻ cồng kềnh, nhưng có thể kích hoạt một số cờ cgroup kernel cgroup_enable=memory swapaccount=1
(ví dụ: trong cấu hình grub) và sau đó thử sử dụng bộ điều khiển bộ nhớ cgroup để hạn chế sử dụng bộ nhớ.
các nhóm có các tính năng giới hạn bộ nhớ nâng cao hơn sau đó là các tùy chọn 'ulimit'. Cgroup v2 lưu ý gợi ý về những nỗ lực cải thiện cách thức hoạt động của ulimits.
Bộ nhớ kết hợp + kế toán hoán đổi và giới hạn được thay thế bằng sự kiểm soát thực sự đối với không gian hoán đổi.
Tùy chọn Cgroup có thể được đặt thông qua các tùy chọn kiểm soát tài nguyên systemd . Ví dụ:
Các tùy chọn hữu ích khác có thể là
Những điều này có một số nhược điểm:
- Trên không. Tài liệu docker hiện tại đề cập ngắn gọn về việc sử dụng bộ nhớ thêm 1% và suy giảm hiệu suất 10% (có thể liên quan đến các hoạt động cấp phát bộ nhớ - nó không thực sự chỉ định).
- Công cụ Cgroup / systemd đã được làm việc lại gần đây, vì vậy dòng chảy ngược ngụ ý các nhà cung cấp phân phối Linux có thể đang chờ nó giải quyết trước.
Trong Cgroup v2 , họ đề xuất rằng memory.high
nên là một lựa chọn tốt để điều tiết và quản lý việc sử dụng bộ nhớ của một nhóm quy trình. Tuy nhiên, trích dẫn này cho thấy rằng việc theo dõi các tình huống áp lực bộ nhớ cần nhiều công việc hơn (tính đến năm 2015).
Một thước đo áp lực bộ nhớ - khối lượng công việc đang bị ảnh hưởng do thiếu bộ nhớ - là cần thiết để xác định xem một khối lượng công việc có cần thêm bộ nhớ hay không; Thật không may, cơ chế giám sát áp suất bộ nhớ chưa được thực hiện.
Do các công cụ không gian người dùng systemd và cgroup rất phức tạp, tôi đã không tìm thấy một cách đơn giản để đặt thứ gì đó phù hợp và tận dụng điều này hơn nữa. Tài liệu cgroup và systemd cho Ubuntu không phải là tuyệt vời. Công việc trong tương lai nên dành cho các phiên bản dành cho máy tính để bàn để tận dụng các nhóm và systemd để dưới áp suất bộ nhớ cao, các thành phần ssh và X-Server / trình quản lý cửa sổ có quyền truy cập ưu tiên cao hơn vào CPU, RAM vật lý và IO lưu trữ, để tránh cạnh tranh với các quy trình bận trao đổi. Các tính năng ưu tiên CPU và I / O của kernel đã xuất hiện được một thời gian. Nó dường như được ưu tiên truy cập vào RAM vật lý mà thiếu.
Tuy nhiên, ngay cả các ưu tiên CPU và IO cũng không được thiết lập phù hợp!? Khi tôi kiểm tra giới hạn nhóm hệ thống, chia sẻ cpu, v.v., theo như tôi có thể nói, Ubuntu đã không nướng trong bất kỳ tình trạng viêm nhiễm nào được xác định trước. Ví dụ: tôi đã chạy:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
Tôi đã so sánh nó với cùng một đầu ra cho ssh, samba, gdm và nginx. Những thứ quan trọng như GUI và bảng điều khiển quản trị từ xa phải chiến đấu bình đẳng với tất cả các quy trình khác khi xảy ra sự cố.
Ví dụ giới hạn bộ nhớ tôi có trên hệ thống RAM 16 GB
Tôi muốn kích hoạt chế độ ngủ đông, vì vậy tôi cần một phân vùng trao đổi lớn. Do đó cố gắng để giảm thiểu với ulimits, vv
lo lắng
Tôi đưa * hard as 16777216
vào /etc/security/limits.d/mem.conf
để không một quy trình đơn lẻ nào được phép yêu cầu nhiều bộ nhớ hơn mức có thể. Tôi sẽ không ngăn chặn tất cả cùng nhau, nhưng nếu không, chỉ một quá trình sử dụng bộ nhớ tham lam hoặc rò rỉ bộ nhớ có thể gây ra sự cố. Ví dụ: tôi đã thấy gnome-contacts
mất 8GB bộ nhớ khi thực hiện những việc trần tục như cập nhật danh sách địa chỉ toàn cầu từ máy chủ trao đổi ...
Như đã thấy ulimit -S -v
, nhiều bản phân phối có giới hạn cứng và mềm này được đặt là 'không giới hạn', theo lý thuyết, một quá trình có thể sẽ yêu cầu rất nhiều bộ nhớ nhưng chỉ chủ động sử dụng một tập hợp con và vui vẻ nghĩ rằng nó được cung cấp 24GB RAM trong khi hệ thống chỉ có 16GB. Giới hạn cứng ở trên sẽ khiến các quy trình có thể chạy tốt để hủy bỏ khi kernel từ chối các yêu cầu bộ nhớ đầu cơ tham lam của chúng.
Tuy nhiên, nó cũng bắt được những thứ điên rồ như danh bạ gnome và thay vì mất khả năng phản hồi của máy tính để bàn, tôi gặp lỗi "không đủ bộ nhớ trống":
Biến chứng thiết lập ulimit cho không gian địa chỉ (bộ nhớ ảo)
Thật không may, một số nhà phát triển muốn giả vờ bộ nhớ ảo là một nguồn tài nguyên vô hạn và thiết lập một lỗ hổng trên bộ nhớ ảo có thể phá vỡ một số ứng dụng. Ví dụ: WebKit (mà một số ứng dụng gnome phụ thuộc vào) đã thêm một gigacage
tính năng bảo mật cố gắng phân bổ số lượng bộ nhớ ảo và FATAL: Could not allocate gigacage memory
lỗi với một gợi ý táo tợn Make sure you have not set a virtual memory limit
xảy ra. Công việc xung quanh,GIGACAGE_ENABLED=no
quên các lợi ích bảo mật, nhưng tương tự, không được phép giới hạn cấp phát bộ nhớ ảo cũng là một tính năng bảo mật (ví dụ: kiểm soát tài nguyên có thể ngăn chặn từ chối dịch vụ). Trớ trêu thay, giữa các nhà phát triển gigacage và gnome, họ dường như quên mất rằng việc giới hạn phân bổ bộ nhớ chính là một biện pháp kiểm soát an ninh. Và thật đáng buồn, tôi nhận thấy các ứng dụng gnome dựa trên gigacage không bận tâm yêu cầu giới hạn cao hơn, do đó, ngay cả giới hạn mềm cũng phá vỡ mọi thứ trong trường hợp này.
Công bằng mà nói, nếu hạt nhân làm tốt hơn việc có thể từ chối cấp phát bộ nhớ dựa trên việc sử dụng bộ nhớ thường trú thay vì bộ nhớ ảo, thì giả vờ bộ nhớ ảo là không giới hạn sẽ ít nguy hiểm hơn.
thừa
Nếu bạn muốn các ứng dụng bị từ chối truy cập bộ nhớ và muốn ngừng hoạt động quá mức, hãy sử dụng các lệnh bên dưới để kiểm tra cách hệ thống của bạn hoạt động khi chịu áp lực bộ nhớ cao.
Trong trường hợp của tôi, tỷ lệ cam kết mặc định là:
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
Nhưng nó chỉ có hiệu lực đầy đủ khi thay đổi chính sách để vô hiệu hóa quá mức và áp dụng tỷ lệ
sudo sysctl -w vm.overcommit_memory=2
Tỷ lệ ngụ ý chỉ có 24 GB bộ nhớ có thể được phân bổ tổng thể (RAM 16 GB * 0,5 + 16 GB SWAP). Vì vậy, có lẽ tôi sẽ không bao giờ thấy OOM xuất hiện và thực sự ít có khả năng các quy trình liên tục truy cập bộ nhớ trong trao đổi. Nhưng tôi cũng có thể hy sinh hiệu quả hệ thống tổng thể.
Điều này sẽ khiến nhiều ứng dụng bị sập, do các nhà phát triển thường không xử lý một cách duyên dáng hệ điều hành từ chối yêu cầu cấp phát bộ nhớ. Nó đánh đổi rủi ro thỉnh thoảng bị khóa do bị đập (mất tất cả công việc của bạn sau khi thiết lập lại cứng) với rủi ro thường xuyên hơn về các ứng dụng khác nhau bị sập. Trong thử nghiệm của tôi, nó không giúp được gì nhiều vì máy tính để bàn bị sập khi hệ thống chịu áp lực bộ nhớ và nó không thể phân bổ bộ nhớ. Tuy nhiên, ít nhất là bàn giao tiếp và SSH vẫn hoạt động.
Làm thế nào để VM overcommit memory hoạt động có nhiều thông tin hơn.
Tôi đã chọn hoàn nguyên về mặc định cho điều này, sudo sysctl -w vm.overcommit_memory=0
do toàn bộ ngăn xếp đồ họa trên máy tính để bàn và các ứng dụng trong đó bị sập.