Linux tidak melakukan "pertukaran oportunistik" seperti yang didefinisikan dalam pertanyaan ini.
Referensi utama berikut tidak menyebutkan konsep sama sekali:
- Memahami Manajer Memori Virtual Linux. Buku online oleh Mel Gorman. Ditulis pada tahun 2003, tepat sebelum peluncuran Linux 2.6.0.
- Dokumentasi/admin-guide/sysctl/vm.rst. Ini adalah dokumentasi utama pengaturan merdu manajemen memori virtual Linux.
Lebih spesifiknya:
10.6 Daemon Pageout (kswapd)
Secara historis
kswapd
digunakan untuk bangun setiap 10 detik tetapi sekarang hanya dibangunkan oleh pengalokasi halaman fisik ketika jumlah pages_low halaman gratis di zona tercapai. [...] Di bawah tekanan memori yang ekstrem, proses akan melakukan pekerjaankswapd
serentak. [...]kswapd
terus mengosongkan halaman hingga tanda air pages_high tercapai.
Berdasarkan hal di atas, kami tidak mengharapkan adanya pertukaran saat 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. Ketika sebuah halaman dibagikan oleh beberapa proses, kswapd tidak dapat segera membebaskannya. Ini adalah sejarah kuno. Semua postingan 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 mengurangi jumlah swap. Nilai 0 menginstruksikan kernel untuk tidak memulai pertukaran hingga jumlah halaman yang didukung file gratis kurang dari tanda air tinggi di suatu zona.
Kutipan ini menjelaskan kasus khusus:jika Anda mengonfigurasi swappiness
nilai menjadi 0
. Dalam hal ini, kita juga tidak boleh berharap adanya pertukaran hingga jumlah halaman cache turun ke tanda air yang tinggi. Dengan kata lain, kernel akan mencoba membuang hampir semua cache file sebelum mulai bertukar. (Ini dapat menyebabkan pelambatan besar-besaran. Anda perlu memiliki beberapa cache file! Cache file digunakan untuk menyimpan kode semua program Anda yang sedang berjalan :-)
Apa itu watermark?
Kutipan di atas menimbulkan pertanyaan:Seberapa besar reservasi memori "watermark" pada 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, watermark akan memiliki proporsi yang 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" individu ditampilkan di /proc/zoneinfo
, seperti yang didokumentasikan dalam proc(5). Ekstrak 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 "pengambilan kembali 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 membuang cache, hingga free
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.
Kode Linux berkomitmen
mm:menskalakan tanda air kswapd sebanding dengan memori
[...]
watermark_scale_factor:
Faktor ini mengontrol agresivitas kswapd. Ini menentukan jumlah memori yang tersisa di node/sistem sebelum kswapd dibangunkan dan berapa banyak memori yang perlu dikosongkan sebelum kswapd kembali ke mode tidur.
Satuannya dalam pecahan 10.000. Nilai default 10 berarti jarak antar watermark adalah 0,1% dari memori yang tersedia di node/sistem. Nilai maksimumnya adalah 1000, atau 10% dari memori.
Tingkat utas yang tinggi memasuki klaim ulang langsung (allocstall) atau kswapdakan tidur sebelum waktunya (kswapd_low_wmark_hit_quickly) dapat menunjukkan bahwa jumlah halaman gratis yang dipertahankan kswapd karena alasan latensi terlalu kecil untuk semburan alokasi yang terjadi di sistem. Kenop ini kemudian dapat digunakan untuk menyetel agresivitas kswapd yang sesuai.
proc:meminfo:perkirakan memori yang tersedia dengan lebih konservatif
MemAvailable
item di/proc/meminfo
adalah memberi petunjuk kepada pengguna tentang berapa banyak memori yang dapat dialokasikan tanpa menyebabkan pertukaran, sehingga mengecualikan watermark rendah zona sebagai tidak tersedia untuk ruang pengguna.Namun, untuk alokasi ruang pengguna,
kswapd
benar-benar akan diklaim ulang sampai halaman gratis mencapai kombinasi tanda air tinggi dan perlindungan memori rendah pengalokasi halaman yang juga menyimpan sejumlah memori DMA dan DMA32 dari ruang pengguna.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 0
akan secara efektif menonaktifkan "pertukaran oportunistik". Ini memberikan jalan investigasi yang menarik. Jika ada sesuatu yang disebut "pertukaran oportunistik", dan itu dapat disetel dengan pertukaran, maka kita dapat mengejarnya dengan menemukan semua rantai panggilan yang membaca vm_swappiness
. Perhatikan bahwa kita dapat mengurangi ruang pencarian 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 klaim ulang langsung". Yaitu. fungsi ini meningkatkan jumlah gratis halaman. Itu tidak mencoba untuk menggandakan halaman untuk bertukar sehingga mereka dapat dibebaskan di lain waktu. Tetapi meskipun kami mengabaikan itu:
Rantai di atas dipanggil dari tiga fungsi berbeda, ditunjukkan di bawah ini. Seperti yang diharapkan, kami dapat membagi situs panggilan menjadi klaim langsung vs. kswapd. 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 kswapd dibangunkan entah bagaimana, bahkan ketika semua alokasi memori dipenuhi segera dari memori bebas. Saya melihat-lihat penggunaan wake_up_interruptible(&pgdat->kswapd_wait)
, dan saya tidak melihat bangun seperti ini.
Tidak, tidak ada yang namanya pertukaran oportunistik di Linux. Saya telah menghabiskan beberapa waktu melihat masalah ini dan semua sumber (buku teks, email pada daftar email pengembang kernel, kode sumber Linux dan komentar komit, dan beberapa pertukaran Twitter dengan Mel Gorman) memberi tahu saya hal yang sama:Linux hanya mengklaim kembali memori sebagai respons terhadap beberapa bentuk tekanan memori (dengan pengecualian hibernasi yang jelas).
Semua kesalahpahaman populer tentang subjek ini mungkin berasal dari fakta sederhana bahwa Linux tidak dapat menunggu hingga byte terakhir dari memori bebas sebelum mulai bertukar. Diperlukan semacam bantalan untuk melindunginya dari bentuk penipisan memori yang ekstrem, dan ada beberapa merdu yang dapat memengaruhi ukuran bantalan tersebut (mis. vm.min_free_kbytes
). Tapi itu tidak sama dengan "bertukar karena tidak ada yang lebih baik untuk dilakukan".
Sayangnya algoritma reklamasi bingkai halaman telah tumbuh jauh lebih kompleks sehubungan dengan 2.6 (ketika dijelaskan secara rinci dalam buku Mel Gorman), tetapi ide dasarnya kurang lebih sama:reklamasi halaman dipicu oleh alokasi yang gagal, yang kemudian bangun kswapd
atau coba kosongkan halaman secara sinkron (bergantung pada tekanan memori, bendera alokasi, dan faktor lainnya).
Alasan paling jelas mengapa alokasi halaman mungkin mulai gagal dengan sisa memori yang cukup adalah bahwa mereka mungkin meminta memori yang berdekatan sementara pada kenyataannya memori mungkin terlalu terfragmentasi untuk memenuhi permintaan. Secara historis, pengembang kernel Linux berusaha keras untuk menghindari kebutuhan akan alokasi yang berdekatan. Namun demikian, beberapa driver perangkat masih memerlukan itu - baik karena mereka tidak dapat melakukan I/O memori multi halaman (scatter-gather DMA), atau mungkin hanya pengkodean yang ceroboh oleh pengembang driver. Munculnya Halaman Besar Transparan (THP) memberikan alasan lain untuk mengalokasikan memori dalam potongan yang berdekatan secara fisik.
Pemadatan zona, yang diperkenalkan sekitar jangka waktu yang sama, seharusnya membantu mengatasi masalah fragmentasi memori, tetapi tidak selalu menghasilkan efek yang diharapkan.
Ada berbagai vmscan
tracepoints yang dapat membantu memahami apa yang sebenarnya terjadi dalam kasus khusus Anda -- selalu lebih mudah untuk menemukan hal-hal yang Anda perlukan dalam kode kernel Linux saat memiliki kumpulan panggilan tertentu, daripada hanya memindai semua yang terlihat relevan dari jarak jauh.