Mengosongkan objek dalam kode aplikasi atau menutup aliran data sementara tidak selalu mengembalikan RAM fisik ke sistem operasi. Alokator native kustom, runtime pembersihan sampah memori, dan tabel hash alamat terbuka sering kali mempertahankan arena memori virtual yang tetap didukung oleh halaman fisik lama setelah data logis di dalamnya hilang. Demikian pula, membaca atau memetakan memori arsip aset besar akan mengisi cache halaman kernel, yang tetap dibebankan ke grup kontrol memori (memcg) aplikasi Anda.
Halaman ini menjelaskan cara menggunakan panggilan sistem madvise dan posix_fadvise untuk
mengembalikan halaman anonim dan yang didukung file yang tidak digunakan ke OS, sekaligus menjaga reservasi alamat
virtual dan deskriptor file tetap utuh, serta cara memverifikasi dampaknya
di adb shell dan Perfetto.
Alasan dealokasi logis mempertahankan RAM fisik
Kernel Linux melacak memori fisik pada tingkat perincian halaman hardware,
yang berukuran 4 KB atau 16 KB di perangkat Android. Saat
proses mencadangkan region ruang alamat virtual dengan mmap, kernel
membuat area memori virtual (VMA) tanpa mengalokasikan RAM fisik. Kernel
mengalokasikan dan mengisi halaman fisik hanya saat proses pertama kali menyentuh halaman
tersebut. Untuk memori anonim, pembacaan pertama memetakan halaman nol bersama, sehingga hanya operasi tulis yang mengalokasikan RAM.
Setelah halaman mengalami fault ke RAM, kernel tidak mengetahui apakah byte di dalam halaman tersebut masih mewakili objek aktif dalam runtime aplikasi Anda. Dua pola umum membuat halaman fisik tetap berada di memori setelah aplikasi Anda selesai menggunakannya:
- Arena dan kumpulan anonim: Alokator native kustom (seperti alokator slab,
kumpulan, atau arena frame), runtime terkelola dengan ruang heap yang tidak bergerak, dan tabel hash besar mencadangkan rentang alamat virtual yang berdekatan dengan
mmapmenggunakanMAP_PRIVATE | MAP_ANONYMOUS. Saat aplikasi Anda mereset arena, mengosongkan blok kembali ke kumpulan kustom, atau menghapus tabel hash dengan mengosongkan metadatanya, halaman yang mendasarinya tetap kotor. Tanpa petunjuk eksplisit ke kernel, halaman tersebut akan terus dihitung dalam resident set size (RSS) dan proportional set size (PSS) anonim proses Anda dan biaya cgroupmemory.current-nya. Di bawah tekanan memori, kernel mengompresinya ke dalam ZRAM, tempat halaman tersebut masih menempati ruang swap yang dibebankan kememory.swap.current. - Cache halaman yang didukung file dari streaming aset: Saat aplikasi Anda membaca
paket aset besar, arsip level, penampung media, atau model machine learning
menggunakan
read,pread, ataummapyang didukung file, kernel akan meng-cache setiap halaman yang dibaca di cache halaman dan mengenakan biaya halaman tersebut ke penghitungfiledi filememory.statcgroup proses Anda. Jika aplikasi Anda mendekompresi atau menyalin aset tersebut ke dalam buffer runtime anonim atau menguploadnya ke GPU, menyimpan halaman file mentah di cache halaman akan menduplikasi aset di RAM.
Merilis halaman anonim
Panggilan sistem madvise memberikan saran kepada kernel tentang cara proses Anda menggunakan rentang alamat virtual. Untuk pemetaan anonim pribadi (MAP_PRIVATE |
MAP_ANONYMOUS), meneruskan MADV_DONTNEED akan menginstruksikan kernel untuk segera
menghapus halaman fisik dan entri ZRAM yang di-swap yang mendukung rentang
yang selaras dengan halaman yang ditentukan.
Setelah madvise dengan MADV_DONTNEED menampilkan:
- Rentang alamat virtual tetap dicadangkan dan valid di ruang alamat proses Anda (
VmSizetidak berubah), sehingga pointer dan batas arena tetap utuh tanpa memanggilmunmapataummap. - Halaman fisik akan segera dibatalkan pemetaannya dan dikosongkan, sehingga mengurangi
RssAnon,Pss, penghitunganondimemory.stat, danmemory.swap.currentuntuk halaman apa pun yang ada di ZRAM. - Setiap pembacaan atau penulisan berikutnya ke alamat dalam rentang tersebut akan mengalami kesalahan di halaman baru yang diisi nol sesuai permintaan.
| Tanda saran | Pemetaan target | Perilaku kernel di Android |
|---|---|---|
MADV_DONTNEED |
Anonim pribadi (MAP_PRIVATE | MAP_ANONYMOUS) |
Segera menghapus halaman fisik dan slot swap ZRAM. Akses berikutnya
mengalami error di halaman yang diisi nol. Penurunan deterministik dalam
RssAnon dan memory.current. |
MADV_DONTNEED |
Didukung file (MAP_PRIVATE atau MAP_SHARED) |
Membatalkan pemetaan halaman dari tabel halaman proses (RssFile
penurunan). Halaman copy-on-write pribadi dalam pemetaan MAP_PRIVATE
akan dihapus, sehingga modifikasi akan hilang dan akses berikutnya akan membaca ulang
file. Halaman MAP_SHARED yang kotor akan ditulis kembali ke penyimpanan
nanti. Halaman bersih tetap berada di cache halaman hingga dihapus. |
MADV_FREE |
Anonim pribadi (MAP_PRIVATE | MAP_ANONYMOUS) |
Menandai halaman sebagai dapat digunakan kembali secara lambat. Kernel mempertahankan halaman di
RssAnon jika tidak ada tekanan memori dan hanya mengklaimnya kembali
saat klaim kembali global atau memcg berjalan. |
MADV_WILLNEED |
Anonim yang didukung file atau di-swap | Memulai readahead asinkron untuk pemetaan yang didukung file, atau membaca halaman anonim yang di-swap kembali dari ZRAM ke cache swap lebih awal. |
Menyelaraskan rentang interior dengan ukuran halaman runtime
madvise beroperasi di seluruh halaman. Fungsi ini memerlukan alamat awal yang selaras dengan halaman dan
membulatkan panjangnya ke batas halaman berikutnya. Jika Anda merilis span di dalam
arena bersama tempat byte di sekitarnya masih menyimpan objek aktif, pembulatan rentang
ke luar dapat mengosongkan alokasi aktif yang berbagi halaman batas.
Selalu buat kueri ukuran halaman runtime dengan sysconf(_SC_PAGESIZE) untuk mendukung perangkat halaman 4 KB dan 16 KB, serta bulatkan alamat awal interior ke batas halaman berikutnya dan alamat akhir interior ke batas halaman sebelumnya. Untuk panduan selengkapnya tentang pengalokasi yang tidak bergantung pada ukuran halaman, lihat
Mengoptimalkan pengalokasi memori kustom.
#include <sys/mman.h>
#include <unistd.h>
#include <cstdint>
// Reclaims physical pages strictly inside [region_start, region_start + length)
// without disturbing live objects on partially occupied boundary pages.
void ReleaseUnusedArenaSpan(void* region_start, size_t length) {
const uintptr_t page_size = static_cast<uintptr_t>(sysconf(_SC_PAGESIZE));
const uintptr_t page_mask = ~(page_size - 1);
const uintptr_t raw_start = reinterpret_cast<uintptr_t>(region_start);
const uintptr_t raw_end = raw_start + length;
// Round start UP and end DOWN so only fully unused pages are discarded.
const uintptr_t aligned_start = (raw_start + page_size - 1) & page_mask;
const uintptr_t aligned_end = raw_end & page_mask;
if (aligned_end > aligned_start) {
madvise(reinterpret_cast<void*>(aligned_start),
aligned_end - aligned_start,
MADV_DONTNEED);
}
}
Saat membuat pemetaan anonim kustom dengan mmap, beri label VMA dengan prctl menggunakan PR_SET_VMA_ANON_NAME sehingga Anda dapat melacak residensinya berdasarkan nama di showmap dan /proc/<pid>/smaps. dumpsys
meminfo menghitung region anonim yang diberi nama kustom di bagian Unknown.
Beberapa kernel lama menyimpan pointer ke nama, bukan menyalinnya, jadi teruskan
string yang tetap valid selama masa aktif pemetaan, seperti literal
string:
#include <sys/mman.h>
#include <sys/prctl.h>
#ifndef PR_SET_VMA
#define PR_SET_VMA 0x53564d41
#define PR_SET_VMA_ANON_NAME 0
#endif
void* ReserveNamedArena(size_t capacity_bytes, const char* arena_name) {
void* ptr = mmap(nullptr, capacity_bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr != MAP_FAILED) {
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME,
reinterpret_cast<unsigned long>(ptr), capacity_bytes,
reinterpret_cast<unsigned long>(arena_name));
}
return ptr;
}
Mengeluarkan halaman cache file
Saat aplikasi Anda membaca data dari deskriptor file, kernel akan meng-cache halaman file di cache halaman untuk mengantisipasi pembacaan di masa mendatang. Meskipun mempercepat akses berulang ke file konfigurasi kecil atau pustaka bersama, hal ini akan merugikan Anda saat melakukan streaming arsip aset besar, paket tekstur, atau potongan audio dan video yang diuraikan sekali dan disimpan dalam bentuk yang didekode di tempat lain.
Panggilan sistem posix_fadvise memungkinkan aplikasi Anda memberi tahu kernel tentang
pola akses file yang diharapkan pada deskriptor file yang terbuka:
POSIX_FADV_DONTNEED: Menginstruksikan kernel bahwa rentang byte yang ditentukan tidak akan diakses dalam waktu dekat. Kernel segera mengeluarkan halaman yang di-cache yang bersih dan tidak dipetakan dalam rentang yang selaras dengan halaman tersebut dari cache halaman, sehingga mengurangi penghitungfiledimemory.statdan biayamemory.currentcgroup Anda.POSIX_FADV_SEQUENTIAL: Menggandakan periode readahead kernel untuk deskriptor file, sehingga meningkatkan throughput saat melakukan streaming arsip besar dari awal hingga akhir. Gabungkan ini denganPOSIX_FADV_DONTNEEDpada potongan berikutnya saat Anda menggunakannya sehingga jejak cache halaman tetap terikat pada jendela geser kecil.POSIX_FADV_RANDOM: Menonaktifkan readahead kernel spekulatif pada deskriptor file. Gunakan ini saat melakukan pencarian sparse yang tidak berdekatan berdasarkan offset byte ke dalam file arsip atau database yang besar sehingga setiap pembacaan kecil tidak menarik halaman yang tidak digunakan yang berdekatan ke dalam cache halaman. Untuk file yang dipetakan memori, panggilmadvisedenganMADV_RANDOMpada pemetaan.
Contoh berikut men-streaming arsip aset besar dalam potongan, sehingga memungkinkan readahead berurutan di awal dan mengeluarkan setiap span yang selaras dengan halaman yang diproses dari cache halaman:
#include <fcntl.h>
#include <unistd.h>
#include <cstdint>
#include <vector>
void StreamAssetArchive(int fd, size_t total_size) {
const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
constexpr size_t kChunkSize = 4 * 1024 * 1024; // 4 MB streaming window
std::vector<uint8_t> buffer(kChunkSize);
// Hint sequential access so the kernel prefetches upcoming chunks.
posix_fadvise(fd, 0, total_size, POSIX_FADV_SEQUENTIAL);
off_t offset = 0;
while (offset < static_cast<off_t>(total_size)) {
ssize_t bytes_read = pread(fd, buffer.data(), buffer.size(), offset);
if (bytes_read <= 0) break;
// Decode or upload buffer[0 .. bytes_read) into runtime structures here.
// Evict full pages that have been completely consumed.
const size_t aligned_len =
(static_cast<size_t>(bytes_read) / page_size) * page_size;
if (aligned_len > 0) {
posix_fadvise(fd, offset, static_cast<off_t>(aligned_len),
POSIX_FADV_DONTNEED);
}
offset += bytes_read;
}
}
Mendapatkan kembali region mmap yang didukung file
Jika aplikasi Anda memetakan file aset besar ke memori dengan mmap, bukan membacanya
dengan pread, memanggil posix_fadvise dengan POSIX_FADV_DONTNEED saja tidak akan
mengeluarkan halaman yang masih dipetakan ke dalam tabel halaman proses Anda. Untuk menghapus
rentang pemetaan file hanya baca yang digunakan tanpa membatalkan pemetaan seluruh VMA:
- Panggil
madvise(addr, length, MADV_DONTNEED)pada rentang alamat virtual yang dipetakan untuk membatalkan pemetaan halaman tersebut dari tabel halaman proses Anda (RssFiledihapus). - Panggil
posix_fadvise(fd, offset, length, POSIX_FADV_DONTNEED)pada offset file yang sesuai sehingga kernel juga mengeluarkan halaman bersih yang tidak dipetakan dari cache halaman (filedalam penurunanmemory.stat).
Mengikuti panduan saran halaman
Terapkan praktik ini saat mengintegrasikan madvise dan posix_fadvise ke dalam
alokator, pemuat aset, dan pengendali siklus proses:
- Mengelompokkan panggilan ke dalam region kasar: Setiap panggilan
madvisemengambil kunci peta memori proses Anda (mmap_lock), menelusuri tabel halaman, dan membatalkan validasi entri buffering lookaside terjemahan (TLB) yang cocok di core CPU lain (dengan petunjuk pemeliharaan TLB siaran di Arm dan interupsi antar-prosesor di x86). Jangan panggilmadvisepada setiap dealokasi kecil. Gabungkan span kosong dan beri tahu kernel dalam potongan berukuran 64 KB hingga 1 MB atau lebih besar, atau sapu span kosong selama batas frame dan transisi latar belakang (onStopdanTRIM_MEMORY_UI_HIDDEN). - Klaim kembali kapasitas kosong dalam tabel hash dan kumpulan: Saat tabel hash, kumpulan objek, atau buffering staging yang besar dihapus setelah transisi scene atau sinkronisasi data, perkecil alokasi pendukungnya atau keluarkan
MADV_DONTNEEDdi seluruh array pendukung yang dihapus. Mempertahankan tabel beralamat terbuka 32 MB yang dialokasikan dengan tombstone akan membuat semua halaman fisik 32 MB dibebankan ke proses Anda. - Menghapus data file kotor sebelum mengeluarkannya:
POSIX_FADV_DONTNEEDhanya mengeluarkan halaman cache halaman yang bersih. Jika aplikasi Anda menulis file sementara atau cache berukuran besar yang tidak akan segera dibaca kembali, panggilfdatasyncsebelumposix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)agar halaman kotor ditulis ke penyimpanan, lalu dihapus dari RAM. - Jangan mengeluarkan kode atau aset bersama yang sering digunakan: Hindari memanggil
POSIX_FADV_DONTNEEDpada DEX, ODEX, VDEX, pustaka bersama (.so), atau aset UI yang diakses berulang kali. Mengeluarkan halaman kode atau halaman aset yang aktif akan memaksa refault penyimpanan sinkron yang menghentikan thread dan meningkatkan tekanan I/O, seperti yang dilaporkan oleh informasi penghentian tekanan (PSI).
Memverifikasi reklamasi halaman di shell
Pastikan madvise dan posix_fadvise mengklaim kembali RAM fisik menggunakan showmap
dan file akuntansi cgroup v2 aplikasi Anda.
Memeriksa ukuran virtual versus fisik dengan showmap
Saat Anda memberi nama arena anonim dengan PR_SET_VMA_ANON_NAME, showmap akan menampilkan
pemesanan virtualnya (virtual size) dan halaman fisik residennya
(RSS dan PSS). Contoh output berikut berasal dari aplikasi contoh MemoryLab
di AOSP, yang memberi nama arenanya memorylab-arena. Ganti com.example.app
dan memorylab-arena dengan nama paket dan nama arena Anda. Sebelum memanggil
madvise dengan MADV_DONTNEED di arena 64 MB yang disentuh, jalankan:
adb shell "showmap \$(pidof com.example.app) | grep -E '^ +virtual|^ +size|memorylab-arena' | head -3"
virtual shared shared private private Anon Shmem File Shared Private
size RSS PSS clean dirty clean dirty swap swapPSS HugePages PmdMapped PmdMapped Hugetlb Hugetlb Locked # object
65536 65536 65536 0 0 0 65536 0 0 0 0 0 0 0 0 1 [anon:memorylab-arena]
Setelah memanggil madvise(arena_ptr, 64 * 1024 * 1024, MADV_DONTNEED), jalankan
showmap lagi:
virtual shared shared private private Anon Shmem File Shared Private
size RSS PSS clean dirty clean dirty swap swapPSS HugePages PmdMapped PmdMapped Hugetlb Hugetlb Locked # object
65536 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 [anon:memorylab-arena]
virtual size tetap di 65536 KB (64 MB), yang mengonfirmasi bahwa
rentang alamat virtual masih dicadangkan, sedangkan RSS, PSS, dan private dirty
turun ke 0 KB.
Memeriksa memory.current dan memory.stat cgroup
Untuk memverifikasi reklamasi halaman anonim dan penghapusan cache halaman yang tidak dipetakan
(yang tidak muncul dalam tabel halaman proses jika dibaca dengan pread), periksa
direktori cgroup v2 proses. Di Android, setiap proses aplikasi memiliki cgroup-nya sendiri
(seperti /sys/fs/cgroup/apps/uid_<UID>/pid_<PID>/, bergantung pada perangkat).
Perintah berikut menemukan direktori dari baris 0:: dari
/proc/<PID>/cgroup dan mencetak penghitung:
adb shell '
PID=$(pidof com.example.app)
CG=/sys/fs/cgroup$(sed -n "s/^0:://p" /proc/$PID/cgroup)
echo "memory.current: $(cat $CG/memory.current)"
echo "memory.swap.current: $(cat $CG/memory.swap.current)"
grep -E "^(anon|file) " $CG/memory.stat
'
Sebelum merilis arena anonim 64 MB dan mengeluarkan file aset yang dipetakan memori 128 MB dari cache halaman:
memory.current: 242962432
memory.swap.current: 16633856
anon 100671488
file 140009472
Segera setelah memanggil madvise dengan MADV_DONTNEED di arena dan di
pemetaan file aset, lalu posix_fadvise dengan POSIX_FADV_DONTNEED di
deskriptor file aset:
memory.current: 41766912
memory.swap.current: 16502784
anon 33722368
file 5914624
anon turun sebesar 64 MB dan file turun sebesar 128 MB, sehingga mengurangi
memory.current sekitar 192 MB tanpa menutup deskriptor file atau
membatalkan pemetaan ruang alamat virtual arena. memory.swap.current hampir tidak
berubah, karena hampir tidak ada halaman arena yang telah ditukar ke ZRAM. Nilai Anda bergantung pada perangkat dan seberapa banyak file yang telah dikeluarkan kernel dengan sendirinya. Untuk mengetahui informasi selengkapnya tentang cara kernel mengisi dan mengklaim kembali memori per cgroup, lihat Klaim kembali memori: penghapusan dan pertukaran.
Menganalisis reklamasi halaman di Perfetto
Perfetto memungkinkan Anda menghubungkan panggilan madvise dan posix_fadvise dengan penghitung
tabel halaman dan cache halaman kernel pada linimasa terpadu.
Merekam aktivitas
Ambil rekaman aktivitas dengan linux.process_stats untuk penghitung proses berkala dan
linux.ftrace untuk peristiwa RSS dan cache halaman real-time, lalu tarik ke
komputer Anda:
adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/page_advice.perfetto-trace <<EOF
buffers: {
size_kb: 65536
fill_policy: RING_BUFFER
}
data_sources: {
config {
name: "linux.process_stats"
process_stats_config {
scan_all_processes_on_start: true
proc_stats_poll_ms: 100
}
}
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "kmem/rss_stat"
ftrace_events: "filemap/mm_filemap_add_to_page_cache"
ftrace_events: "filemap/mm_filemap_delete_from_page_cache"
}
}
}
duration_ms: 20000
EOF
adb pull /data/misc/perfetto-traces/page_advice.perfetto-trace
Memeriksa jalur di UI Perfetto
Buka rekaman aktivitas di UI Perfetto, luaskan grup proses aplikasi Anda, dan sematkan jalur penghitung berikut agar tetap berada di bagian atas linimasa:
mem.virt: Tetap datar di seluruh panggilanMADV_DONTNEED, yang mengonfirmasi bahwa reservasi alamat virtual (mmap) tidak berubah.mem.rss.anon: Turun tajam pada stempel waktu yang tepat saat aplikasi Anda memanggilmadvisedenganMADV_DONTNEEDdi arena anonim yang kotor atau region heap.mem.rss.file: Turun saat aplikasi Anda memanggilmadvisedenganMADV_DONTNEEDdi regionmmapyang didukung file, disertai dengan burst peristiwa ftracemm_filemap_delete_from_page_cachesaatposix_fadvisedenganPOSIX_FADV_DONTNEEDmengeluarkan halaman bersih dari cache halaman.mem.swap: Turun saatMADV_DONTNEEDmenghapus halaman anonim yang sebelumnya telah dikompresi ke ZRAM.
Gambar 2 menunjukkan jalur ini untuk aplikasi contoh MemoryLab. Untuk menjelajahi tampilan yang sama, buka rekaman aktivitas contoh di UI Perfetto.
Membuat kueri memori puncak dan akhir dengan PerfettoSQL
Jalankan kueri PerfettoSQL berikut di UI Perfetto (tab Query (SQL)) untuk
membandingkan nilai puncak dan akhir mem.virt, mem.rss.anon,
mem.rss.file, dan mem.swap untuk proses target Anda:
WITH counters AS (
SELECT t.name AS counter_name, c.ts, c.value
FROM counter c
JOIN process_counter_track t ON c.track_id = t.id
JOIN process p USING (upid)
WHERE p.name = 'com.example.app'
AND t.name IN ('mem.virt', 'mem.rss.anon', 'mem.rss.file', 'mem.swap')
)
SELECT
counter_name,
CAST(MAX(value) / 1048576 AS INT) AS peak_mb,
CAST((
SELECT value FROM counters AS last
WHERE last.counter_name = counters.counter_name
ORDER BY ts DESC LIMIT 1
) / 1048576 AS INT) AS final_mb
FROM counters
GROUP BY counter_name
ORDER BY counter_name;
Contoh output untuk rekaman aktivitas pada Gambar 2:
counter_name peak_mb final_mb
mem.rss.anon 111 48
mem.rss.file 212 84
mem.swap 36 36
mem.virt 13952 13952
mem.rss.anon turun sebesar 63 MB dan mem.rss.file turun sebesar 128 MB dari
puncaknya, sedangkan mem.virt berakhir di puncaknya karena pemesanan
virtual tidak berubah.
Menyelesaikan halaman yang dikeluarkan ke file
Peristiwa mm_filemap_add_to_page_cache dan mm_filemap_delete_from_page_cache
mengidentifikasi file berdasarkan nomor inode (i_ino), bukan berdasarkan jalur. Untuk mengonfirmasi
bahwa halaman yang dihapus adalah milik file yang Anda sarankan, hitung penghapusan per
inode:
SELECT
EXTRACT_ARG(arg_set_id, 'i_ino') AS inode,
COUNT(*) AS evicted_pages
FROM ftrace_event
WHERE name = 'mm_filemap_delete_from_page_cache'
GROUP BY inode
ORDER BY evicted_pages DESC
LIMIT 5;
Contoh output untuk rekaman aktivitas pada Gambar 2:
inode evicted_pages
9761 35781
76792192 767
126 668
0 612
11587712 514
Saat perangkat yang merekam rekaman aktivitas masih terhubung, selesaikan setiap inode ke jalur. Nomor inode hanya unik dalam satu sistem file, jadi batasi penelusuran ke sistem file yang menyimpan data aplikasi Anda:
INODE=<inode from the query>
adb shell "find /data -xdev -inum $INODE 2>/dev/null"
Contoh output untuk inode 9761:
/data/user/0/com.android.memorylab/files/asset_pack.bin
/data/data/com.android.memorylab/files/asset_pack.bin
Kedua jalur merujuk ke file yang sama, karena /data/user/0 dan /data/data adalah
dua nama untuk direktori data aplikasi yang sama. Jumlah penghapusan untuk file
aset (35.781 halaman) lebih besar daripada file itu sendiri (32.768 halaman pada
4 KB), karena kswapd telah menghapus sebagian file di bawah tekanan
memori sebelum aplikasi membacanya kembali dan memanggil posix_fadvise.
Untuk skrip yang menyelesaikan banyak inode sekaligus, lihat Menyelesaikan kesalahan pada inode, lalu pada file.
← Interaksi kswapd dan lmkd | ↑ Atas | Proses latar belakang yang ramping →