Phân mảnh bộ nhớ Linux


20

Có cách nào để phát hiện sự phân mảnh bộ nhớ trên linux không? Điều này là do trên một số máy chủ chạy lâu tôi đã nhận thấy sự suy giảm hiệu suất và chỉ sau khi tôi khởi động lại quá trình, tôi mới thấy hiệu suất tốt hơn. Tôi nhận thấy nó nhiều hơn khi sử dụng hỗ trợ trang lớn linux - các trang lớn trong linux có dễ bị phân mảnh hơn không?

Tôi đã xem xét / Proc / Buddyinfo nói riêng. Tôi muốn biết liệu có cách nào tốt hơn (không chỉ các lệnh CLI mỗi se, bất kỳ chương trình hoặc nền tảng lý thuyết nào sẽ làm) để xem xét nó.


Tôi không chỉ nhìn vào các giải pháp dòng lệnh nhanh, bất kỳ chương trình / lý thuyết đơn giản nào cũng sẽ làm được. Do đó, tôi đã không hỏi tại serverfault.
Raghu

1
Tôi không hiểu ở đây một điểm. Theo tôi hiểu sự phân mảnh bộ nhớ phải dẫn đến việc thiếu bộ nhớ và dẫn đến lỗi cấp phát bộ nhớ. Tuy nhiên, bạn đang hỏi về sự suy giảm hiệu suất. Có phải vì bạn có rất nhiều bộ nhớ được trao đổi vào đĩa? Và nếu vậy những gì cho vmstattrong lĩnh vực này so?

@skwllsp - Đã chỉnh sửa câu trả lời của tôi để cụ thể hơn.
Tim Post

@Raghu - Tôi không mong đợi hầu hết các quản trị viên hệ thống sửa đổi mã hạt nhân để quản lý bộ nhớ hoạt động khác đi, tuy nhiên, quản trị viên Linux có kỹ năng nên biết ít nhất một cái nhìn tổng quan về cách Linux quản lý bộ nhớ. Câu hỏi này thực sự là trên đường dây. Tôi đã bỏ phiếu để di chuyển nó đơn giản vì tôi không thể đề xuất (trong câu trả lời của tôi) mã trả lời câu hỏi của bạn. Đọc từ / Proc hoặc sử dụng vmstatlà một kinh nghiệm người dùng phổ biến. Nếu bạn đang viết một chương trình để làm như vậy, nó sẽ khác. Nếu bạn có ý định sử dụng bash để thu thập thông tin này, hãy chỉnh sửa câu hỏi của bạn, nó sẽ không bị đóng :)
Tim Post

@Tim - Như tôi đã đề xuất, đó không chỉ là các lệnh bash / cli mà tôi muốn biết, tôi cần thông tin để giúp tôi trong quy trình đo điểm chuẩn của mình (để phân tích kết quả, không chạy chúng).
Raghu

Câu trả lời:


12

Tôi đang trả lời cho thẻ . Câu trả lời của tôi chỉ dành riêng cho Linux .

Có, các trang lớn dễ bị phân mảnh hơn. Có hai khung nhìn của bộ nhớ, một khung nhìn mà quá trình của bạn nhận được (ảo) và một khung nhìn mà kernel quản lý (thực). Bất kỳ trang nào càng lớn, sẽ càng khó nhóm (và giữ nó với) hàng xóm của nó, đặc biệt là khi dịch vụ của bạn đang chạy trên một hệ thống cũng phải hỗ trợ những người khác mặc định phân bổ và ghi vào bộ nhớ nhiều hơn họ thực sự cuối cùng sử dụng.

Ánh xạ của các địa chỉ được cấp (thực) của kernel là riêng tư. Có một lý do rất chính đáng tại sao không gian người dùng xem chúng là kernel trình bày chúng, bởi vì kernel cần có khả năng vượt mức mà không gây nhầm lẫn cho không gian người dùng. Quá trình của bạn có được một không gian địa chỉ "Disneyfied" đẹp, liền kề để làm việc, không biết gì về nhân thực sự đang làm với bộ nhớ đó đằng sau hậu trường.

Lý do bạn thấy hiệu suất bị suy giảm trên các máy chủ chạy dài rất có thể là do các khối được phân bổ chưa bị khóa rõ ràng (ví dụ mlock()/ mlockall()hoặc posix_madvise()) và không được sửa đổi trong một thời gian đã bị loại bỏ , điều đó có nghĩa là dịch vụ của bạn trượt vào đĩa khi nó phải đọc họ Sửa đổi hành vi này làm cho quy trình của bạn trở thành hàng xóm tồi , đó là lý do tại sao nhiều người đưa RDBMS của họ lên một máy chủ hoàn toàn khác so với web / php / python / ruby ​​/ bất cứ điều gì. Cách duy nhất để khắc phục điều đó, hoàn toàn, là giảm sự cạnh tranh cho các khối liền kề.

Sự phân mảnh chỉ thực sự đáng chú ý (trong hầu hết các trường hợp) khi trang A nằm trong bộ nhớ và trang B đã chuyển sang hoán đổi. Đương nhiên, việc bắt đầu lại dịch vụ của bạn dường như sẽ 'chữa trị' điều này, nhưng chỉ vì hạt nhân chưa có cơ hội để đưa ra quy trình '(bây giờ) các khối mới được phân bổ trong giới hạn của tỷ lệ thừa.

Trên thực tế, việc bắt đầu lại (giả sử) 'apache' dưới tải trọng cao có khả năng sẽ gửi các khối thuộc sở hữu của các dịch vụ khác vào thẳng đĩa. Vì vậy, vâng, 'apache' sẽ cải thiện trong một thời gian ngắn, nhưng 'mysql' có thể bị ảnh hưởng .. ít nhất là cho đến khi hạt nhân khiến chúng đau khổ như nhau khi đơn giản là thiếu bộ nhớ vật lý dồi dào.

Thêm bộ nhớ, hoặc chia tách những malloc()người tiêu dùng khó tính :) Nó không chỉ là sự phân mảnh mà bạn cần phải xem xét.

Cố gắng vmstatcó được một cái nhìn tổng quan về những gì thực sự được lưu trữ ở đâu.


Cảm ơn bạn đã trả lời. Tôi đã sử dụng các trang khổng lồ (kích thước = 2048KB mỗi trang) cho mysql - nhóm bộ đệm innodb - để xem giá vé như thế nào (sử dụng sysbench). Ban đầu khi thời gian hoạt động của quá trình (và thậm chí cả thời gian hoạt động của hệ thống) thấp, nó đã cho kết quả rất tốt. Tuy nhiên, hiệu suất của nó bắt đầu xuống cấp qua một số lần chạy. Về trang bạn đã đề cập, tôi chắc chắn nhận thấy một hoạt động VM cao, nhưng tôi cho rằng nó có thể là do tính năng xóa nhật ký chuẩn và innodb (hoạt động vm cao hơn với các trang lớn hơn không có). Tôi cũng đặt vm.swappiness thành 1. Tôi không thể nhận thấy bất kỳ thay đổi mạnh mẽ nào.
Raghu

Theo tài liệu hướng dẫn tốt , "Các trang lớn không thể bị tráo đổi dưới áp lực bộ nhớ." Tôi nghĩ rằng đây là một câu trả lời tốt trong bộ nhớ tiêu chuẩn w / r / t nhưng không phải cho các ôm.
Dan Pritts

5

Hạt nhân

Để có được chỉ số phân mảnh hiện tại, sử dụng:

sudo cat /sys/kernel/debug/extfrag/extfrag_index

Để chống phân mảnh bộ nhớ kernel, hãy thử thực thi:

sysctl vm.compact_memory=1  

Ngoài ra, bạn hãy thử tắt các trang lớn trong suốt (còn gọi là THP) và / hoặc vô hiệu hóa trao đổi (hoặc giảm swappiness).

Không gian người dùng

Để giảm sự phân mảnh không gian người dùng, bạn có thể muốn thử phân bổ khác nhau, ví dụ jemalloc(nó có khả năng hướng nội tuyệt vời , điều này sẽ cung cấp cho bạn một phân đoạn bên trong của phân bổ).

Bạn có thể chuyển sang malloc tùy chỉnh bằng cách biên dịch lại chương trình của bạn với nó hoặc chỉ bằng cách chạy chương trình của bạn với LD_PRELOAD: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app (hãy cẩn thận với các tương tác giữa THP và bộ cấp phát bộ nhớ )

Mặc dù, hơi không liên quan đến phân mảnh bộ nhớ (nhưng được kết nối với quá trình nén / di chuyển bộ nhớ), bạn có thể muốn chạy nhiều phiên bản dịch vụ của mình, một phiên bản cho mỗi nút NUMA và liên kết chúng bằng cách sử dụng numactl.


1
Tại sao bạn nghĩ rằng vô hiệu hóa trao đổi có thể giúp đỡ? Đối với tôi có vẻ như nhiều khả năng vô hiệu hóa trao đổi sẽ làm tổn thương nhiều hơn.
kasperd

1
Vì không có đủ thông tin trong bài viết gốc, có thể quá trình chỉ bị rò rỉ và bắt đầu hoán đổi. Ngoài ra tôi không thấy bất kỳ lý do chính đáng nào cho việc sử dụng trao đổi trên hầu hết mọi hệ thống sản xuất (mb chỉ dành cho các máy trạm dùng chung cho sinh viên).
SaveTheRbtz

2
Có đủ không gian hoán đổi sẽ cải thiện hiệu suất. Các vấn đề về hiệu suất bạn sẽ nhận được nếu bạn không có đủ dung lượng trao đổi là lý do đủ để kích hoạt trao đổi.
kasperd

1
@SaveTheRbtz Một lý do chính đáng để sử dụng trao đổi trên hệ thống sản xuất là nó cung cấp cho hệ thống nhiều tùy chọn hơn mà nó sẽ sử dụng chỉ khi nó nghĩ rằng chúng có lợi. Ngoài ra, nó cho phép các trang đã sửa đổi không được truy cập trong vài giờ (và có thể không bao giờ được truy cập) được đẩy ra khỏi bộ nhớ vật lý quý giá. Cuối cùng, nó cho phép hệ thống xử lý hoàn toàn các trường hợp sử dụng nhiều bộ nhớ hơn so với sử dụng.
David Schwartz

2
"chỉ khi nó nghĩ rằng chúng có lợi" - điều đó bổ sung thêm heuristic và làm cho hệ thống ít dự đoán hơn. Ngoài ra, các thuật toán thay thế trang (được sử dụng trong trao đổi và ẩn danh mmap) được triển khai khác nhau trên các hạt nhân khác nhau (ví dụ: Linux so với FreeBSD) hoặc thậm chí các phiên bản khác nhau của cùng một hệ điều hành (2.6.32 so với 3.2 so với 3.10) .. "nó cho phép các trang được sửa đổi [. ..] sẽ bị đẩy ra khỏi [...] bộ nhớ vật lý "- điều đó sẽ che giấu rò rỉ bộ nhớ. "xử lý các trường hợp sử dụng nhiều bộ nhớ hơn so với sử dụng" - hệ thống chậm tệ hơn nhiều so với hệ thống xuống, vì vậy "lành mạnh" là nghi vấn.
LưuTheRbtz

4

Sử dụng các trang lớn sẽ không gây ra sự phân mảnh bộ nhớ thêm trên Linux; Hỗ trợ Linux cho các trang lớn chỉ dành cho bộ nhớ dùng chung (thông qua shmget hoặc mmap) và bất kỳ trang lớn nào được sử dụng phải được yêu cầu cụ thể và được cấp phép bởi quản trị viên hệ thống. Khi đã ở trong bộ nhớ, chúng được ghim ở đó và không bị tráo đổi. Thách thức của việc hoán đổi trong các trang lớn khi phân mảnh bộ nhớ chính xác là lý do tại sao chúng vẫn bị ghim trong bộ nhớ (khi phân bổ một trang lớn 2 MB, hạt nhân phải tìm 512 trang 4KB miễn phí liền kề, thậm chí có thể không tồn tại).

Tài liệu Linux trên các trang lớn: http://lwn.net/Articles/375098/

Có một trường hợp phân mảnh bộ nhớ có thể khiến việc phân bổ trang lớn bị chậm (nhưng không phải là nơi các trang lớn gây ra phân mảnh bộ nhớ) và đó là nếu hệ thống của bạn được định cấu hình để phát triển nhóm trang lớn nếu được ứng dụng yêu cầu. Nếu / Proc / sys / vm / nr_overcommit_hugepages lớn hơn / Proc / sys / vm / nr_hugepages, điều này có thể xảy ra.


Thật vậy - và nó thường sẽ giúp hiệu suất vì nó sẽ ngăn chặn các lỗi TLB (xem bài viết được liên kết để giải thích).
Dan Pritts 16/12/13

0

/proc/buddyinforất hữu ích. Nó hữu ích hơn với định dạng đầu ra đẹp, như kịch bản Python này có thể làm:

https://gist.github.com/labeneator/9574294

Đối với các trang lớn, bạn muốn có một số mảnh miễn phí ở kích thước 2097152 (2MiB) hoặc lớn hơn. Đối với các trang lớn trong suốt, nó sẽ tự động nén khi kernel được yêu cầu một số, nhưng nếu bạn muốn xem bạn có thể nhận được bao nhiêu, thì khi chạy root:

echo 1 | sudo tee /proc/sys/vm/compact_memory

Cũng có, các trang lớn gây ra vấn đề lớn cho phân mảnh. Hoặc bạn không thể có được bất kỳ trang lớn nào, hoặc sự hiện diện của chúng khiến kernel mất nhiều thời gian hơn để cố gắng lấy một số trang.

Tôi có một giải pháp phù hợp với tôi. Tôi sử dụng nó trên một vài máy chủ và máy tính xách tay của tôi. Nó hoạt động tuyệt vời cho các máy ảo.

Thêm kernelcore=4Gtùy chọn vào dòng lệnh Linux kernel của bạn. Trên máy chủ của tôi, tôi sử dụng 8G. Hãy cẩn thận với số này, vì nó sẽ ngăn hạt nhân của bạn phân bổ bất cứ thứ gì bên ngoài bộ nhớ đó. Các máy chủ cần nhiều bộ đệm ổ cắm hoặc ổ đĩa đó ghi vào hàng trăm ổ đĩa sẽ không thích bị giới hạn như thế này. Bất kỳ phân bổ bộ nhớ nào phải được "ghim" cho bản mỏng hoặc DMA đều thuộc loại này.

Tất cả bộ nhớ khác của bạn sau đó trở thành "có thể di chuyển", điều đó có nghĩa là nó có thể được nén lại thành các đoạn đẹp để phân bổ trang lớn. Bây giờ các trang lớn trong suốt có thể thực sự cất cánh và hoạt động như mong muốn. Bất cứ khi nào kernel cần nhiều hơn 2 triệu trang, nó có thể chỉ cần ánh xạ lại các trang 4K sang một nơi khác.

Và, tôi không hoàn toàn chắc chắn làm thế nào điều này tương tác với IO trực tiếp không sao chép. Bộ nhớ trong "vùng di động" không được cho là được ghim, nhưng một yêu cầu IO trực tiếp sẽ thực hiện chính xác điều đó cho DMA. Nó có thể sao chép nó. Nó có thể ghim nó trong vùng di động nào. Trong cả hai trường hợp, nó có thể không chính xác những gì bạn muốn.

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.