Saya bukan pengembang kernel, tetapi saya menghabiskan waktu bertahun-tahun berfilsafat tentang masalah ini karena saya sering bertemu dengan soooo ini. Saya sebenarnya datang dengan metafora untuk seluruh situasi jadi izinkan saya memberi tahu Anda hal itu. Saya akan berasumsi dalam cerita saya bahwa hal-hal seperti "swap" tidak ada. Swap tidak masuk akal dengan 32 GB RAM hari ini.
Bayangkan sebuah lingkungan Anda di mana air terhubung ke setiap bangunan melalui pipa dan kota-kota perlu mengelola kapasitas. Mari kita asumsikan bahwa Anda hanya memiliki produksi 100 unit air per detik (dan semua kapasitas yang tidak digunakan menjadi sia-sia karena Anda tidak memiliki tangki reservoir). Setiap rumah (rumah = aplikasi kecil, terminal, widget jam, dll.) Membutuhkan satu 1 unit air per detik. Ini semua bagus dan bagus karena populasi Anda sekitar 90 sehingga setiap orang mendapat cukup air.
Sekarang walikota (= Anda) memutuskan bahwa Anda ingin membuka restoran besar (= browser). Restoran ini akan menampung beberapa koki (= tab browser). Setiap juru masak membutuhkan 1 unit air per detik. Anda mulai dengan 10 juru masak, sehingga total konsumsi air untuk seluruh lingkungan adalah 100 unit air yang semuanya masih bagus.
Sekarang hal-hal menyenangkan dimulai: Anda menyewa juru masak lain ke restoran Anda yang membuat total kebutuhan air 101 yang jelas tidak Anda miliki. Anda perlu melakukan sesuatu.
Manajemen air (= kernel) memiliki 3 opsi.
1. Opsi pertama adalah putuskan sambungan layanan untuk rumah yang tidak menggunakan air baru-baru ini. Ini baik-baik saja tetapi jika rumah yang terputus ingin menggunakan air lagi, mereka harus melalui proses pendaftaran yang panjang lagi. Manajemen dapat memutuskan beberapa rumah untuk membebaskan lebih banyak sumber daya air. Sebenarnya, mereka akan memutus semua rumah yang tidak menggunakan air baru-baru ini sehingga menjaga sejumlah air gratis selalu tersedia.
Meskipun kota Anda terus berfungsi, downside adalah bahwa kemajuan terhenti. Sebagian besar waktu Anda dihabiskan untuk menunggu pengelolaan air untuk mengembalikan layanan Anda.
Inilah yang dilakukan kernel dengan halaman yang didukung file. Jika Anda menjalankan executable besar (seperti chrome), file tersebut akan disalin memori. Ketika kehabisan memori atau jika ada bagian yang belum diakses baru-baru ini, kernel akan dapat menjatuhkan bagian-bagian itu karena dapat memuatnya kembali dari disk. Jika ini dilakukan secara berlebihan, ini akan menghentikan desktop Anda karena semuanya akan menunggu disk IO. Perhatikan bahwa kernel juga akan menjatuhkan banyak halaman yang paling baru digunakan ketika Anda mulai melakukan banyak IO. Inilah sebabnya mengapa perlu waktu lama untuk beralih ke aplikasi latar belakang setelah Anda menyalin beberapa file besar seperti gambar DVD.
Ini adalah perilaku yang paling menyebalkan bagi saya karena saya benci hickups dan Anda tidak punya kendali atasnya. Akan lebih baik untuk dapat mematikannya. Saya sedang memikirkan sesuatu
sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c
dan kemudian Anda bisa mengatur vm_swappiness ke -1 untuk menonaktifkan ini. Ini bekerja cukup baik dalam pengujian kecil saya tetapi sayangnya saya bukan pengembang kernel jadi saya tidak mengirimkannya kepada siapa pun (dan jelas modifikasi kecil di atas tidak lengkap).
2.Manajemen bisa menolak permintaan juru masak baru untuk air. Ini awalnya terdengar seperti ide yang bagus. Namun ada dua kelemahan. Pertama, ada perusahaan yang meminta banyak langganan air meskipun mereka tidak menggunakannya. Salah satu alasan yang mungkin untuk melakukan ini adalah untuk menghindari semua biaya overhead berbicara dengan manajemen air setiap kali mereka membutuhkan air tambahan. Penggunaan air mereka naik dan turun tergantung pada waktu hari itu. Misalnya dalam kasus restoran, perusahaan membutuhkan lebih banyak air pada siang hari dibandingkan dengan tengah malam. Jadi mereka meminta semua air yang mungkin mereka gunakan tetapi membuang alokasi air selama tengah malam. Masalahnya adalah bahwa tidak semua perusahaan dapat memperkirakan penggunaan puncaknya dengan benar sehingga mereka meminta lebih banyak dengan harapan mereka tidak perlu khawatir tentang meminta lebih banyak.
Inilah yang dilakukan mesin virtual Java: ia mengalokasikan banyak memori pada startup dan kemudian bekerja darinya. Secara default kernel hanya akan mengalokasikan memori ketika aplikasi Java Anda benar-benar mulai menggunakannya. Namun jika Anda menonaktifkan overcommit, kernel akan menganggap serius reservasi. Itu hanya akan memungkinkan alokasi untuk berhasil jika benar-benar memiliki sumber daya untuk itu.
Namun, ada satu masalah lain yang lebih serius dengan pendekatan ini. Katakanlah satu perusahaan mulai meminta satu unit air setiap hari (bukan dalam langkah 10). Akhirnya Anda akan mencapai keadaan di mana Anda memiliki 0 unit gratis. Sekarang perusahaan ini tidak akan dapat mengalokasikan lebih banyak. Tidak masalah, siapa yang peduli tentang perusahaan besar. Tetapi masalahnya adalah bahwa rumah-rumah kecil juga tidak akan dapat meminta lebih banyak air! Anda tidak akan dapat membangun kamar mandi umum kecil untuk menghadapi kedatangan wisatawan yang tiba-tiba. Anda tidak akan dapat menyediakan air darurat untuk kebakaran di hutan terdekat.
Dalam istilah komputer: Dalam situasi memori sangat rendah tanpa overcommit Anda tidak akan dapat membuka xterm baru, Anda tidak akan dapat ssh ke dalam mesin Anda, Anda tidak akan dapat membuka tab baru untuk mencari kemungkinan perbaikan. Dengan kata lain menonaktifkan overcommit juga membuat desktop Anda menjadi tidak berguna saat kehabisan memori.
3. Sekarang inilah cara menarik untuk menangani masalah ketika perusahaan mulai menggunakan terlalu banyak air. Manajemen air merusaknya! Secara harfiah: ia pergi ke situs restoran, melemparkan dinamit ke dalamnya dan menunggu sampai meledak. Ini akan mengurangi banyak kebutuhan air kota secara instan sehingga orang baru dapat pindah, Anda dapat membuat kamar mandi umum, dll. Anda, sebagai walikota, dapat membangun kembali restoran dengan harapan bahwa kali ini akan membutuhkan lebih sedikit air. Misalnya Anda akan memberi tahu orang-orang untuk tidak masuk ke restoran jika sudah terlalu banyak orang di dalamnya (mis. Anda akan membuka lebih sedikit tab browser).
Ini sebenarnya yang dilakukan kernel ketika kehabisan semua opsi dan membutuhkan memori: ia memanggil pembunuh OOM. Ini mengambil aplikasi besar (berdasarkan banyak heuristik) dan membunuhnya, membebaskan banyak memori tetapi mempertahankan desktop yang responsif. Sebenarnya kernel Android melakukan ini bahkan lebih agresif: itu membunuh aplikasi yang paling baru digunakan ketika memori rendah (dibandingkan dengan kernel stock yang melakukannya hanya sebagai pilihan terakhir). Ini disebut Pembunuh Viking di Android.
Saya pikir ini adalah salah satu solusi paling sederhana untuk masalah ini: tidak seperti Anda memiliki lebih banyak pilihan daripada ini, jadi mengapa tidak menyelesaikannya lebih cepat daripada nanti, kan? Masalahnya adalah bahwa kernel kadang-kadang melakukan cukup banyak pekerjaan untuk menghindari memanggil pembunuh OOM. Itu sebabnya Anda melihat bahwa desktop Anda sangat lambat dan kernel tidak melakukan apa-apa. Tapi untungnya ada opsi untuk memanggil pembunuh OOM sendiri! Pertama, pastikan kunci sysrq ajaib diaktifkan (mis. echo 1 | sudo tee
/proc/sys/kernel/sysrq
) Maka setiap kali Anda merasa bahwa kernel kehabisan memori, cukup tekan Alt + SysRQ, Alt + f.
OK jadi semua itu bagus tetapi Anda ingin mencobanya? Situasi memori rendah sangat mudah untuk mereproduksi. Saya punya aplikasi yang sangat sederhana untuk itu. Anda harus menjalankannya dua kali. Proses pertama akan menentukan berapa banyak RAM gratis yang Anda miliki, proses kedua akan membuat situasi memori rendah. Perhatikan bahwa metode ini mengasumsikan bahwa swap Anda dinonaktifkan (mis. Lakukan a sudo swapoff -a
). Kode dan penggunaannya sebagai berikut:
// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int limit = 123456789;
if (argc >= 2) {
limit = atoi(argv[1]);
}
setbuf(stdout, NULL);
for (int i = 1; i <= limit; i++) {
memset(malloc(1 << 20), 1, 1 << 20);
printf("\rAllocated %5d MiB.", i);
}
sleep(10000);
return 0;
}
Dan inilah cara Anda menggunakannya:
$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed
Doa pertama mendeteksi bahwa kami memiliki 31,118 MiB RAM gratis. Jadi saya katakan aplikasi untuk mengalokasikan 31.110 MiB RAM sehingga kernel tidak akan membunuhnya tetapi memakan hampir semua memori saya. Sistem saya membeku: bahkan pointer mouse tidak bergerak. Saya telah menekan Alt + SysRQ, Alt + f dan itu membunuh proses eatmem saya dan sistem pulih.
Meskipun kita membahas opsi-opsi kita apa yang dilakukan dalam situasi memori rendah, pendekatan terbaik (seperti situasi berbahaya lainnya) adalah untuk menghindarinya sejak awal. Ada banyak cara untuk melakukan ini. Salah satu cara umum yang saya lihat adalah untuk menempatkan aplikasi yang keliru (seperti browser) ke dalam wadah yang berbeda dari sistem lainnya. Dalam hal ini browser tidak akan dapat mempengaruhi desktop Anda. Tetapi pencegahan itu sendiri berada di luar ruang lingkup pertanyaan sehingga saya tidak akan menulis tentang itu.
TL; DR: Meskipun saat ini tidak ada cara untuk sepenuhnya menghindari paging, Anda dapat mengurangi penghentian sistem sepenuhnya dengan menonaktifkan overcommit. Tetapi sistem Anda akan tetap tidak dapat digunakan selama situasi memori rendah tetapi dengan cara yang berbeda. Terlepas dari di atas, dalam situasi dengan memori rendah tekan Alt + SysRQ, Alt + f untuk mematikan proses besar pemilihan kernel. Sistem Anda harus mengembalikan responsnya setelah beberapa detik. Ini mengasumsikan Anda memiliki kunci sysrq ajaib diaktifkan (tidak secara default).