Tôi muốn thực hiện một số thử nghiệm tài nguyên thấp và tôi cần phải có 90% bộ nhớ trống.
Làm thế nào tôi có thể làm điều này trên một *nix
hệ thống?
Tôi muốn thực hiện một số thử nghiệm tài nguyên thấp và tôi cần phải có 90% bộ nhớ trống.
Làm thế nào tôi có thể làm điều này trên một *nix
hệ thống?
Câu trả lời:
stress-ng là một trình tạo khối lượng công việc mô phỏng ứng suất cpu / mem / io / hdd trên các hệ thống POSIX. Cuộc gọi này sẽ thực hiện thủ thuật trên Linux <3.14:
stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Đối với Linux> = 3.14, bạn có thể sử dụng MemAvailable
thay thế để ước tính bộ nhớ khả dụng cho các quy trình mới mà không cần trao đổi:
stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Điều chỉnh /proc/meminfo
cuộc gọi bằng free(1)
/ vm_stat(1)
/ etc. nếu bạn cần nó di động.
stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
--vm 1 and --vm-keep
đều rất quan trọng. Đơn giản là --vm-bytes
không làm gì cả và bạn có thể bị lầm tưởng rằng bạn có thể phân bổ bao nhiêu bộ nhớ mà bạn cần / muốn. Tôi đã nhận được một chút bằng cách này cho đến khi tôi cố gắng tự kiểm tra bằng cách phân bổ 256G bộ nhớ. Đây không phải là một lỗ hổng trong câu trả lời, nó cung cấp các cờ chính xác, chỉ là một sự thận trọng bổ sung.
-m 1
. Theo trang web căng thẳng, -m N
viết tắt của --vm N
: N
công nhân sinh sản quay vòngmalloc()/free()
Bạn có thể viết chương trình C vào malloc()
bộ nhớ cần thiết và sau đó sử dụng mlock()
để ngăn bộ nhớ bị tráo đổi.
Sau đó, chỉ cần để chương trình chờ nhập bàn phím và mở khóa bộ nhớ, giải phóng bộ nhớ và thoát.
calloc
sẽ gặp vấn đề tương tự IIRC. Tất cả bộ nhớ sẽ chỉ vào cùng một trang zeroed chỉ đọc. Nó sẽ không thực sự được phân bổ cho đến khi bạn cố gắng viết cho nó (nó sẽ không hoạt động vì nó chỉ đọc). Cách duy nhất để thực sự chắc chắn rằng tôi biết là thực hiện một memset
bộ đệm. Xem câu trả lời sau để biết thêm thông tin stackoverflow.com/a/2688522/713554
Tôi khuyên bạn nên chạy VM với bộ nhớ hạn chế và kiểm tra phần mềm trong đó sẽ là một thử nghiệm hiệu quả hơn so với cố gắng lấp đầy bộ nhớ trên máy chủ.
Phương pháp đó cũng có ưu điểm là nếu tình trạng bộ nhớ thấp gây ra lỗi OOM ở nơi khác và treo toàn bộ HĐH, bạn chỉ treo máy ảo mà bạn đang kiểm tra không phải máy của bạn mà bạn có thể có các quy trình hữu ích khác đang chạy.
Ngoài ra, nếu thử nghiệm của bạn không chuyên sâu về CPU hoặc IO, bạn có thể chạy đồng thời các phiên bản thử nghiệm trên một họ máy ảo với nhiều kích cỡ bộ nhớ thấp.
Từ HN bình luận này: https://news.ycombinator.com/item?id=6695581
Chỉ cần điền / dev / shm qua dd hoặc tương tự.
swapoff -a dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
pv
được cài đặt, nó sẽ giúp xem số đếm:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Nếu bạn có các công cụ GNU cơ bản ( sh
, grep
, yes
và head
) bạn có thể làm điều này:
yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily
Điều này hoạt động vì grep tải toàn bộ dòng dữ liệu trong RAM (tôi đã học được điều này theo một cách khá đáng tiếc khi lấy một hình ảnh đĩa). Điểm mấu, được tạo ra bởi yes
, dòng mới thay thế, sẽ là dài vô hạn, nhưng bị hạn chế bởi head
để $BYTES
byte, do đó grep sẽ nạp $ byte trong bộ nhớ. Bản thân Grep sử dụng như 100-200KB đối với tôi, bạn có thể cần phải trừ đi để có số tiền chính xác hơn.
Nếu bạn cũng muốn thêm một hạn chế về thời gian, điều này có thể được thực hiện khá dễ dàng trong bash
(sẽ không hoạt động sh
):
cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n
Điều <(command)
này dường như ít được biết đến nhưng thường cực kỳ hữu ích, thông tin thêm về nó ở đây: http://tldp.org/LDP/abs/html/ process-sub.html
Sau đó, để sử dụng cat
: cat
sẽ đợi các đầu vào hoàn thành cho đến khi thoát ra và bằng cách giữ một trong các đường ống mở, nó sẽ giữ cho grep sống.
Nếu bạn có pv
và muốn từ từ tăng RAM, hãy sử dụng:
yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n
Ví dụ:
yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n
Sẽ sử dụng tối đa một gigabyte với tốc độ 1MB mỗi giây. Là một phần thưởng bổ sung, pv
sẽ cho bạn thấy tỷ lệ sử dụng hiện tại và tổng số sử dụng cho đến nay. Tất nhiên điều này cũng có thể được thực hiện với các biến thể trước đó:
yes | tr \\n x | head -c $BYTES | pv | grep n
Chỉ cần chèn | pv |
phần này sẽ cho bạn thấy trạng thái hiện tại (thông lượng và tổng số, theo mặc định, tôi nghĩ - nếu không hãy xem trang người đàn ông (ual)).
Tại sao câu trả lời khác? Câu trả lời được chấp nhận khuyên bạn nên cài đặt một gói (Tôi cá là có một bản phát hành cho mọi chipset mà không cần người quản lý gói); câu trả lời được bình chọn hàng đầu khuyên bạn nên biên dịch chương trình C (Tôi chưa cài đặt trình biên dịch hoặc chuỗi công cụ để biên dịch cho nền tảng mục tiêu của bạn); câu trả lời được bình chọn hàng đầu thứ hai khuyên bạn nên chạy ứng dụng trong máy ảo (vâng, hãy để tôi chỉ cần sdcard nội bộ của điện thoại này qua usb hoặc một cái gì đó và tạo một hình ảnh hộp ảo); phần ba đề nghị sửa đổi một cái gì đó trong chuỗi khởi động không lấp đầy RAM như mong muốn; cái thứ tư chỉ hoạt động trong khoảng thời gian gắn kết / dev / shm (1) và (2) là lớn (đáp ứng nhu cầu gốc); thứ năm kết hợp nhiều thứ ở trên mà không có mã mẫu; thứ sáu là một câu trả lời tuyệt vời nhưng tôi đã không thấy câu trả lời này trước khi đưa ra cách tiếp cận của riêng mình, Vì vậy, tôi nghĩ rằng tôi nên thêm cái riêng của mình, cũng bởi vì nó ngắn hơn để nhớ hoặc gõ nếu bạn không thấy rằng dòng memblob thực sự là mấu chốt của vấn đề; thứ bảy một lần nữa không trả lời câu hỏi (sử dụng ulimit để giới hạn một quá trình thay thế); thứ tám cố gắng để bạn cài đặt python; người thứ chín nghĩ rằng tất cả chúng ta đều rất không sáng tạo và cuối cùng, người thứ mười đã viết chương trình C ++ của riêng mình, điều này gây ra vấn đề tương tự như câu trả lời được bình chọn hàng đầu.
set -e
, vì vậy tôi mới học được điều gì đó :)
time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n
(sử dụng bộ nhớ 10 GiB) mất 1 phút 46 giây. Chạy chương trình eatmemory của julman99 tại github.com/julman99/eatmemory mất 6 giây. ... Chà, cộng với thời gian tải xuống và biên dịch, nhưng nó không có vấn đề gì ... và rất nhanh chóng ... trên máy RHEL6.4 của tôi. Tuy nhiên, tôi thích giải pháp này. Tại sao phải phát minh lại bánh xe?
Tôi giữ một chức năng để làm một cái gì đó tương tự trong dotfiles của tôi. https://github.com/sagotsky/.dotfiles/blob/master/.fifts#L248
function malloc() {
if [[ $# -eq 0 || $1 -eq '-h' || $1 -lt 0 ]] ; then
echo -e "usage: malloc N\n\nAllocate N mb, wait, then release it."
else
N=$(free -m | grep Mem: | awk '{print int($2/10)}')
if [[ $N -gt $1 ]] ;then
N=$1
fi
sh -c "MEMBLOB=\$(dd if=/dev/urandom bs=1MB count=$N) ; sleep 1"
fi
}
Làm thế nào để vượt qua một giải pháp python đơn giản?
#!/usr/bin/env python
import sys
import time
if len(sys.argv) != 2:
print "usage: fillmem <number-of-megabytes>"
sys.exit()
count = int(sys.argv[1])
megabyte = (0,) * (1024 * 1024 / 8)
data = megabyte * count
while True:
time.sleep(1)
sysctl vm.swappiness=0
và hơn nữa đặt vm.min_free_kbytes thành một số nhỏ, có thể là 1024. Tôi chưa thử, nhưng các tài liệu nói rằng đây là cách bạn kiểm soát sự nhanh chóng của việc hoán đổi ... bạn nên thực sự có thể làm cho nó khá chậm, đến mức gây ra tình trạng OOM trên máy của bạn. Xem kernel.org/doc/Documentation/sysctl/vm.txt và kernel.org/doc/gorman/html/understand/understand005.html
Nếu bạn muốn kiểm tra một quy trình cụ thể với bộ nhớ hạn chế, bạn nên sử dụng ulimit
để hạn chế lượng bộ nhớ phân bổ.
man setrlimit
:RLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.
Tôi nghĩ rằng đây là một trường hợp đặt câu hỏi sai và sự tỉnh táo bị nhấn chìm bởi những người cạnh tranh cho câu trả lời sáng tạo nhất. Nếu bạn chỉ cần mô phỏng các điều kiện OOM, bạn không cần phải lấp đầy bộ nhớ. Chỉ cần sử dụng một phân bổ tùy chỉnh và nó thất bại sau một số phân bổ nhất định. Cách tiếp cận này dường như hoạt động đủ tốt cho SQLite .
Tôi đã viết chương trình C ++ nhỏ này cho điều đó: https://github.com/rmetzger/dynamic-ballooner
Ưu điểm của việc thực hiện này là kiểm tra định kỳ nếu nó cần giải phóng hoặc phân bổ lại bộ nhớ.