Bagaimana saya bisa membatasi jumlah memori yang tersedia untuk suatu proses?

11

Saya sedang mengembangkan program; kadang-kadang berakhir mengalokasikan jumlah memori yang sangat besar (>> 10G pada mesin dengan memori fisik 8G), menyebabkan sistem menjadi tidak responsif. Saya ingin membatasi jumlah memori yang dapat dialokasikan oleh proses. Cara yang biasa saya lakukan adalah:

ulimit -m 4000000 ; ./myprogram

... yang seharusnya mematikan program saya jika mencoba menggunakan lebih dari 4GB memori.

Pada OS X El Capitan ini tampaknya tidak berpengaruh; bahkan ulimit -m 1(membatasi semua program hanya dengan memori 1kB!) tidak efektif.

Bagaimana saya bisa mengatur batas atas pada memori yang tersedia untuk proses tertentu?

callallen
sumber
Ketika Anda mengatakan dengan cara yang biasa saya lakukan ini , apa maksud Anda? Lebih khusus, kapan Anda biasanya melakukan ini? Dan ketika Anda melakukannya, maksud Anda di dalam Mac OS X El Capitan atau di lingkungan lain? Bisakah Anda memberi contoh kapan Anda berhasil menggunakannya? Pada dasarnya, saya hanya mencoba menjelaskan apakah proses ini bekerja untuk Anda secara normal, tetapi tidak berfungsi untuk program khusus ini? Atau apakah itu tidak bekerja untuk Anda sama sekali tetapi Anda pikir itu harus?
Monomeeth
1
Dengan "cara biasa saya akan melakukan ini", maksud saya cara saya akan melakukan ini pada rasa unix lainnya. Saya perhatikan bahwa saya baru saja menemukan bahwa ulimit -mtidak lagi berfungsi di Linux (> 2.4.30), meskipun ulimit -vmasih berfungsi seperti yang diharapkan. (Seperti ulimit -m, ulimit -vjuga tampaknya tidak berpengaruh pada OS X.)
cpcallen
Kedengarannya seperti Anda memiliki kebocoran memori dalam program yang Anda tulis dan perlu melakukan pengumpulan sampah yang lebih baik. Sudahkah Anda membaca tentang manajemen memori?
Todd Dabney
1
Tidak, bukan kebocoran memori — hanya pencarian grafik dari ruang keadaan yang berpotensi sangat besar. Saya dapat menambahkan kode untuk membatalkan pencarian jika berbagai struktur internal menjadi terlalu besar, tetapi saya berharap dapat melakukan hal yang sama (mencegah mesin terjepit oleh input besar) dengan shell one-liner.
cpcallen

Jawaban:

1

Ada dua pendekatan untuk membatasi penggunaan memori Anda: Ex post facto, dan preemptive. Artinya, Anda dapat mencoba untuk mematikan program Anda setelah terlalu besar, atau Anda dapat memprogramnya untuk tidak menjadi terlalu besar.

Jika Anda bersikeras pada pendekatan ex post facto, Anda dapat menggunakan skrip Bash berikut. Script ini pertama-tama menemukan jumlah memori (seperti yang didefinisikan oleh "resident set size") yang digunakan oleh prosesid pid, memfilter semua data non numerik menggunakan grep, dan menyimpan jumlahnya sebagai variabel n. Script kemudian memeriksa apakah n lebih besar dari x yang Anda tentukan. Jika ya, proses dengan pid prosesi terbunuh.

Tolong dicatat:

  1. Anda harus mengganti <pid>dengan id proses program Anda.
  2. Anda harus mengganti <x>dengan rss = "resident set size" (yaitu ukuran memori sebenarnya) yang tidak Anda inginkan melebihi program.

n=$(ps -<pid> -o rss | grep '[0-9]') if [ $n -gt <x> ]; then kill -9 <pid>; fi

Jika Anda ingin ini berjalan setiap y detik, cukup masukkan dalam satu lingkaran, dan katakan itu untuk menunggu y detik setelah setiap iterasi. Anda juga bisa menulis perintah serupa menggunakan top. Titik awal Anda adalah top -l 1|grep "<pid>"|awk '{print $10}'.

@ kenorb ini jawabannya membantu saya dengan naskah saya


Sementara saya percaya bahwa menjawab pertanyaan, dalam jangka panjang saya percaya itu adalah desain pemrograman yang lebih baik untuk mengambil pendekatan preemptive menggunakan alokasi memori manual.

Pertama, apakah Anda yakin penggunaan memori benar-benar masalah? Dokumentasi Go menyatakan:

Pengalokasi memori Go mencadangkan wilayah besar memori virtual sebagai arena alokasi. Memori virtual ini bersifat lokal untuk proses Go tertentu; reservasi tidak menghilangkan proses memori lainnya.

Jika Anda masih berpikir Anda memiliki masalah, maka saya mendorong Anda untuk mengelola memori secara manual seperti yang dilakukan dalam bahasa pemrograman C. Karena go ditulis dalam C, saya curiga akan ada cara untuk masuk ke manajemen / alokasi memori C, dan memang ada. Lihat repositori github ini yang,

memungkinkan Anda melakukan manajemen memori manual melalui pengalokasi C standar untuk sistem Anda. Ini adalah pembungkus tipis di atas malloc, calloc dan bebas dari. Lihat man malloc untuk detail tentang fungsi-fungsi ini untuk sistem Anda. Perpustakaan ini menggunakan cgo.

Kasus penggunaan diberikan sebagai:

Mengapa Anda menginginkan ini?

Ketika suatu program menyebabkan tekanan memori atau sistem kehabisan memori, akan sangat membantu untuk secara manual mengontrol alokasi dan deallokasi memori. Go dapat membantu Anda mengontrol alokasi tetapi tidak mungkin untuk secara eksplisit membatalkan alokasi data yang tidak diperlukan.

Ini sepertinya solusi jangka panjang yang lebih baik.

Jika Anda ingin mempelajari lebih lanjut tentang C (termasuk manajemen memori), Bahasa Pemrograman C adalah referensi standar.

Evan Rosica
sumber
Saya yakin bahwa penggunaan memori benar-benar masalah. Ketika program tiba-tiba tumbuh menjadi> 2x ukuran memori fisik, mesin menjadi hampir seluruhnya tidak responsif karena meronta-ronta halaman. Butuh sekitar satu jam antara saat saya menekan ^ C dan ketika macOS kembali merespons klik mouse; sementara itu satu-satunya bukti bahwa itu tidak beku adalah suara tenang dari hard drive dengan cepat berdetak.
callallen
Ini mungkin solusi yang masuk akal dalam praktiknya, tetapi tidak seperti ulimit pada OS UNIX (non-Darwin), ini tergantung pada kemampuan untuk mengalokasikan memori yang cukup secara tepat waktu agar berhasil menjalankan perintah kill. Saya lebih suka menerapkan batasan ukuran proses oleh kernel.
cpcallen
@cpcallen melakukan beberapa pencarian sepertinya "-m parameter to ulimit tidak berpengaruh pada sistem Linux dengan versi kernel yang lebih baru dari 2.4.30." Tampaknya OSX juga menerima perubahan ini. Coba opsi -v untuk membatasi ruang alamat
Evan Rosica