ngăn chặn hệ thống đóng băng / không phản hồi do hoán đổi sử dụng bộ nhớ


48

Nếu một quy trình đòi hỏi nhiều bộ nhớ, hệ thống sẽ chuyển tất cả quy trình khác sang tệp hoán đổi. Bao gồm có vẻ như, các quy trình cần thiết như máy chủ X11 hoặc thiết bị đầu cuối.

Vì vậy, nếu một quá trình tiếp tục phân bổ không giới hạn, mọi thứ sẽ không phản hồi, cho đến khi quá trình đó bị giết bởi OOM-killer. Máy tính xách tay của tôi dường như đặc biệt hợp lý và phản ứng cực kỳ xấu. Tôi vừa trải qua một GIỜ ENTIRE chờ kết thúc quá trình trong đó thậm chí không thể di chuyển con trỏ chuột.

Làm thế nào điều này có thể tránh được?

1) Vô hiệu hóa trao đổi => Tôi thường bắt đầu rất nhiều quá trình sau đó trở nên không hoạt động. Những người không hoạt động nên được chuyển đến trao đổi.

2) Nhận SSD => quá đắt

3) đặt ulimit bộ nhớ tối đa => nhưng sau đó nó bị lỗi trong trường hợp chương trình cần một bộ nhớ lớn, có thể cộng hưởng. Vấn đề không phải là nó sử dụng quá nhiều, mà là nó triệt tiêu các quá trình khác

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 chúng => điều này có thể được thực hiện không? làm sao? có lẽ chỉ trao đổi chương trình lớn?

5)?


Và ti lại xảy ra :( Bắt đầu gcc khi firefox đang chạy, mọi thứ đã bị chặn trong nửa giờ. Không di chuyển chuột, không đọc ebook
BeniBela

Tôi không chắc tôi hiểu bạn muốn gì. Bạn có muốn hệ thống làm phép thuật nhanh hơn với các tài nguyên mà nó có không? Bạn có muốn nó tiêu diệt các quá trình sử dụng nhiều bộ nhớ sớm hơn không?
David Schwartz

Âm thanh như những gì bạn thực sự cần là RAM nhiều hơn. Hoặc ít hơn các nhiệm vụ nền không hoạt động.
Daniel B

2
Bạn có thể sử dụng tổ hợp phím Alt + SysRq + F để buộc OOM-killer chạy. Điều này có thể cắt giảm thời gian cần thiết để chờ hệ thống của bạn mở giao diện điều khiển để bạn có thể giết chết một quy trình.
hololeap

Sửa lỗi cho tôi nếu tôi sai nhưng vấn đề này thực sự có vẻ như hệ thống đang tìm kiếm không gian hoán đổi đĩa nên tồn tại nhưng không tồn tại (phân vùng trao đổi quá nhỏ). Không đủ không gian hoán đổi sẽ dẫn đến việc hệ thống "đập" ổ cứng (hoặc ssd) để tìm không gian có sẵn.
mchid 18/03/18

Câu trả lời:


45

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 -vvà có thể đặt giới hạn cứng hoặc mềm bằng astù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_rationhư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, OOMScoreAdjustlà 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ụ:

  • Bộ nhớ cao
  • Bộ nhớMax

Các tùy chọn hữu ích khác có thể là

  • IOWeight
  • CPUShares

Những điều này có một số nhược điểm:

  1. 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).
  2. 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.highnê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 16777216và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-contactsmấ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 ...

Danh bạ Gnome nhai RAM

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":

nhập mô tả hình ảnh ở đây

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 gigacagetí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 memorylỗi với một gợi ý táo tợn Make sure you have not set a virtual memory limitxảy ra. Công việc xung quanh,GIGACAGE_ENABLED=noquê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=0do 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.


3
Đây là bài viết hay nhất tôi từng thấy về vấn đề này và bạn không dùng đến "chỉ cần mua thêm RAM!" Một điều bạn không đề cập đến là làm thế nào các tùy chọn cấu hình kernel phát huy tác dụng này. Ví dụ, mô hình tiền tố được sử dụng hoặc bộ lập lịch I / O được sử dụng có ảnh hưởng lớn đến bất kỳ điều này không?
hololeap

2
but the kernel won't be able to use an overcommit strategy for allocating memory and this will likely hurt performance. Even a smaller swap partition allows this. Có bằng chứng nào cho điều này? Tôi tin rằng hạt nhân hoạt động tốt chỉ cần không có cấu hình trao đổi
ygrek

@ygrek, cảm ơn, cách diễn đạt đó có vẻ hơi sai - overcommit vẫn hoạt động mà không cần trao đổi, trừ khi chế độ không bao giờ thừa (2) được chọn. Chế độ heuristic mặc định (0), hoặc luôn luôn cam kết (1) có thể vẫn hoạt động mà không cần trao đổi. Không thể nhớ lại nơi tôi đọc rằng tắt trao đổi làm tổn thương khả năng phân bổ bộ nhớ quá mức (và chế độ nào nó bị ảnh hưởng cụ thể). Googled một lần nữa mà không gặp may, nhưng đây là một bài viết bán hữu ích: stackoverflow.com/questions/38688824/ vì tôi sẽ chỉnh sửa câu trả lời một cách thích hợp.
JPvRiel

Tôi đã hy vọng bản vá ghi lại nền sẽ giúp tôi, nhưng tôi đang sử dụng kernel rất mới (4.14.81) và phải đối mặt với các vấn đề phản hồi đáng kể trong I / O đĩa nặng (bất kể trao đổi có phải là nguyên nhân hay không). Tôi tự hỏi nếu trình quản lý thiết bị hoặc mã hóa LUKS của tôi gây ra vấn đề về hiệu suất bằng cách nào đó. Tôi thực sự có chút manh mối làm thế nào để gỡ lỗi loại vấn đề này.
Darius Jahandarie
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.