GNU/Linux >> Belajar Linux >  >> Linux

Mengapa sistem Linux saya gagap kecuali saya terus-menerus menjatuhkan cache?

Sepertinya Anda sudah mencoba banyak hal yang saya sarankan pada awalnya (menyesuaikan konfigurasi swap, mengubah penjadwal I/O, dll).

Selain dari apa yang sudah Anda coba ubah, saya sarankan untuk melihat ke dalam mengubah default yang agak mati otak untuk perilaku writeback VM. Ini dikelola oleh enam nilai sysctl berikut:

  • vm.dirty_ratio :Mengontrol berapa banyak penulisan yang harus ditunda untuk penulisan kembali sebelum dipicu. Menangani writeback latar depan (per-proses), dan dinyatakan sebagai persentase bilangan bulat dari RAM. Standarnya adalah 10% dari RAM
  • vm.dirty_background_ratio :Mengontrol berapa banyak penulisan yang harus ditunda untuk penulisan kembali sebelum dipicu. Menangani writeback latar belakang (seluruh sistem), dan dinyatakan sebagai persentase bilangan bulat dari RAM. Standarnya adalah 20% dari RAM
  • vm.dirty_bytes :Sama seperti vm.dirty_ratio , kecuali dinyatakan sebagai jumlah total byte. Entah ini atau vm.dirty_ratio akan digunakan, mana yang ditulis terakhir.
  • vm.dirty_background_bytes :Sama seperti vm.dirty_background_ratio , kecuali dinyatakan sebagai jumlah total byte. Entah ini atau vm.dirty_background_ratio akan digunakan, mana yang ditulis terakhir.
  • vm.dirty_expire_centisecs :Berapa seperseratus detik harus berlalu sebelum pending writeback dimulai ketika keempat nilai sysctl di atas belum memicunya. Default ke 100 (satu detik).
  • vm.dirty_writeback_centisecs :Seberapa sering (dalam seperseratus detik) kernel akan mengevaluasi halaman kotor untuk ditulis kembali. Default ke 10 (sepersepuluh detik).

Jadi, dengan nilai default, setiap sepersepuluh detik, kernel akan melakukan hal berikut:

  • Tulis halaman yang dimodifikasi ke penyimpanan persisten jika terakhir diubah lebih dari satu detik yang lalu.
  • Tulis semua halaman yang dimodifikasi untuk suatu proses jika jumlah total memori yang dimodifikasi yang belum ditulis melebihi 10% dari RAM.
  • Tulis semua halaman yang dimodifikasi dalam sistem jika jumlah total memori yang dimodifikasi yang belum ditulis melebihi 20% dari RAM.

Jadi, seharusnya cukup mudah untuk melihat mengapa nilai default dapat menyebabkan masalah bagi Anda, karena sistem Anda mungkin mencoba menulis hingga 4 gigabyte data ke penyimpanan persisten setiap kesepuluh detik.

Konsensus umum saat ini adalah menyesuaikan vm.dirty_ratio menjadi 1% dari RAM, dan vm.dirty_background_ratio menjadi 2%, yang untuk sistem dengan RAM kurang dari 64 GB menghasilkan perilaku yang setara dengan apa yang awalnya dimaksudkan.

Beberapa hal lain yang perlu diperhatikan:

  • Coba tingkatkan vm.vfs_cache_pressure sysctl sedikit. Ini mengontrol seberapa agresif kernel mengambil kembali memori dari cache sistem file ketika membutuhkan RAM. Standarnya adalah 100, jangan turunkan ke bawah 50 (Anda akan mendapatkan perilaku yang sangat buruk jika Anda berada di bawah 50, termasuk kondisi OOM), dan jangan menaikkannya menjadi lebih dari sekitar 200 (jauh lebih tinggi, dan kernel akan membuang waktu untuk mencoba mendapatkan kembali memori yang sebenarnya tidak bisa). Saya telah menemukan bahwa meningkatkannya hingga 150 benar-benar meningkatkan daya tanggap jika Anda memiliki penyimpanan yang cukup cepat.
  • Coba ubah mode overcommit memori. Ini dapat dilakukan dengan mengubah nilai vm.overcommit_memory sysctl. Secara default, kernel akan menggunakan pendekatan heuristik untuk mencoba dan memprediksi berapa banyak RAM yang benar-benar mampu dikomit. Menyetel ini ke 1 menonaktifkan heuristik dan memberi tahu kernel untuk bertindak seolah-olah memiliki memori tak terbatas. Menyetel ini ke 2 memberi tahu kernel untuk tidak menggunakan lebih banyak memori daripada jumlah total ruang swap pada sistem ditambah persentase RAM sebenarnya (dikontrol oleh vm.overcommit_ratio ).
  • Coba sesuaikan vm.page-cluster sysctl. Ini mengontrol berapa banyak halaman yang ditukar masuk atau keluar pada satu waktu (ini adalah nilai logaritma basis-2, jadi default dari 3 diterjemahkan menjadi 8 halaman). Jika Anda benar-benar bertukar, hal ini dapat membantu meningkatkan kinerja pertukaran masuk dan keluar halaman.

Masalah telah ditemukan!

Ternyata itu adalah masalah kinerja di reclaimer memori Linux ketika ada sejumlah besar kontainer/grup memori. (Penafian:penjelasan saya mungkin cacat, saya bukan pengembang kernel.) Masalah telah diperbaiki di 4.19-rc1+ di set tambalan ini:

Patchset ini memecahkan masalah dengan slow shrink_slab() yang terjadi pada mesin yang memiliki banyak shrinkers dan cgroup memori (yaitu, dengan banyak container). Masalahnya adalah kompleksitas shrink_slab() adalah O(n^2) dan tumbuh terlalu cepat dengan pertumbuhan jumlah penampung.

Mari kita memiliki 200 kontainer, dan setiap kontainer memiliki 10 tunggangan dan 10cgroup. Semua tugas kontainer diisolasi, dan tidak menyentuh tunggangan kontainer asing.

Dalam kasus reklamasi global, tugas harus mengulangi seluruh memcgs dan memanggil semua penyusutan yang sadar memcg untuk semuanya. Artinya, tugas harus mengunjungi 200 * 10 =2000 shrinkers untuk setiap memcg, dan karena ada 2000 memcg, total panggilan do_shrink_slab() adalah 2000 *2000 =4000000.

Sistem saya sangat terpukul, karena saya menjalankan banyak container, yang mungkin menyebabkan munculnya masalah.

Langkah pemecahan masalah saya, jika berguna bagi siapa pun yang menghadapi masalah serupa:

  1. Perhatikan kswapd0 menggunakan banyak CPU saat komputer saya gagap
  2. Coba hentikan wadah Docker dan isi memori lagi → komputer tidak gagap!
  3. Jalankan ftrace (mengikuti blog penjelasan luar biasa Julia Evan) untuk mendapatkan jejak, lihat bahwa kswapd0 cenderung macet di shrink_slab , super_cache_count , dan list_lru_count_one .
  4. Google shrink_slab lru slow , temukan patchset!
  5. Beralihlah ke Linux 4.19-rc3 dan verifikasi bahwa masalah telah diperbaiki.

Linux
  1. Linux – Bagaimana Gnome Reboot Tanpa Hak Root?

  2. Linux – Mengapa Linux Mengizinkan 'init=/bin/bash'?

  3. Linux – Mengapa Setuid Tidak Bekerja??

  1. Linux – Mengapa Es_mx Lokal Bekerja Tapi Tidak Es?

  2. Linux – Mengapa Perlu Waktu Lama Untuk Mendeteksi Usb Stick?

  3. Apakah Thundering Herd Problem ada lagi di Linux?

  1. Mengapa preprosesor C mengartikan kata linux sebagai konstanta 1?

  2. Mengapa popen() memanggil shell untuk mengeksekusi suatu proses?

  3. Mengapa sistem saya hanya menampilkan RAM 3,2 GiB padahal saya pasti memiliki 4,0 GiB