Solusi 1:
Pengaturan overcommit_ratio
ke 80 sepertinya bukan tindakan yang tepat. Menyetel nilai ke kurang dari 100 hampir selalu salah.
Alasannya adalah aplikasi linux mengalokasikan lebih dari yang sebenarnya mereka butuhkan. Katakanlah mereka mengalokasikan 8kb untuk menyimpan beberapa karakter string teks. Nah itulah beberapa KB yang tidak terpakai disana. Aplikasi sering melakukan ini, dan untuk inilah overcommit dirancang.
Jadi pada dasarnya dengan overcommit pada 100, kernel tidak akan mengizinkan aplikasi mengalokasikan lebih banyak memori daripada yang Anda miliki (swap + ram). Mengaturnya kurang dari 100 berarti Anda tidak akan pernah menggunakan semua memori Anda. Jika Anda akan menyetel setelan ini, Anda harus menyetelnya lebih tinggi dari 100 karena skenario yang disebutkan sebelumnya, yang cukup umum.
Sekarang, untuk masalah Anda dengan pemicu OOM killer, pengaturan overcommit secara manual kemungkinan besar tidak akan memperbaikinya. Pengaturan default (penentuan heuristik) cukup cerdas.
Jika Anda ingin mengetahui apakah ini benar-benar penyebab masalahnya, lihat /proc/meminfo
saat pembunuh OOM berjalan. Jika Anda melihat Committed_AS
itu dekat dengan CommitLimit
, tetapi free
masih menunjukkan memori kosong yang tersedia, maka ya Anda dapat menyesuaikan overcommit secara manual untuk skenario Anda. Menyetel nilai ini terlalu rendah akan menyebabkan pembunuh OOM mulai mematikan aplikasi saat Anda masih memiliki banyak memori kosong. Menyetelnya terlalu tinggi dapat menyebabkan aplikasi acak mati saat mereka mencoba menggunakan memori yang dialokasikan, tetapi sebenarnya tidak tersedia (ketika semua memori benar-benar habis).
Solusi 2:
Bagian 9.6 "Overcommit dan OOM" dalam dokumen yang disebutkan oleh @dunxd sangat jelas tentang bahaya mengizinkan overcommit. Namun, 80
tampak menarik bagi saya juga, jadi saya melakukan beberapa pengujian.
Apa yang saya temukan adalah overcommit_ratio
mempengaruhi total RAM yang tersedia untuk SEMUA proses. Proses root tampaknya tidak diperlakukan berbeda dari proses pengguna normal.
Mengatur rasio ke 100
atau kurang harus menyediakan semantik klasik tempat mengembalikan nilai dari malloc/sbrk
dapat diandalkan. Mengatur rasionya lebih rendah dari 100
mungkin merupakan cara untuk mencadangkan lebih banyak RAM untuk aktivitas non-proses seperti caching dan sebagainya.
Jadi, di komputer saya dengan RAM 24 GiB, dengan swap dinonaktifkan, 9 GiB sedang digunakan, dengan top
menunjukkan
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
Berikut adalah beberapa overcommit_ratio
pengaturan dan berapa banyak RAM yang dapat diambil oleh program konsumen ram saya (menyentuh setiap halaman) - dalam setiap kasus program keluar dengan bersih sekali malloc
gagal.
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
Menjalankan beberapa sekaligus, bahkan dengan beberapa sebagai pengguna root, tidak mengubah jumlah total yang mereka konsumsi bersama. Sangat menarik bahwa ia tidak dapat mengkonsumsi 3+ GiB terakhir atau lebih; free
tidak turun jauh di bawah apa yang ditampilkan di sini:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Eksperimennya berantakan - apa pun yang menggunakan malloc saat ini semua RAM sedang digunakan cenderung macet, karena banyak programmer yang sangat buruk dalam memeriksa kegagalan malloc di C, beberapa perpustakaan koleksi populer mengabaikannya sepenuhnya, dan C ++ dan berbagai bahasa lainnya bahkan lebih buruk.
Sebagian besar implementasi awal RAM imajiner yang saya lihat adalah untuk menangani kasus yang sangat spesifik, di mana satu proses besar - katakanlah 51%+ dari memori yang tersedia - diperlukan untuk fork()
untuk exec()
beberapa program pendukung, biasanya yang jauh lebih kecil. OS dengan semantik copy-on-write akan mengizinkan fork()
, tetapi dengan ketentuan bahwa jika proses bercabang benar-benar mencoba memodifikasi terlalu banyak halaman memori (masing-masing halaman harus dibuat sebagai halaman baru yang terpisah dari proses besar awal) proses tersebut akan berakhir dengan terbunuh. Proses induk hanya dalam bahaya jika mengalokasikan lebih banyak memori, dan dapat menangani kehabisan, dalam beberapa kasus hanya dengan menunggu sebentar sampai beberapa proses lain mati, dan kemudian melanjutkan. Proses anak biasanya hanya menggantikan dirinya sendiri dengan program (biasanya lebih kecil) melalui exec()
dan kemudian bebas dari ketentuan.
Konsep overcommit Linux adalah pendekatan ekstrem untuk memungkinkan fork()
terjadi serta memungkinkan proses tunggal untuk mengalokasi secara besar-besaran. Kematian yang disebabkan oleh OOM terjadi secara asinkron, bahkan pada program yang melakukannya menangani alokasi memori secara bertanggung jawab. Saya pribadi benci di seluruh sistem overcommit secara umum dan oom-killer pada khususnya - ini memupuk pendekatan yang sangat peduli terhadap manajemen memori yang menginfeksi perpustakaan dan melaluinya setiap aplikasi yang menggunakannya.
Saya sarankan mengatur rasio ke 100, dan memiliki partisi swap juga yang umumnya hanya akan digunakan oleh proses besar - yang seringkali hanya menggunakan sebagian kecil dari bagian dirinya yang dimasukkan ke dalam swap, dan dengan demikian melindungi sebagian besar proses dari kesalahan fitur pembunuh OOM. Ini akan menjaga server web Anda aman dari kematian acak, dan jika ditulis untuk menangani malloc
bertanggung jawab, bahkan aman dari bunuh diri (tetapi jangan bertaruh pada yang terakhir).
Itu berarti saya menggunakan ini di /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100