Bagaimana cara mengisi 90% dari memori bebas?

181

Saya ingin melakukan beberapa pengujian sumber daya rendah dan untuk itu saya perlu memiliki 90% dari memori bebas penuh.

Bagaimana saya bisa melakukan ini pada *nixsistem?

Eduard Florinescu
sumber
3
Apakah itu benar-benar harus bekerja pada setiap sistem * nix?
CVn
31
Alih-alih mengisi memori, dapatkah Anda membuat VM (menggunakan buruh pelabuhan, atau gelandangan, atau yang serupa) yang memiliki jumlah memori terbatas?
abendigo
4
@ abendigo Untuk QA, banyak solusi yang disajikan di sini bermanfaat: untuk tujuan umum OS tanpa platform spesifik, parameter VM atau kernel boot bisa berguna, tetapi untuk sistem tertanam di mana Anda mengetahui spesifikasi memori dari sistem yang ditargetkan saya akan pergi untuk mengisi memori bebas.
Eduard Florinescu
2
Jika ada orang lain yang sedikit terkejut dengan penilaian di sini: meta.unix.stackexchange.com/questions/1513/… ?
goldilocks

Jawaban:

157

stress-ng adalah generator beban kerja yang mensimulasikan tekanan cpu / mem / io / hdd pada sistem POSIX. Panggilan ini harus melakukan trik di Linux <3.14:

stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

Untuk Linux> = 3.14, Anda dapat menggunakan MemAvailableuntuk memperkirakan memori yang tersedia untuk proses baru tanpa bertukar:

stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

Sesuaikan /proc/meminfopanggilan dengan free(1)/ vm_stat(1)/ etc. jika Anda membutuhkannya portabel.

tkrennwa
sumber
3
stress --vm-bytes $ (awk '/ MemFree / {printf "% d \ n", $ 2 * 0,097;}' </ proc / meminfo) k --vm-keep -m 10
Robert
1
Sebagian besar MemFree disimpan oleh OS, jadi saya menggunakan MemAvailable sebagai gantinya. Ini memberi saya 92% penggunaan pada Cent OS 7.stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
kujiy
baik untuk mengetahui, MemAvailable ditambahkan ke "perkiraan berapa banyak memori tersedia untuk memulai aplikasi baru, tanpa bertukar", lihat git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ … Dan git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/…
tkrennwa
1
Sama seperti catatan tambahan, menyediakan keduanya --vm 1 and --vm-keepsangat penting. Cukup --vm-bytestidak melakukan apa-apa dan Anda mungkin disangka berpikir Anda dapat mengalokasikan memori sebanyak yang Anda butuhkan / inginkan. Saya mendapatkan sedikit dengan ini sampai saya mencoba untuk memeriksa kewarasan diriku dengan mengalokasikan 256G memori. Ini bukan cacat dalam jawabannya, itu memberikan bendera yang benar, hanya peringatan tambahan.
meraba
Inilah mengapa ada -m 1. Menurut halaman stres, -m Nadalah kependekan dari --vm N: Npekerja spawn berputar terusmalloc()/free()
tkrennwa
92

Anda dapat menulis program C ke malloc()memori yang diperlukan dan kemudian menggunakannya mlock()untuk mencegah memori tidak ditukar.

Kemudian biarkan program menunggu input keyboard, dan membuka kunci memori, membebaskan memori dan keluar.

Chris
sumber
25
Dulu saya harus menguji use case yang serupa. Saya mengamati bahwa sampai Anda menulis sesuatu ke memori itu tidak akan benar-benar dialokasikan (yaitu sampai kesalahan halaman terjadi). Saya tidak yakin apakah mlock () menangani hal itu.
Poorna
2
Saya setuju dengan @siri; Namun, itu tergantung pada varian UNIX yang Anda gunakan.
Anthony
2
Beberapa inspirasi untuk kode. Selanjutnya, saya pikir Anda tidak perlu membuka / membebaskan memori . OS akan melakukan itu untuk Anda ketika proses Anda telah berakhir.
Sebastian
9
Anda mungkin harus benar-benar menulis ke memori, kernel mungkin saja overcommit jika Anda hanya malloc itu. Jika dikonfigurasikan ke, mis. Linux akan membiarkan malloc berhasil kembali tanpa benar-benar membebaskan memori, dan hanya benar-benar mengalokasikan memori ketika sedang ditulis. Lihat win.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen
7
@Sebastian: callocakan mengalami masalah IIRC yang sama. Semua memori hanya akan mengarah ke halaman nol-baca yang sama. Ini tidak akan benar-benar dialokasikan sampai Anda mencoba menulis ke sana (yang tidak akan berfungsi karena hanya baca). Satu-satunya cara untuk benar-benar yakin bahwa saya tahu adalah dengan melakukan memsetseluruh buffer. Lihat jawaban berikut untuk info lebih lanjut stackoverflow.com/a/2688522/713554
Leo
45

Saya akan menyarankan menjalankan VM dengan memori terbatas dan menguji perangkat lunak yang akan menjadi tes yang lebih efisien daripada mencoba mengisi memori pada mesin host.

Metode itu juga memiliki keuntungan bahwa jika situasi memori rendah menyebabkan kesalahan OOM di tempat lain dan menggantung seluruh OS, Anda hanya menggantung VM yang Anda uji di mesin Anda dan Anda mungkin memiliki proses berguna lainnya berjalan.

Juga jika pengujian Anda bukan CPU atau IO intensif, Anda dapat secara bersamaan menjalankan contoh pengujian pada keluarga VM dengan berbagai ukuran memori rendah.

David Spillett
sumber
31

Dari komentar HN ini: https://news.ycombinator.com/item?id=6695581

Cukup isi / dev / shm melalui dd atau serupa.

swapoff -a
dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
damio
sumber
8
Tidak semua * nixes memiliki / dev / shm. Ada ide yang lebih portabel?
Tadeusz A. Kadłubowski
Jika pvdiinstal, ada baiknya untuk melihat hitungan:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Otheus
1
Jika Anda ingin kecepatan, metode ini adalah pilihan yang tepat! Karena itu mengalokasikan jumlah RAM yang diinginkan dalam hitungan detik. Jangan nyalakan / dev / urandom, itu akan menggunakan 100% CPU dan perlu beberapa menit jika RAM Anda besar. BELUM, / dev / shm memiliki ukuran relatif di distro Ubuntu / Debian modern, ia memiliki ukuran yang secara default 50% dari RAM fisik. Semoga Anda dapat me-remount / dev / shm atau mungkin membuat mount point baru. Pastikan ukurannya sesuai dengan yang Anda inginkan.
develCuy
30
  1. jalankan linux;
  2. boot dengan mem=nn[KMG]parameter boot kernel

(lihat di linux / Documentation / kernel-parameter.txt untuk detailnya).

Segera
sumber
24

Jika Anda memiliki alat GNU dasar ( sh, grep, yesdan head) Anda dapat melakukan ini:

yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily

Ini berfungsi karena grep memuat seluruh baris data dalam RAM (saya mempelajari ini dengan cara yang agak disayangkan ketika grepping gambar disk). Garis, yang dihasilkan oleh yes, menggantikan baris baru, akan panjang tak terhingga, tetapi dibatasi oleh headke $BYTESbyte, sehingga grep akan memuat $ BYTES dalam memori. Grep sendiri menggunakan seperti 100-200KB untuk saya, Anda mungkin perlu mengurangi itu untuk jumlah yang lebih tepat.

Jika Anda juga ingin menambahkan batasan waktu, ini dapat dilakukan dengan mudah di bash(tidak akan berfungsi sh):

cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n

The <(command)hal tampaknya sedikit diketahui tetapi sering sangat berguna, info lebih lanjut tentang di sini: http://tldp.org/LDP/abs/html/process-sub.html

Kemudian untuk penggunaan cat: catakan menunggu input selesai sampai keluar, dan dengan menjaga salah satu pipa terbuka, itu akan membuat grep tetap hidup.

Jika Anda telah pvdan ingin secara perlahan meningkatkan penggunaan RAM:

yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n

Sebagai contoh:

yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n

Akan menggunakan hingga satu gigabyte dengan kecepatan 1MB per detik. Sebagai bonus tambahan, pvakan menunjukkan tingkat penggunaan saat ini dan total penggunaan sejauh ini. Tentu ini juga bisa dilakukan dengan varian sebelumnya:

yes | tr \\n x | head -c $BYTES | pv | grep n

Hanya memasukkan | pv |bagian akan menunjukkan kepada Anda status saat ini (throughput dan total, secara default, saya pikir - kalau tidak lihat halaman man (ual)).


Mengapa ada jawaban lain? Jawaban yang diterima merekomendasikan untuk menginstal paket (saya yakin ada rilis untuk setiap chipset tanpa memerlukan manajer paket); jawaban pilihan teratas merekomendasikan kompilasi program C (saya tidak memiliki kompiler atau toolchain yang diinstal untuk dikompilasi untuk platform target Anda); jawaban pilihan kedua teratas merekomendasikan untuk menjalankan aplikasi dalam VM (ya biarkan aku hanya dd sdcard internal ponsel ini melalui usb atau sesuatu dan membuat gambar virtualbox); yang ketiga menyarankan untuk memodifikasi sesuatu dalam urutan boot yang tidak mengisi RAM seperti yang diinginkan; yang keempat hanya berfungsi sejauh / dev / shm mountpoint (1) ada dan (2) besar (remounting membutuhkan root); yang kelima menggabungkan banyak hal di atas tanpa kode sampel; keenam adalah jawaban yang bagus tetapi saya tidak melihat jawaban ini sebelum datang dengan pendekatan saya sendiri, jadi saya pikir saya akan menambahkan sendiri, juga karena itu lebih pendek untuk diingat atau ketik jika Anda tidak melihat bahwa garis memblob sebenarnya adalah inti dari masalah ini; ketujuh lagi tidak menjawab pertanyaan (menggunakan ulimit untuk membatasi proses sebagai gantinya); yang kedelapan mencoba membuat Anda menginstal python; yang kesembilan berpikir kita semua sangat tidak kreatif dan akhirnya yang kesepuluh menulis program C ++ sendiri yang menyebabkan masalah yang sama dengan jawaban pilihan teratas.

Luc
sumber
solusi yang bagus. Satu-satunya kesalahan adalah bahwa kode keluar dari konstruk adalah 1 karena grep tidak menemukan kecocokan. Tak satu pun dari solusi dari stackoverflow.com/questions/6550484/… tampaknya dapat memperbaikinya.
Holger Brandl
@ HolgerBrandl Poin bagus, saya tidak akan tahu bagaimana cara memperbaikinya. Ini adalah pertama kalinya saya dengar set -e, jadi saya baru belajar sesuatu :)
Luc
$ DETIK sepertinya bukan pilihan yang baik karena ini adalah variabel bawaan yang mencerminkan waktu sejak shell dimulai. lihat tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl
@ HolgerBrandl Bagus, saya tidak tahu itu. Agak keren menemukan terminal yang terbuka untuk> 3 juta detik saat ini: D. Saya memperbarui pos.
Luc
Teknik keren! time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n(gunakan memori 10 GiB) membutuhkan waktu 1 menit 46 detik. Menjalankan program eatmemory julman99 di github.com/julman99/eatmemory membutuhkan waktu 6 detik. ... Ya, ditambah waktu unduh dan kompilasi, tetapi dikompilasi tanpa masalah ... dan sangat cepat ... di mesin RHEL6.4 saya. Tetap saja, saya suka solusi ini. Mengapa menemukan kembali roda?
Mike S
18

Saya menjaga fungsi untuk melakukan sesuatu yang serupa di dotfiles saya. https://github.com/sagotsky/.dotfiles/blob/master/.functions#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
}
Valadil
sumber
1
Ini adalah solusi IMHO terbaik, karena pada dasarnya hanya perlu dd untuk bekerja, semua hal lain dapat dikerjakan di shell apa pun. Perhatikan bahwa ia sebenarnya mengklaim memori dua kali lipat dari data yang dihasilkan, setidaknya untuk sementara. Diuji pada debian 9, dash 0.5.8-2.4. Jika Anda menggunakan bash untuk menjalankan bagian MEMBLOB, itu menjadi sangat lambat dan menggunakan empat kali jumlah yang dd hasilkan.
P.Péter
16

Bagaimana abount solusi python sederhana?

#!/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)
swiftcoder
sumber
7
Itu mungkin akan dengan cepat ditukar, memiliki dampak aktual yang sangat kecil pada tekanan memori (kecuali jika Anda mengisi semua swap juga, yang akan memakan waktu, biasanya)
Joachim Sauer
1
Mengapa unix swap sementara ada RAM yang tersedia? Ini sebenarnya cara yang masuk akal untuk mengusir cache disk saat dibutuhkan.
Alexander Shcheblikin
@AlexanderShcheblikin Pertanyaan ini bukan tentang mengusir cache disk (yang berguna untuk pengujian kinerja tetapi tidak untuk pengujian sumber daya rendah).
Gilles
1
Solusi ini berhasil menambah satu atau dua Gig dalam pengujian saya, meskipun saya tidak mencoba untuk menekankan memori saya. Tapi, @ JoachimSauer, seseorang dapat mengatur sysctl vm.swappiness=0dan selanjutnya mengatur vm.min_free_kbytes ke sejumlah kecil, mungkin 1024. Saya belum mencobanya, tetapi para dokter mengatakan bahwa ini adalah bagaimana Anda mengontrol kecepatan bertukar ... Anda harus mampu membuatnya sangat lambat, sampai menyebabkan kondisi OOM pada mesin Anda. Lihat kernel.org/doc/Documentation/sysctl/vm.txt dan kernel.org/doc/gorman/html/understand/understand005.html
Mike S
cukup satu liner untuk 1GB: python -c "x = (1 * 1024 * 1024 * 1024/8) * (0,); raw_input ()"
adrianlzt
10

Bagaimana dengan ramf jika ada? Pasang dan salin ke file besar? Jika tidak ada /dev/shmdan tidak ada ramf - saya kira program C kecil yang melakukan malloc besar berdasarkan pada beberapa nilai input? Mungkin harus menjalankannya beberapa kali sekaligus pada sistem 32 bit dengan banyak memori.

nemo
sumber
8

Jika Anda ingin menguji proses tertentu dengan memori terbatas, Anda mungkin lebih baik menggunakan ulimituntuk membatasi jumlah memori yang dapat dialokasikan.

sj26
sumber
2
Sebenarnya ini tidak bekerja di linux (tidak tahu tentang * nixes lain). 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.
Patrick
4

Saya pikir ini adalah kasus mengajukan pertanyaan yang salah dan kewarasan ditenggelamkan oleh orang-orang yang bersaing untuk mendapatkan jawaban paling kreatif. Jika Anda hanya perlu mensimulasikan kondisi OOM, Anda tidak perlu mengisi memori. Cukup gunakan pengalokasi khusus dan gagal setelah sejumlah alokasi tertentu. Pendekatan ini tampaknya bekerja cukup baik untuk SQLite .

Craig Barnes
sumber
3

Saya menulis program C ++ kecil ini untuk itu: https://github.com/rmetzger/dynamic-ballooner

Keuntungan dari implementasi ini adalah secara berkala memeriksa apakah perlu membebaskan atau mengalokasikan kembali memori.

Robert Metzger
sumber