Bagaimana cara kerja vm.overcommit_memory?

50

Ketika saya menggunakan pengaturan default:

vm.overcommit_memory = 0
vm.overcommit_ratio = 50

Saya dapat membaca nilai-nilai ini dari /proc/meminfofile:

CommitLimit:     2609604 kB
Committed_AS:    1579976 kB

Tetapi ketika saya berubah vm.overcommit_memorydari 0menjadi 2, saya tidak dapat memulai set aplikasi yang sama yang bisa saya mulai sebelum perubahan, terutama amarok. Saya harus mengubah vm.overcommit_ratioke 300, sehingga batasnya dapat ditingkatkan. Sekarang ketika saya memulai amarok, /proc/meminfomenunjukkan yang berikut:

CommitLimit:     5171884 kB
Committed_AS:    3929668 kB

Mesin ini hanya memiliki 1GiB RAM, tetapi amarok bekerja tanpa masalah ketika vm.overcommit_memorydiatur ke 0. Tetapi dalam hal mengaturnya 2, amarok perlu mengalokasikan lebih dari 2GiB memori. Apakah itu perilaku normal? Jika demikian, adakah yang bisa menjelaskan mengapa, misalnya, firefox (yang menghabiskan memori 4-6x lebih banyak dari amarok) bekerja dengan cara yang sama sebelum dan sesudah perubahan?

Mikhail Morfikov
sumber

Jawaban:

67

Anda dapat menemukan dokumentasi di man 5 proc( atau di kernel.org ):

/proc/sys/vm/overcommit_memory
       This file contains the kernel virtual memory accounting mode.
       Values are:

              0: heuristic overcommit (this is the default)
              1: always overcommit, never check
              2: always check, never overcommit

       In mode 0, calls of mmap(2) with MAP_NORESERVE are not
       checked, and the default check is very weak, leading to the
       risk of getting a process "OOM-killed".

       In mode 2 (available since Linux 2.6), the total virtual
       address space that can be allocated (CommitLimit in /proc/mem‐
       info) is calculated as

           CommitLimit = (total_RAM - total_huge_TLB) *
                         overcommit_ratio / 100 + total_swap

Jawaban sederhananya adalah bahwa pengaturan overcommit ke 1, akan mengatur tahap sehingga ketika suatu program memanggil sesuatu seperti malloc()mengalokasikan sepotong memori ( man 3 malloc), itu akan selalu berhasil terlepas jika sistem tahu itu tidak akan memiliki semua memori yang sedang meminta.

Konsep yang mendasarinya untuk dipahami adalah gagasan tentang memori virtual . Program melihat ruang alamat virtual yang mungkin, atau mungkin tidak, dipetakan ke memori fisik aktual. Dengan menonaktifkan pemeriksaan overcommit, Anda memberi tahu OS untuk hanya berasumsi bahwa selalu ada cukup memori fisik untuk membuat cadangan ruang virtual.

Contoh

Untuk menyoroti mengapa ini terkadang penting, lihat panduan Redis tentang mengapa vm.overcommit_memoryharus ditetapkan ke 1 untuk itu.

Kyle Brandt
sumber
2
Tetapi bukankah seharusnya nilainya Committed_ASsama dalam kedua kasus?
Mikhail Morfikov
@MikhailMorfikov: Secara teori, saya percaya begitu, tetapi siapa yang tahu apa yang sedang dilakukan program-program ini. Ingin melihat lingkungan yang lebih terkontrol dengan program sederhana yang hanya mengalokasikan mengatakan pertunjukan ram melalui Malloc. Dan kemudian jalankan tes setelah me-reboot antar tes.
Kyle Brandt
Ok, jadi saya akan tinggal bersama 0untuk saat ini.
Mikhail Morfikov
2
@MikhailMorfikov: Ya, praktis saya pikir 0 paling masuk akal. Di lingkungan saya, satu-satunya waktu saya mengaktifkan 1 adalah untuk Redis, yang melakukan hal-hal yang diharapkan memang meminta lebih banyak memori yang digunakan karena garpu (). Anak itu akan cukup banyak menggunakan semua halaman memori yang sama, tetapi Linux tidak tahu yang mengatakan aman itu harus mengasumsikan 2x memori akan digunakan (jika Anda ingin belajar lebih banyak: redis.io/topics/faq )
Kyle Brandt
bukankah seharusnya pernyataan terakhir dalam jawaban Anda dimulai seperti "dengan mengaktifkan overcommit"? karena mengaturnya ke 1 berarti Anda memintanya untuk berlebihan, bukan?
as