Misalkan sebuah program meminta beberapa memori, tetapi tidak ada cukup memori yang tersisa. Ada beberapa cara berbeda yang dapat ditanggapi oleh Linux. Salah satu tanggapannya adalah memilih beberapa memori bekas lainnya, yang belum diakses baru-baru ini, dan pindahkan memori tidak aktif ini untuk bertukar.
Namun, saya melihat banyak artikel dan komentar yang melampaui ini. Mereka mengatakan bahkan ketika ada sejumlah besar memori bebas, Linux terkadang memutuskan untuk menulis memori tidak aktif untuk ditukar. Menulis ke swap terlebih dahulu berarti bahwa ketika kita ingin menggunakan memori ini, kita tidak perlu menunggu penulisan disk. Mereka mengatakan ini adalah strategi yang disengaja untuk mengoptimalkan kinerja.
Apakah mereka benar? Ataukah itu mitos? Kutip sumber Anda.
Harap pahami pertanyaan ini menggunakan definisi berikut:
- tukar
- gratis memori – memori “bebas” yang ditampilkan oleh perintah bebas. Ini adalah
MemFree
nilai dari/proc/meminfo
./proc/meminfo
adalah file teks virtual yang disediakan oleh kernel. Lihat proc(5), atau dokumen RHEL. - bahkan ketika ada banyak memori kosong – untuk tujuan argumen, bayangkan ada lebih dari 10% memori bebas.
Referensi
Berikut adalah beberapa istilah pencarian:linux "swap oportunistik" ATAU (swap "ketika sistem tidak ada yang lebih baik untuk dilakukan" ATAU "ketika tidak ada yang lebih baik untuk dilakukan" ATAU "ketika sistem idle" ATAU "selama waktu idle")
Dalam hasil tertinggi kedua di Google, pengguna StackExchange bertanya “Mengapa menggunakan swap ketika ada lebih dari cukup ruang kosong di RAM?”, dan menyalin hasil free
perintah yang menunjukkan sekitar 20% memori bebas. Menanggapi pertanyaan khusus ini, saya melihat jawaban ini sangat dipilih:
Linux mulai bertukar sebelum RAM terisi. Hal ini dilakukan untuk
meningkatkan kinerja dan daya tanggap:
Performa meningkat karena terkadang RAM lebih baik digunakan untuk cache disk daripada untuk menyimpan memori program. Jadi lebih baik untuk menukar
program yang sudah lama tidak aktif, dan menyimpan file
yang sering digunakan dalam cache.Responsivitas ditingkatkan dengan menukar halaman saat sistem idle, bukan saat memori penuh dan beberapa program sedang berjalan
dan meminta lebih banyak RAM untuk menyelesaikan tugas.Bertukar memang memperlambat sistem, tentu saja — tetapi alternatif untuk
bertukar bukanlah tidak menukar, melainkan memiliki lebih banyak RAM atau menggunakan lebih sedikit RAM.
Hasil pertama di Google telah ditandai sebagai duplikat dari pertanyaan di atas :-). Dalam hal ini, penanya menyalin detail yang menunjukkan 7GB MemFree
, dari 16GB. Pertanyaan memiliki jawaban yang diterima dan dipilih sendiri:
Bertukar hanya ketika tidak ada memori kosong hanya terjadi jika Anda mengatur
swappiness
ke 0. Jika tidak, selama waktu idle, kernel akan menukar memori. Dalam melakukan ini, data tidak dihapus dari memori, melainkan salinan dibuat di partisi swap.Ini berarti bahwa, jika muncul situasi bahwa memori habis, ia tidak harus menulis ke disk saat itu juga. Dalam hal ini kernel hanya dapat menimpa halaman memori yang telah ditukar, yang diketahui memiliki salinan datanya.
swappiness
parameter pada dasarnya hanya mengontrol seberapa banyak ia melakukan ini.
Kutipan lainnya tidak secara eksplisit mengklaim bahwa data yang ditukar disimpan dalam memori juga. Tapi sepertinya Anda lebih suka pendekatan itu, jika Anda menukar bahkan saat Anda memiliki 20% memori bebas, dan alasan Anda melakukannya adalah untuk meningkatkan kinerja.
Sejauh yang saya tahu, Linux mendukung penyimpanan salinan data yang sama di memori utama dan ruang swap.
Saya juga memperhatikan klaim umum bahwa "pertukaran oportunistik" terjadi "selama waktu menganggur". Saya mengerti itu seharusnya membantu meyakinkan saya bahwa fitur ini umumnya baik untuk kinerja. Saya tidak memasukkan ini dalam definisi saya di atas, karena saya pikir itu sudah memiliki cukup detail untuk membuat pertanyaan yang jelas dan bagus. Saya tidak ingin membuat ini lebih rumit dari yang seharusnya.
Motivasi asli
di atas menunjukkan `swout` (swapping) ketika saya memiliki gigabyte memori bebas. Mengapa?
Ada beberapa laporan seperti ini, tentang penulisan Linux untuk ditukar ketika ada banyak memori kosong. "Pertukaran oportunistik" mungkin menjelaskan laporan ini. Pada saat yang sama, setidaknya satu penyebab alternatif diusulkan. Sebagai langkah pertama dalam melihat kemungkinan penyebab:Apakah Linux pernah melakukan “pertukaran oportunistik” seperti yang didefinisikan di atas?
Dalam contoh yang saya laporkan, pertanyaannya sekarang telah dijawab. Penyebabnya bukan pertukaran oportunistik.
Jawaban yang Diterima:
Linux tidak melakukan “pertukaran oportunistik” seperti yang didefinisikan dalam pertanyaan ini.
Referensi utama berikut tidak menyebutkan konsep sama sekali:
- Memahami Manajer Memori Virtual Linux. Sebuah buku online oleh Mel Gorman. Ditulis pada tahun 2003, tepat sebelum rilis Linux 2.6.0.
- Dokumentasi/panduan admin/sysctl/vm.rst. Ini adalah dokumentasi utama dari pengaturan yang dapat diatur dari manajemen memori virtual Linux.
Lebih khusus:
10.6 Daemon Halaman Keluar (kswapd)
Secara historis
kswapd
digunakan untuk bangun setiap 10 detik tetapi sekarang hanya dibangunkan oleh pengalokasi halaman fisik ketika jumlah halaman_rendah halaman gratis di suatu zona tercapai. […] Di bawah tekanan memori yang ekstrim, proses akan melakukan pekerjaankswapd
serentak. […]kswapd
terus mengosongkan halaman hingga mencapai tanda air pages_high.
Berdasarkan hal di atas, kami tidak mengharapkan pertukaran apa pun ketika jumlah halaman gratis lebih tinggi dari “tanda air tinggi”.
Kedua, ini memberitahu kita tujuan dari kswapd
adalah membuat lebih banyak halaman gratis.
Ketika kswapd
menulis halaman memori untuk bertukar, segera membebaskan halaman memori. kswapd tidak menyimpan salinan halaman yang ditukar di memori .
Linux 2.6 menggunakan "rmap" untuk membebaskan halaman. Di Linux 2.4, ceritanya lebih kompleks. Saat halaman dibagikan oleh beberapa proses, kswapd tidak dapat segera membebaskannya. Ini adalah sejarah kuno. Semua posting tertaut adalah tentang Linux 2.6 atau lebih tinggi.
pertukaran
Kontrol ini digunakan untuk menentukan seberapa agresif kernel akan menukar
halaman memori. Nilai yang lebih tinggi akan meningkatkan agresivitas, nilai yang lebih rendah
akan menurunkan jumlah swap. Nilai 0 menginstruksikan kernel untuk tidak
memulai swap hingga jumlah halaman yang didukung file dan halaman bebas kurang
dari tanda air tinggi di suatu zona.
Kutipan ini menjelaskan kasus khusus:jika Anda mengonfigurasi swappiness
nilainya menjadi . Dalam hal ini, kita juga tidak boleh mengharapkan pertukaran apa pun sampai jumlah halaman cache turun ke tanda air yang tinggi. Dengan kata lain, kernel akan mencoba membuang hampir semua cache file sebelum mulai bertukar. (Ini mungkin menyebabkan perlambatan besar. Anda perlu memiliki beberapa cache file! Cache file digunakan untuk menyimpan kode dari semua program yang sedang berjalan
Apa tanda airnya?
Kutipan di atas menimbulkan pertanyaan:Seberapa besar reservasi memori "tanda air" di sistem saya? Jawaban:pada sistem "kecil", tanda air zona default mungkin setinggi 3% dari memori. Ini karena perhitungan tanda air “min”. Pada sistem yang lebih besar, proporsi watermark akan lebih kecil, mendekati 0,3% dari memori.
Jadi, jika pertanyaannya adalah tentang sistem dengan memori bebas lebih dari 10%, detail pasti dari logika tanda air ini tidak signifikan.
Tanda air untuk setiap “zona” ditampilkan di /proc/zoneinfo
, seperti yang didokumentasikan dalam proc(5). Kutipan dari info zona saya:
Node 0, zone DMA32
pages free 304988
min 7250
low 9062
high 10874
spanned 1044480
present 888973
managed 872457
protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone Normal
pages free 11977
min 9611
low 12013
high 14415
spanned 1173504
present 1173504
managed 1134236
protection: (0, 0, 0, 0, 0)
"Tanda air" saat ini adalah min
, low
, dan high
. Jika suatu program meminta memori yang cukup untuk mengurangi free
di bawah min
, program memasuki "reklamasi langsung". Program dibuat untuk menunggu sementara kernel mengosongkan memori.
Kami ingin menghindari reklamasi langsung jika memungkinkan. Jadi jika free
akan turun di bawah low
tanda air, kernel membangunkan kswapd
. kswapd
membebaskan memori dengan menukar dan/atau menghapus cache, hingga free
berada di atas high
lagi.
Kualifikasi tambahan:kswapd
juga akan berjalan untuk melindungi jumlah lowmem_reserve penuh, untuk penggunaan kernel lowmem dan DMA. Lowmem_reserve default adalah sekitar 1/256 dari RAM 4GiB pertama (zona DMA32), jadi biasanya sekitar 16MiB.
Komit kode Linux
mm:skala tanda air kswapd sebanding dengan memori
[…]
watermark_scale_factor:
Faktor ini mengontrol agresivitas kswapd. Ini mendefinisikan
jumlah memori yang tersisa di sebuah node/sistem sebelum kswapd dibangunkan dan
berapa banyak memori yang perlu dikosongkan sebelum kswapd kembali tidur.Satuannya dalam pecahan 10.000. Nilai default 10 berarti jarak
antara tanda air adalah 0,1% dari memori yang tersedia di
node/sistem. Nilai maksimumnya adalah 1000, atau 10% dari memori.Tingginya jumlah utas yang memasuki reklamasi langsung (allocstall) atau kswapd
tertidur sebelum waktunya (kswapd_low_wmark_hit_quickly) dapat menunjukkan
bahwa jumlah halaman gratis yang dipertahankan kswapd karena alasan latensi
terlalu kecil untuk alokasi burst terjadi dalam sistem. Kenop ini
kemudian dapat digunakan untuk menyesuaikan agresivitas kswapd.
proc:meminfo:memperkirakan memori yang tersedia secara lebih konservatif
MemAvailable
item di/proc/meminfo
adalah untuk memberi petunjuk kepada pengguna tentang seberapa
banyak memori yang dapat dialokasikan tanpa menyebabkan pertukaran, sehingga mengecualikan
tanda air rendah zona sebagai tidak tersedia untuk ruang pengguna.Namun, untuk alokasi ruang pengguna,
kswapd
akan benar-benar mendapatkan kembali
hingga halaman gratis mencapai kombinasi tanda air tinggi dan
perlindungan lowmem pengalokasi halaman yang menyimpan sejumlah DMA
dan memori DMA32 dari ruang pengguna juga.Kurangi jumlah penuh yang kami tahu tidak tersedia untuk ruang pengguna dari
jumlah halaman gratis saat menghitung MemAvailable.
Kode Linux
Terkadang diklaim bahwa mengubah swappiness
ke akan secara efektif menonaktifkan "pertukaran oportunistik". Ini memberikan jalan investigasi yang menarik. Jika ada sesuatu yang disebut “pertukaran oportunistik”, dan dapat disetel dengan swappiness, maka kita dapat mengejarnya dengan menemukan semua rantai panggilan yang bertuliskan
vm_swappiness
. Perhatikan bahwa kami dapat mengurangi ruang pencarian kami dengan mengasumsikan CONFIG_MEMCG
tidak disetel (yaitu "grup memori" dinonaktifkan). Rantai panggilan berbunyi:
- vm_swappiness
- mem_cgroup_swappiness
- get_scan_count
- shrink_node_memcg
- shrink_node
shrink_node_memcg
dikomentari “Ini adalah halaman per-node dasar yang lebih bebas. Digunakan oleh kswapd dan reclaim langsung”. Yaitu. fungsi ini meningkatkan jumlah gratis halaman. Itu tidak mencoba menduplikasi halaman untuk ditukar sehingga mereka dapat dibebaskan di lain waktu. Tetapi bahkan jika kita mengabaikannya:
Rantai di atas dipanggil dari tiga fungsi yang berbeda, ditunjukkan di bawah ini. Seperti yang diharapkan, kami dapat membagi situs panggilan menjadi reklamasi langsung vs. kswap. Tidak masuk akal untuk melakukan “pertukaran oportunistik” dalam klaim langsung.
/* * This is the direct reclaim path, for page-allocating processes. We only * try to reclaim pages from zones which will satisfy the caller's allocation * request. * * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ static void shrink_zones
* kswapd shrinks a node of pages that are at or below the highest usable * zone that is currently unbalanced. * * Returns true if kswapd scanned at least the requested number of pages to * reclaim or if the lack of progress was due to pages under writeback. * This is used to determine if the scanning priority needs to be raised. */ static bool kswapd_shrink_node
* For kswapd, balance_pgdat() will reclaim pages across a node from zones * that are eligible for use by the caller until at least one zone is * balanced. * * Returns the order kswapd finished reclaiming at. * * kswapd scans the zones in the highmem->normal->dma direction. It skips * zones which have free_pages > high_wmark_pages(zone), but once a zone is * found to have free_pages <= high_wmark_pages(zone), any page in that zone * or lower is eligible for reclaim until at least one usable zone is * balanced. */ static int balance_pgdat
Jadi, mungkin klaimnya adalah bahwa kswapd entah bagaimana dibangunkan, bahkan ketika semua alokasi memori dipenuhi segera dari memori bebas. Saya memeriksa penggunaan wake_up_interruptible(&pgdat->kswapd_wait)
, dan saya tidak melihat bangun seperti ini.