Bagian 9.6 "Komitmen berlebihan dan OOM" dalam dokumen yang menyebutkan @dunxd secara khusus menggambarkan bahaya dari mengizinkan komitmen berlebihan. Namun, itu 80
tampak menarik bagi saya juga, jadi saya melakukan beberapa tes.
Apa yang saya temukan adalah bahwa 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 memberikan semantik klasik di mana nilai kembali dari malloc/sbrk
dapat diandalkan. Pengaturan rasio lebih rendah daripada 100
mungkin cara untuk memesan lebih banyak RAM untuk kegiatan non-proses seperti caching dan sebagainya.
Jadi, di komputer saya dengan 24 GiB RAM, dengan swap dinonaktifkan, 9 GiB digunakan, dengan top
ditampilkan
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 bisa diambil oleh program ram-konsumen saya (menyentuh setiap halaman) - dalam setiap kasus program keluar dengan bersih begitu 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 itu tidak dapat mengkonsumsi 3+ GiB terakhir atau lebih; yang free
tidak menjatuhkan jauh di bawah apa yang ditampilkan di sini:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Eksperimen itu berantakan - apa pun yang menggunakan malloc pada saat ini semua RAM yang digunakan cenderung macet, karena banyak programmer yang mengerikan untuk 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% + memori yang tersedia - diperlukan fork()
untuk exec()
beberapa program pendukung, biasanya yang jauh, jauh lebih kecil. OS dengan semantik copy-on-write akan memungkinkan fork()
, tetapi dengan ketentuan bahwa jika proses bercabang benar-benar mencoba untuk memodifikasi terlalu banyak halaman memori (masing-masing kemudian harus dipakai sebagai halaman baru yang independen dari proses besar awal) itu akan berakhir terbunuh. Proses induk hanya dalam bahaya jika mengalokasikan lebih banyak memori, dan dapat menangani kehabisan, dalam beberapa kasus hanya dengan menunggu sedikit proses lain mati, dan kemudian melanjutkan. Proses anak biasanya hanya mengganti sendiri dengan program (biasanya lebih kecil) viaexec()
dan kemudian bebas dari ketentuan.
Konsep overcommit Linux adalah pendekatan ekstrem untuk memungkinkan fork()
terjadinya dan juga proses tunggal secara keseluruhan. Kematian OOM-pembunuh-disebabkan terjadi asynchronous, bahkan untuk program yang melakukan alokasi memori menangani secara bertanggung jawab. Saya pribadi benci overcommit seluruh sistem secara umum dan oom-killer pada khususnya - itu mendorong pendekatan setan-hati untuk manajemen memori yang menginfeksi perpustakaan dan melalui mereka setiap aplikasi yang menggunakannya.
Saya sarankan untuk mengatur rasio ke 100, dan memiliki partisi swap juga yang umumnya hanya akan berakhir digunakan oleh proses besar - yang sering hanya menggunakan sebagian kecil dari bagian diri mereka yang dimasukkan ke dalam swap, dan dengan demikian melindungi sebagian besar proses dari kesalahan pembunuh OOM. Ini harus menjaga server web Anda aman dari kematian acak, dan jika itu ditulis untuk menangani secara malloc
bertanggung jawab, bahkan aman dari membunuh sendiri (tetapi jangan bertaruh pada yang terakhir).
Itu berarti saya menggunakan ini /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100