Fragmentasi memori Linux

20

Apakah ada cara untuk mendeteksi fragmentasi memori di linux? Ini karena pada beberapa server yang berjalan lama saya telah melihat penurunan kinerja dan hanya setelah saya me-restart proses saya melihat kinerja yang lebih baik. Saya lebih memperhatikan ketika menggunakan dukungan halaman besar linux - apakah halaman besar di linux lebih rentan terhadap fragmentasi?

Saya telah melihat / proc / buddyinfo secara khusus. Saya ingin tahu apakah ada cara yang lebih baik (bukan hanya perintah CLI per se, program atau latar belakang teoritis yang akan dilakukan) untuk melihatnya.

Raghu
sumber
Saya tidak melihat solusi commandline cepat saja, program / teori sederhana juga akan melakukan. Oleh karena itu, saya tidak bertanya di serverfault.
Raghu
1
Saya tidak mengerti satu hal di sini. Sejauh yang saya mengerti fragmentasi memori harus menyebabkan kurangnya memori dan sebagai akibat dari kesalahan alokasi memori. Namun Anda bertanya tentang penurunan kinerja. Apakah karena Anda memiliki banyak memori yang ditukar ke disk? Dan jika demikian apa yang memberi vmstatdi lapangan so?
@ skwllsp - Diedit jawaban saya untuk lebih spesifik.
Tim Post
@ Raghu - Saya tidak berharap sebagian besar administrator sistem untuk memodifikasi kode kernel untuk membuat manajemen memori berperilaku berbeda, namun, admin Linux yang terampil harus tahu setidaknya gambaran umum tentang bagaimana Linux mengelola memori. Pertanyaan ini benar-benar di telepon. Saya memilih untuk memigrasikannya hanya karena saya tidak dapat menyarankan kode (dalam jawaban saya) yang menjawab pertanyaan Anda. Membaca dari / proc atau menggunakan vmstatadalah pengalaman pengguna yang umum. Jika Anda menulis program untuk melakukan hal yang sama, itu akan berbeda. Jika Anda berniat menggunakan bash untuk memanen info ini, edit pertanyaan Anda, itu tidak akan ditutup :)
Tim Post
@Tim - Seperti yang saya sarankan bukan hanya perintah bash / cli yang ingin saya ketahui, saya membutuhkan informasi untuk membantu saya dalam prosedur pembandingan (untuk menganalisis hasilnya, bukan untuk menjalankannya).
Raghu

Jawaban:

12

Saya menjawab tag . Jawaban saya hanya khusus untuk Linux .

Ya, halaman besar lebih rentan terhadap fragmentasi. Ada dua tampilan memori, yang proses Anda (virtual) dan yang dikelola kernel (nyata). Semakin besar halaman apa pun, semakin sulit untuk mengelompokkan (dan menyimpannya) dengan tetangganya, terutama ketika layanan Anda berjalan pada sistem yang juga harus mendukung orang lain yang secara default mengalokasikan dan menulis ke memori yang jauh lebih banyak daripada mereka. sebenarnya berakhir menggunakan.

Pemetaan kernel dari alamat (nyata) yang diberikan bersifat pribadi. Ada alasan yang sangat bagus mengapa userspace melihatnya sebagai kernel yang mempresentasikannya, karena kernel harus dapat overcommit tanpa membingungkan userspace. Proses Anda mendapatkan ruang alamat "Disneyfied" yang bagus dan berdekatan tempat untuk bekerja, tanpa mengetahui apa yang sebenarnya dilakukan kernel dengan memori di belakang layar.

Alasan Anda melihat kinerja yang menurun pada server yang berjalan lama kemungkinan besar karena blok yang dialokasikan yang belum dikunci secara eksplisit (misalnya mlock()/ mlockall()atau posix_madvise()) dan tidak dimodifikasi dalam beberapa saat telah dikeluarkan , yang berarti layanan Anda tergelincir ke disk ketika harus membaca mereka. Mengubah perilaku ini membuat proses Anda menjadi tetangga yang buruk , itulah sebabnya banyak orang meletakkan RDBMS mereka di server yang sama sekali berbeda dari web / php / python / ruby ​​/ apa pun. Satu-satunya cara untuk memperbaikinya, secara waras, adalah mengurangi persaingan untuk blok yang berdekatan.

Fragmentasi hanya benar-benar terlihat (dalam kebanyakan kasus) ketika halaman A ada dalam memori dan halaman B telah pindah untuk bertukar. Secara alami, memulai kembali layanan Anda tampaknya akan 'menyembuhkan' ini, tetapi hanya karena kernel belum memiliki kesempatan untuk membatalkan proses '(sekarang) blok-blok yang baru dialokasikan dalam batas rasio overcommit-nya.

Bahkan, memulai kembali (katakanlah) 'apache' di bawah beban tinggi kemungkinan akan mengirim blok yang dimiliki oleh layanan lain langsung ke disk. Jadi ya, 'apache' akan meningkat untuk waktu yang singkat, tetapi 'mysql' mungkin menderita .. setidaknya sampai kernel membuat mereka menderita secara sama ketika hanya ada kekurangan memori fisik yang cukup.

Tambahkan lebih banyak memori, atau pisahkan malloc()konsumen yang menuntut :) Bukan hanya fragmentasi yang perlu Anda perhatikan.

Cobalah vmstatuntuk mendapatkan gambaran umum tentang apa yang sebenarnya disimpan di mana.

Pos Tim
sumber
Terima kasih atas jawabannya. Saya menggunakan halaman besar (masing-masing ukuran = 2048KB) untuk mysql - kumpulan buffer innodb - untuk melihat seberapa bagus tarifnya (menggunakan sysbench). Awalnya ketika proses uptime (dan bahkan system uptime) rendah, itu memberikan hasil yang sangat bagus. Namun, kinerjanya mulai menurun selama beberapa kali proses. Mengenai halaman yang Anda sebutkan, saya pasti melihat aktivitas VM yang tinggi, tapi saya kira itu mungkin karena pembilasan log benchmark dan innodb (aktivitas vm lebih tinggi dengan halaman besar daripada tanpa). Saya juga mengatur vm.swappiness ke 1. Saya tidak bisa melihat adanya perubahan drastis.
Raghu
Menurut manual yang bagus , "Halaman besar tidak dapat ditukar dengan tekanan memori." Saya pikir ini adalah jawaban yang baik dalam memori standar w / r / t tetapi tidak untuk hugepages.
Dan Pritts
5

Inti

Untuk mendapatkan indeks fragmentasi saat ini, gunakan:

sudo cat /sys/kernel/debug/extfrag/extfrag_index

Untuk mendefrag memori kernel coba jalankan:

sysctl vm.compact_memory=1  

Anda juga mencoba mematikan Halaman Besar Transparan (alias THP) dan / atau menonaktifkan swap (atau mengurangi swappiness).

Ruang pengguna

Untuk mengurangi fragmentasi userspace Anda mungkin ingin mencoba pengalokasi yang berbeda, misalnya jemalloc(ia memiliki kemampuan introspeksi yang hebat , yang akan memberi Anda bagian dalam ke dalam fragmentasi internal pengalokasi).

Anda dapat beralih ke malloc kustom dengan mengkompilasi ulang program Anda dengannya atau hanya dengan menjalankan program Anda dengan LD_PRELOAD: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app (waspadalah terhadap interaksi antara THP dan pengalokasi memori memori )

Meskipun, sedikit tidak terkait dengan fragmentasi memori (tetapi terhubung ke pemadatan / migrasi memori), Anda mungkin ingin menjalankan beberapa instance layanan Anda, satu untuk setiap NUMA node dan mengikatnya menggunakan numactl.

SaveTheRbtz
sumber
1
Mengapa Anda berpikir bahwa menonaktifkan swap dapat membantu? Bagi saya kelihatannya lebih besar kemungkinan menonaktifkan swap akan lebih menyakitkan.
kasperd
1
Karena tidak ada informasi yang cukup di posting asli, mungkin proses hanya bocor dan mulai bertukar. Juga saya tidak melihat alasan yang sah untuk menggunakan swap pada hampir semua sistem produksi (mb hanya untuk workstation bersama untuk siswa).
SaveTheRbtz
2
Memiliki ruang swap yang cukup akan meningkatkan kinerja. Masalah kinerja yang akan Anda dapatkan jika ruang swap Anda tidak cukup adalah alasan yang cukup untuk memungkinkan swap.
kasperd
1
@SaveTheRbtz Alasan yang baik untuk menggunakan swap pada sistem produksi adalah karena ia memberi sistem lebih banyak opsi yang hanya akan digunakan jika dianggap menguntungkan. Juga, ini memungkinkan halaman yang dimodifikasi yang belum diakses dalam jam (dan mungkin tidak pernah diakses) dikeluarkan dari memori fisik yang berharga. Terakhir, ini memungkinkan sistem untuk menangani kasus-kasus di mana lebih banyak memori dicadangkan daripada yang digunakan.
David Schwartz
2
"hanya jika dianggap menguntungkan" - yang menambah heuristik tambahan dan membuat sistem kurang dapat diprediksi. Juga algoritma penggantian halaman (digunakan dalam swap dan anonim mmap) yang dilaksanakan berbeda pada kernel yang berbeda (misalnya Linux vs FreeBSD), atau bahkan versi yang berbeda dari OS yang sama (2.6.32 vs 3,2 vs 3,10) .. "itu izin-izin halaman dimodifikasi [. ..] akan dikeluarkan dari [...] memori fisik "- yang akan menyembunyikan kebocoran memori. "menangani kasus-kasus di mana lebih banyak memori dicadangkan daripada digunakan" - sistem lambat jauh lebih buruk daripada sistem turun, jadi "waras" dipertanyakan.
SaveTheRbtz
4

Menggunakan halaman besar seharusnya tidak menyebabkan fragmentasi memori ekstra di Linux; Dukungan Linux untuk halaman besar hanya untuk memori bersama (via shmget atau mmap), dan setiap halaman besar yang digunakan harus secara khusus diminta dan dialokasikan sebelumnya oleh admin sistem. Setelah di memori, mereka disematkan di sana, dan tidak ditukar. Tantangan untuk menukar halaman-halaman besar dalam menghadapi fragmentasi memori adalah persis mengapa mereka tetap tersemat dalam memori (ketika mengalokasikan halaman besar 2MB, kernel harus menemukan 512 halaman 4KB gratis yang berdekatan, yang bahkan mungkin tidak ada).

Dokumentasi Linux pada halaman besar: http://lwn.net/Articles/375098/

Ada satu keadaan di mana fragmentasi memori dapat menyebabkan alokasi halaman besar menjadi lambat (tetapi tidak di mana halaman besar menyebabkan fragmentasi memori), dan itulah jika sistem Anda dikonfigurasi untuk menumbuhkan kumpulan halaman besar jika diminta oleh aplikasi. Jika / proc / sys / vm / nr_overcommit_hugepages lebih besar dari / proc / sys / vm / nr_hugepages, ini mungkin terjadi.

jstultz
sumber
Memang - dan itu umumnya harus membantu kinerja karena akan mencegah kesalahan TLB (lihat artikel terkait untuk penjelasan).
Dan Pritts
0

Ada /proc/buddyinfoyang sangat bermanfaat. Ini lebih berguna dengan format output yang bagus, seperti yang dapat dilakukan skrip Python ini:

https://gist.github.com/labeneator/9574294

Untuk halaman besar Anda ingin beberapa fragmen gratis dalam ukuran 2097152 (2MiB) atau lebih besar. Untuk halaman besar transparan, ia akan memadat secara otomatis ketika kernel diminta untuk beberapa, tetapi jika Anda ingin melihat berapa banyak yang bisa Anda dapatkan, maka sebagai root run:

echo 1 | sudo tee /proc/sys/vm/compact_memory

Juga ya, halaman besar menyebabkan masalah besar bagi fragmentasi. Entah Anda tidak bisa mendapatkan halaman besar, atau kehadirannya menyebabkan kernel menghabiskan banyak waktu ekstra untuk mencoba mendapatkan sebagian.

Saya punya solusi yang berfungsi untuk saya. Saya menggunakannya di beberapa server dan laptop saya. Ini bekerja bagus untuk mesin virtual.

Tambahkan kernelcore=4Gopsi ke baris perintah kernel Linux Anda. Di server saya, saya menggunakan 8G. Berhati-hatilah dengan nomor tersebut, karena itu akan mencegah kernel Anda mengalokasikan apa pun di luar memori itu. Server yang membutuhkan banyak soket buffer atau disk streaming yang menulis ke ratusan drive tidak akan suka dibatasi seperti ini. Setiap alokasi memori yang harus "disematkan" untuk slab atau DMA ada dalam kategori ini.

Semua memori Anda yang lain kemudian menjadi "bergerak" yang artinya dapat dipadatkan menjadi potongan-potongan bagus untuk alokasi halaman yang besar. Sekarang halaman besar transparan benar-benar dapat lepas landas dan berfungsi sebagaimana mestinya. Setiap kali kernel membutuhkan lebih banyak halaman 2M, ia hanya dapat memetakan kembali halaman 4K ke tempat lain.

Dan, saya tidak sepenuhnya yakin bagaimana ini berinteraksi dengan IO langsung zero-copy. Memori di "zona bergerak" tidak seharusnya disematkan, tetapi permintaan IO langsung akan melakukan hal itu untuk DMA. Mungkin menyalinnya. Lagipula itu mungkin menyematkannya di zona bergerak. Dalam kedua kasus itu mungkin bukan yang Anda inginkan.

Zan Lynx
sumber